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;
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 f, 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 f, 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 f, ref Filter filter)
{
// gets the input for player 0
var input = f.GetPlayerInput(0);
UpdateShipMovement(f, 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
キーを使用して船を動かせるようになります。
