一つのアクションを磨き上げる
Ryzeの移動はただ一つ。溜めて投げたパールの着地点へワープすることです。キャラクターコントローラーは小さなステートマシン(接地、エイム中、パール飛行中、リスポーン中)で動いており、状態の切り替わりの瞬間を特に丁寧に作っています。着地直前のボタン入力は先行入力として受け付けます。足場から歩いて落ちると、そのまま落下するのではなくパールに変身します。両足の下のプローブが崖際でふらついている状態を検知し、落ちる前にアニメーションが反応します。
パールは壁で跳ね返り、坂を転がります。遠投ではカメラがパールを追いかけるので、着地点を見失うことはありません。
投げの溜め
ボタンを押し続けると上限まで溜めが増えて高く飛び、上限に達するか落下し始めると自動で投げます。ゲームで最も調整される部分だからこそ、コアループのコードは読みやすさを重視しています。
if (PlayerInput.Shoot.WasPressedThisFrame())
shootPressedAt = Time.unscaledTime;
// A press shortly before landing still counts.
if (CanShoot && Mode != ShootingMode.Aiming
&& PlayerInput.Shoot.IsPressed() && HasBufferedShootPress)
{
shootPressedAt = float.NegativeInfinity;
chargingFX.ChargeShot();
Mode = ShootingMode.Aiming;
}
if (Mode == ShootingMode.Aiming)
{
aimTime += Time.deltaTime * buildUpSpeed;
if (IsFalling || PlayerInput.Shoot.WasReleasedThisFrame()
|| aimTime >= maxBuildUp)
Shoot();
}
すべてのギミックのためのテストレベル
追加したギミックはすべて、一本の長い技術検証用テストレベルに専用の区画を持ちます。コントローラーを変更したら、全ギミックとの組み合わせを1分で確認でき、デザイナーは実際のレベルで使う前に各コンポーネントの動きを単体で確認できます。どれも独立したコンポーネントで、インスペクターから調整できます。
タイムバブルもその一つです。キャラクター、パール、ピストンはそれぞれ独自のタイムライン(Chronosプラグインを利用)で動いているので、バブルは中にあるものすべての速度を変えます。移動も物理もアニメーションも一緒に遅く、または速くなります。
テストレベルで録画。そのほか、動く足場や滑る足場、ピストン、会話トリガー、エリアバナー、日本語テキストの区画があります。
プロジェクトをまたいで使える会話システム
この会話システムは以前のプロジェクトのために作ったもので、中核部分は変えずにRyzeに持ち込みました。それを可能にしたのは、三つの設計判断です。
- UIのことを何も知らない。各セリフはRippleのイベントとして送られます。NPCはそれぞれこのイベントを受け取り、自分のセリフでプレイヤーが近くにいるときだけ吹き出しを表示します。会話のサウンドも同じイベントを受け取ります。新しいプロジェクトでは、表示部分を作るだけで済みます。
- 次のセリフに進むタイミングは呼び出し側が決める。会話の開始は、進む条件を受け取るawait可能な呼び出し一つだけです。トリガー範囲、歩いて近づくカットシーン、同じチェックポイントで失敗を繰り返したときのセリフは、どれもこの呼び出しを包む小さなコンポーネントです。
- 会話はデータ。ライターはセリフと話者をアセットとしてインスペクターで編集し、すべてのセリフに英語の原文にフォールバックする多言語版があります。
Rippleの上に構築
Ryzeのゲーム状態は、自作のScriptableObjectフレームワークRippleで動いています。プレイヤーの表示状態、カメラのターゲット、すべてのゲームプレイイベントがアセットです。システム同士は疎結合のまま、プレイテストで問題が起きればインスペクターで誰が何を変えたかを確認できます。
Idomi Games:Tristan Metz(プログラミング)、Arjen de Aldrey(プログラミング)、Canozalez(レベルデザイン・シナリオ)、Chaos-1001(アート)、Pierre-Henri Barralis(音楽・サウンド)。