4 - プレイヤーのエンティティ
概要
ここではプレイヤーのエンティティを作成します。また、Quantumでのゲームプレイコードの書き方も説明します。
宇宙船の作成
シーン上の(Quantum > 2D > Quad Entity)から新しいエンティティを作成します。名前はAsteroidsShipにして、Mesh FilterとMesh Rendererコンポーネントを削除してください。
Box ColliderのExtendsは(0.7, 0.9)に調整します。PhysicsBody2Dにチェックを入れて、Angular Dragを6に調整します。
次に船のモデルを作成します。空の子オブジェクトを作成し、名前はModelにします。Modelでは、子オブジェクトで3つのCubeを作成します。各CubeのBox Colliderを削除して、回転を(0, 0, -45)に設定します。
- 1つ目のCubeは、位置を
(0, 0, -0.542)、スケールを(1.2, 0.7, 0.7)に設定 - 2つ目のCubeは、位置を
(0, 0, 0.07)、スケールを(0.6, 0.6, 0.8)に設定 - 3つ目のCubeは、位置を
(0, 0, 0.649)、スケールを(0.3, 0.3, 0.5)に設定
ゲームプレイコード
プロジェクトウインドウのAssets/QuantumUser/Simulationに移動します。ここがすべてのゲームプレイコードを置く場所です。
Simulationフォルダーを右クリックしてCreate > C# Scriptを選択し、名前をAsteroidsShipSystem.csにします。
AsteroidsShipSystem.csをダブルクリックして、IDEを開きましょう。
ファイルを開いたら、すべてのコードを削除して、以下に置き換えましょう。
C#
using UnityEngine.Scripting;
using Photon.Deterministic;
namespace Quantum.Asteroids
{
[Preserve]
public unsafe class AsteroidsShipSystem
{
}
}
ネームスペースは任意で、他の名前を使用できます。Quantumネームスペースを使用しない場合は、コードの先頭にusing Quantum;を追加してください。
unsafeキーワードによって、ポインタなどのunsafeなコードをシステム内で使用できるようにします。
Preserve属性は、すべてのQuantumシステムに追加する必要があります。これによって、Unityのビルドに含まれることを保証し、コードストリッピングで無視されないようにします。
ゲームプレイコードを記述するためのECSの最も一般的なパターンは、一連のコンポーネントを持つエンティティのコレクションを反復するシステムを作成することです。Quantum ECSでは、SystemMainThreadFilterを使用することで実現できます。
最初に、フィルター構造体をAsteroidsShipSystemクラスに追加します。
C#
public struct Filter
{
public EntityRef Entity;
public Transform2D* Transform;
public PhysicsBody2D* Body;
}
各フィルターは、EntityRefフィールドと、フィルタリングしたいコンポーネントのポインタのフィールドを含む必要があります。フィルターのコンポーネント型は必ずポインタを使用してください。
フィルターを追加するために、システムはSystemMainThreadFilter<AsteroidsShipSystem.Filter>クラスを継承します。
C#
[Preserve]
public unsafe class AsteroidsShipSystem : SystemMainThreadFilter<AsteroidsShipSystem.Filter>
以下のコードに従って、抽象関数Updateのオーバーライドを追加します。
C#
public override void Update(Frame frame, ref Filter filter)
{
// note: pointer property access via -> instead of .
filter.Body->AddForce(filter.Transform->Up);
}
Update関数は、フィルターのすべてのコンポーネントを持つ各エンティティにつき、フレーム毎に一度実行されます。Frameパラメーターによって、システムが実行している現在のフレームと、そのフレームにおける完全なゲームステートの取得が可能です。
このコードでは単純に、船に対してUp方向で一定の力を加えています。
ただし、このコードはまだ動作しません。システムを実行するには、システムがSystemConfigアセットに登録されている必要があります。Unityに戻って、新しいSystemConfigアセットを作成(Resourcesフォルダーを右クリックしてCreate > Quantum > Asset.. > SystemConfigを選択)して、アセット名をAsteroidsSystemConfigにします。
アセットには既にEntriesリスト内に定義済みのシステムのリストが入っています。SystemConfig内のシステムは、厳密にリスト順で実行されます。PhysicsSystem3DとCullingSystem3Dなどの3Dシステムは削除してください。また、Navigationシステムはナビメッシュの経路探索で使用されるシステムですが、このゲームでは使用しないので削除しましょう。
リストに新しい項目を追加して、System TypeはQuantum.Asteroids > AsteroidsShipSystemを選択します。
シーン上のQuantumDebugRunnerオブジェクトを選択し、Runtime Config > Systems ConfigのフィールドにSystemConfigをドロップしましょう。
重力の無効化
ゲームを再生すると、船が上昇せずに落下することがわかります。これは重力がまだ有効になっていることが原因です。
PhysicsBodyにかかる重力を無効化する方法は2つあります。
QuantumEntityPrototypeのPhysicsBody2DのGravity Scaleを0に設定する- シミュレーション全体の重力を無効にする
このゲームでは特定の方向の重力は存在しないので、今回は後者のアプローチを使用します。
新しいSimulationConfigアセットを作成(Resourcesフォルダーで右クリックしてCreate > Quantum > Asset.. > SimulationConfigを選択)して、名前はAsteroidsSimulationConfigにします。そこのPhysicsタブのGravityを(0, 0, 0)に設定します。
SimulationConfigアセットは、Quantumのシミュレーションに関する様々な設定が含まれています。このチュートリアルはデフォルト値で十分です。QuantumDebugRunnerのSimulation ConfigフィールドにAsteroidsSimulationConfigをドロップしてください。
再度ゲームを再生すると、船がゆっくりと正常に上昇するようになります。
入力
QuantumUser/Simulationフォルダーを右クリックして、Create > Quantum > Qtnを選択し、ファイル名をInputにします。
Qtnファイルは、Quantumのドメイン固有言語(DSL:Domain Specific Language)を使用するQuantum固有のファイルです。DSLの構文はC#に似ていて、エンティティコンポーネントデータと入力データを定義するために使用されます。ゲームプレイのシステムはC#で記述します。
InputファイルをダブルクリックしてIDEを開き、以下を追加してください。
C#
input {
button Left;
button Right;
button Up;
button Fire;
}
inputはQuantumの特別なキーワードです。Quantumはネットワークを通して入力のみを送信し、ゲームの状態は送信しません。ここで定義されたinputは、ネットワークを通して送信されるデータとなり、ゲームプレイのシミュレーションに使用されます。
備考: 「入力」はティック毎に送信され、頻繁に変わる入力で使用されて、リアルタイムのゲームプレイに影響します。上の例では、移動とボタン押下です。不規則で稀な入力については、コマンドを使用してください。
ジャンプボタンは、プレイヤーをジャンプされるために使用されます。button型はQuantum固有の型で、あらゆるボタン入力で使用します。ブール型は帯域消費が増えるので、ボタン入力には使用しないでください。buttonは1bitでネットワーク通信されます。
備考: DSLファイルに対して、IDEにシンタックスハイライトを追加したい場合は、こちらをご覧ください。
AsteroidsShipSystemの更新
Unityに戻ると、プロジェクトがコンパイルされます。ここでQuantumのコード生成が実行されて、.qtnファイルのInputが、C#スクリプトで使用可能になります。
入力が使用できるようになったので、AsteroidsShipSystemを開き、新しくUpdateShipMovement関数を追加しましょう。
C#
private void UpdateShipMovement(Frame frame, ref Filter filter, Input* input)
{
FP shipAcceleration = 7;
FP turnSpeed = 8;
if (input->Up)
{
filter.Body->AddForce(filter.Transform->Up * shipAcceleration);
}
if (input->Left)
{
filter.Body->AddTorque(turnSpeed);
}
if (input->Right)
{
filter.Body->AddTorque(-turnSpeed);
}
filter.Body->AngularVelocity = FPMath.Clamp(filter.Body->AngularVelocity, -turnSpeed, turnSpeed);
}
FP型はQuantumにおいて、C#のfloat型と同等です。Quantumはfloatのかわりに固定小数点数(FP)を使用することで、クロスプラットフォームの決定論的シミュレーションを保証しています。
次に、Update関数を以下のコードに置き換えます。
C#
public override void Update(Frame frame, ref Filter filter)
{
// gets the input for player 0
var input = frame.GetPlayerInput(0);
UpdateShipMovement(frame, ref filter, input);
}
この関数は、プレイヤー0の入力を取得し、その入力に基づいて船を動かします。コードは後ほど置き換えて、各プレイヤーに対応した船を動かすようにしていきます。
Unityの入力の接続
QuantumUser/Viewフォルダーに、新しくAsteroidsInputスクリプトを作成してください。Viewフォルダーには、Unityから入力を収集してQuantumのシミュレーションに渡すコードのような、Unity側で実行するQuantumのコードを格納します。
Unityプロジェクトでスクリプトを開きます。このスクリプトは、Unityの入力を収集してQuantumエンジンに渡す責務を持ちます。スクリプトのコードを以下のように置き換えてください。
C#
using Photon.Deterministic;
using UnityEngine;
namespace Quantum.Asteroids
{
public class AsteroidsInput : MonoBehaviour
{
private void OnEnable()
{
QuantumCallback.Subscribe(this, (CallbackPollInput callback) => PollInput(callback));
}
public void PollInput(CallbackPollInput callback)
{
Quantum.Input i = new Quantum.Input();
// Note: Use GetKey() instead of GetKeyDown/Up. Quantum calculates up/down internally.
i.Left = UnityEngine.Input.GetKey(KeyCode.A) || UnityEngine.Input.GetKey(KeyCode.LeftArrow);
i.Right = UnityEngine.Input.GetKey(KeyCode.D) || UnityEngine.Input.GetKey(KeyCode.RightArrow);
i.Up = UnityEngine.Input.GetKey(KeyCode.W) || UnityEngine.Input.GetKey(KeyCode.UpArrow);
i.Fire = UnityEngine.Input.GetKey(KeyCode.Space);
callback.SetInput(i, DeterministicInputFlags.Repeatable);
}
}
}
Unityに戻って、シーン上のQuantumDebugInputオブジェクトを選択します。名前をQuantumLocalInputに変更し、QuantumDebugInputスクリプトを削除して、新しくAsteroidsInputスクリプトを追加してください。
次に、QuantumDebugRunnerゲームオブジェクトのインスペクターを開き、Local Playersにプレイヤー項目を追加します。これがQuantumが入力を収集するプレイヤー0になります。ハードコードされた0とシーン上に置かれたプレイヤーは、後ほど動的にプレイヤーエンティティをスポーンするように置き換えます。
プレイヤーのニックネームやアバターは、プレイヤーの追加情報をシミュレーションに渡す際に使用できます。
これでゲームを再生すると、WASDキーを使用して船を動かせるようになります。