Quantum 103 - プレイヤーキャラクター
概要
Quantum 103 では、キャラクタ コントローラを使って移動するキャラクタを紹介します。また、Quantum でゲームプレイのコードを書き始めるための説明もあります。
キャラクタ・エンティティのセットアップ
Game シーンに新しいキャラクタ・コントローラ・エンティティを作成します (Quantum > 3d > Character Controller Entity
)。名前を PlayerCharacter
とし、オブジェクトのトランスフォームを (2, 2, 0) に設定します。
このエンティティは PhysicsCollider3D
が有効になっており、EntityPrototype MonoBehaviour に CharacterController3D
コンポーネントが追加されていることに注意してください。
- CharacterController3Dはキャラクターの動きを制御する。configフィールドはキャラクターコントローラーの動作を微調整するための設定を提供します。デフォルトの設定は、
Resources/DB/Configs
にあります。このチュートリアルでは、デフォルトの設定が使用されます。 - UnityのCharacterControllerとは異なり、Quantumのキャラクターコントローラはコライダーとして動作しません。PhysicsCollider3Dコンポーネントは、エンティティのコライダーとして動作し、ビジュアル球のサイズに合わせます。
エンティティ間で共有されるデータや、コンポーネントデータとは異なり、特定のエンティティに依存しないデータへのアクセスをエンティティに与える必要がある場合があります。Quantumでは、これはアセット設定ファイルによって行われます。設定ファイルは、コードで作成するか、Unity の ScriptableObjects で定義します。キャラクターコントローラには、キャラクターコントローラの動きやインタラクションに関する情報を格納したコンフィグファイルがあります。
プレイモードを押してみてください。ご覧の通り、このエンティティはまだ動いておらず、重力の影響も受けません。キャラクターコントローラを動作させるためには、コードの実装が必要です。
Quantum コード プロジェクトを開く
Quantumのゲームプレイは、quantum_code
というc#プロジェクトで書かれています。プロジェクトを開くには、Visual Studio または Rider の新しいインスタンスを開いてください。
- Visual Studio では
Open a project or solution
を選択してください。 - Rider では
Open
を選択します。
quantum_code
フォルダにある .sln ファイルを検索して選択します。
Visual Studioを使用している場合、.NETフレームワークのバージョンをアップグレードするように指示するポップアップが表示されるかもしれません。推奨されるバージョンをダウンロードするよう選択してください。
Riderを使用する場合、ソリューションを開いた後、ctrl + shift + b
を押してください。エラーメッセージのウィンドウが表示されたら、指示に従ってMicrosoftから.NET Framework Targeting Packをダウンロードしてください。
これで、ゲームプレイコードを書き始める準備ができました。
ゲームプレイコード
ソリューションエクスプローラーでquantum_codeプロジェクトファイルを右クリックし、Add > New Directory
を選択します。ディレクトリ名はPlatformer
とします。
次に、新しく作成した Platformer
フォルダを右クリックします。Add > Class
を選択します。そして、ポップアップで再びクラスを選択し、名前を MoventSystem.cs
に設定して、Add
ボタンをクリックします。
以下のテキストを含むクラスファイルが作成されました。
C#
namespace Quantum.Platformer
{
class MovementSystem
{
}
}
ECSでゲームプレイのコードを書く際に最もよくあるパターンは、コンポーネントのリストを含むエンティティのコレクションをシステムが反復処理することです。Quantum ECSでは、システムのメインスレッドフィルタを使って、これを実現することができます。
まず、MovementSystemクラスにフィルター構造体を追加します。
C#
public struct Filter
{
public EntityRef Entity;
public CharacterController3D* CharacterController;
}
各フィルタには、必ず EntityRef フィールドと、フィルタリングするコンポーネント ポインタ フィールドを任意の数だけ含める必要があります。フィルタのコンポーネントタイプには、常にポインタを使用します。
public
と unsafe
キーワードを追加し、 SystemMainThreadFilter<MovementSystem.Filter>
クラスを継承するようにします。
C#
public unsafe class MovementSystem : SystemMainThreadFilter<MovementSystem.Filter>
Add an override of the abstract Update
function with the following code:
C#
public override void Update(Frame f, ref Filter filter)
{
// note: pointer property access via -> instead of .
filter.CharacterController->Move(f, filter.Entity, default);
}
更新関数は、フィルター内のすべてのコンポーネントを持つ各エンティティについて、各フレームで1回ずつ実行されます。frameパラメータはシステムが動作している現在のフレームを表し、その特定のフレームに対する完全なゲーム状態にアクセスすることができます。
このコードでは、キャラクターコントローラの移動関数を呼び出し、デフォルトのゼロベクターを渡しているだけです。これは、キャラクターコントローラがどの方向にも動こうとせず、エンティティが重力の影響を受けることを意味します。
しかし、このコードはまだ実行されません。システムを動かすには、SystemSetup.cs
ファイルに登録する必要があります。このファイルを開いて、using宣言に以下を追加してください。
C#
using Quantum.Platformer;
その後、user systems go here
のコメントの下に以下の行を追加してください。
C#
// user systems go here
new MovementSystem(),
最後に、Core.CullingSystem2D
、Core.PhysicsSystem2D
、NavigationSystem
を追加する行をコメントアウトします。
Core.NavigationSystem
を追加する行をコメントアウトします。このシリーズで作成されるゲームでは、これらは使用されません。
SystemSetup
ファイルは次のようにします。
C#
using Photon.Deterministic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Quantum.Platformer;
namespace Quantum {
public static class SystemSetup {
public static SystemBase[] CreateSystems(RuntimeConfig gameConfig, SimulationConfig simulationConfig) {
return new SystemBase[] {
// pre-defined core systems
// new Core.CullingSystem2D(),
new Core.CullingSystem3D(),
// new Core.PhysicsSystem2D(),
new Core.PhysicsSystem3D(),
Core.DebugCommand.CreateSystem(),
// new Core.NavigationSystem(),
new Core.EntityPrototypeSystem(),
new Core.PlayerConnectedSystem(),
// user systems go here
new MovementSystem(),
};
}
}
}
SystemSetupに含まれるシステムは、リストアップされた順番に実行されます。
動きの実装を完成させるために、最後のステップが残っています。quantum_code
プロジェクトは別のプロジェクトなので、ビルドする必要があります。ビルド (ctrl + shift + b
) を押してください。
重要: quantum_code
プロジェクトを変更したときは、Unity プロジェクトで変更を反映させるためにビルドする必要があります。
Unityエディタに戻り、プレイモードにします。キャラクター球はKCC重力の影響を受けるようになりましたが、キーボード入力にはまだ反応しません。
入力
Platformer
フォルダを右クリックします。Add > New Item
を選択します。新しいウィンドウがポップアップするので、Visual C# Items > General > Text File
を選択し、ファイル名をInput.qtn
にしてAdd
ボタンをクリックします。
Qtnファイルは、Quantumドメイン固有言語(DSL)を用いたQuantum特有のファイルです。DSLの構文はC#に似ています。DSLはエンティティコンポーネントデータと入力データの定義に使用されます。ゲームプレイ系はC#です。
Input.qtnファイルに以下を追加します。
C#
input
{
button Jump;
FPVector2 Direction;
}
inputはQuantumの特別なキーワードです。Quantum は input sync を使用するので、ゲーム状態ではなく入力だけがネットワーク上に送信されます。ここで定義される input
は、ネットワーク上で送信され、ゲームプレイシミュレーションの入力として使用されるデータです。
注意: 入力はtickごとに送信され、頻繁に変化し、リアルタイムのゲームプレイに影響を与える入力に使用されます。例としては、移動とボタン操作が挙げられます。予測を必要としない不定期なレア入力には、commandsを使用してください。
FPVector2 型は、Unity の Vector2 型と同等の Quantum 型です。Quantum では浮動小数点ではなく固定小数点(FP)を使用し、デバイス間で決定論的なシミュレーションができることを保証しています。方向ベクトルには、後で水平と垂直の入力軸を記入します。
ジャンプボタンは、プレイヤーをジャンプさせるために使用されます。ボタンタイプはQuantum固有のタイプで、すべてのボタン入力に使用する必要があります。ボタン入力にブーリアンは使わないでください。より多くの帯域幅を使用します。
これで入力が定義できたので、build (ctrl + shift + b
) を押してください。これでDSLコンパイラが実行され、C#のクラスで入力が利用できるようになります。
__ 注意:__ DSLファイルのシンタックスハイライトをIDEに追加するには、ガイドここに従ってください。
Movement System を更新する
入力が可能になったので、MovementSystem を開き、Update 関数内のコードを以下のコードに置き換えます。
C#
public override void Update(Frame f, ref Filter filter)
{
// gets the input for player 0
var input = *f.GetPlayerInput(0);
if (input.Jump.WasPressed)
{
filter.CharacterController->Jump(f);
}
filter.CharacterController->Move(f, filter.Entity, input.Direction.XOY);
}
Unity入力の接続
Unityプロジェクト内のPhoton/QuantumDemo/Game/Scripts/LocalInput
スクリプトを開いてください。このスクリプトは、Unityの入力を収集し、Quantumエンジンに渡す役割を担っています。スクリプト内のコードを以下のように置き換えてください。
C#
using Photon.Deterministic;
using Quantum;
using UnityEngine;
public class LocalInput : MonoBehaviour
{
private void Start()
{
QuantumCallback.Subscribe(this, (CallbackPollInput callback) => PollInput(callback));
}
public void PollInput(CallbackPollInput callback)
{
Quantum.Input input = new Quantum.Input();
// Note: Use GetButton not GetButtonDown/Up Quantum calculates up/down itself.
input.Jump = UnityEngine.Input.GetButton("Jump");
var x = UnityEngine.Input.GetAxis("Horizontal");
var y = UnityEngine.Input.GetAxis("Vertical");
// Input that is passed into the simulation needs to be deterministic that's why it's converted to FPVector2.
input.Direction = new Vector2(x, y).ToFPVector2();
callback.SetInput(input, DeterministicInputFlags.Repeatable);
}
}
これで、再びプレイモードに入ると、キャラクターはWASD
キーで移動し、space
キーでジャンプすることができます。