マテリアライゼーション
はじめに
Component Prototype
や Entity Prototype
からエンティティやコンポーネントのインスタンスを生成するプロセスは、マテリアライゼーション と呼ばれます。
マップアセットに組み込まれたシーンプロトタイプのマテリアライゼーションは、Frame.Create
APIを使用してコードで作成されたインスタンスのマテリアライゼーションと同じルールと実行フローに従います。
プロトタイプ vs インスタンス
コンポーネントインスタンスとエンティティインスタンスは、ゲームの状態の一部であり、実行時に操作することができます。DSLで宣言されたコンポーネントは、対応するComponent Prototypes
の生成に使用されます。コードで生成されたプロトタイプは、MyComponent_Prototype
という命名規則に従います。
Component Prototypes
とEntity Prototypes
はどちらもアセットです。これは、ゲームの状態の一部ではなく、実行時では不変であり、すべてのクライアントに対して常に同一でなければならないことを意味します。各 Component Prototype
は ComponentPrototypeRef
を持ち、これは Frame.FindPrototype<MyComponentName_Prototype>(MyComponentPrototypeRef)
を使って、対応するアセットを見つけるのに使用できます。
コンポーネントプロトタイプ
Component Prototype
を拡張して、マテリアライゼーションでは直接使用されないデータを含めることができます。これにより、例えば、特定のコンポーネントのインスタンス間でデータを共有したり、ゲームの状態をコンパクトに保つためにフレームから読み取り専用のデータを除外したりすることができます。
コードで生成されたComponent Prototypes
は、簡単に拡張できる部分クラスです。
MyComponentName_Prototype.cs
というC#ファイルを作成します。- スクリプトの本体を
Quantum.Prototypes
名前空間に置く。 - ( Optional )
using Quantum.Inspector;
を追加して,Manual \ ECS
ページのAttributes
セクションで紹介されているインスペクタの属性にアクセスできるようにします.
これにより、Component Prototype
アセットに追加データを追加したり、パーシャルの MaterializeUser()
メソッドを実装して、カスタムの具現化ロジックを追加することができます。
例
以下の例では、Arcade Racing Template にあるVehicle
コンポーネントのマテリアライゼーションを示します。
Vehicle
コンポーネントは、主に実行時に計算される動的な値を保持します。これらは初期化することができないので、DSLのコンポーネント定義では、これらのパラメータにExcludeFromPrototype
属性を使用して、デザイナーがUnityエディタで操作できる Vehicle_Prototype
アセットから除外しています。Nitro
パラメータは、デザイナーが特定のVehicle
をどのくらいのNitroで初期化するかを決めるために編集できる唯一の部分です。
C#
component Vehicle
{
[ExcludeFromPrototype]
ComponentPrototypeRef Prototype;
[ExcludeFromPrototype]
Byte Flags;
[ExcludeFromPrototype]
FP Speed;
[ExcludeFromPrototype]
FP ForwardSpeed;
[ExcludeFromPrototype]
FPVector3 EngineForce;
[ExcludeFromPrototype]
FP WheelTraction;
[ExcludeFromPrototype]
FPVector3 AvgNormal;
[ExcludeFromPrototype]
array<Wheel>[4] Wheels;
FP Nitro;
}
Vehicle_Prototype
アセットが拡張され、設計者にカスタマイズ可能な読み取り専用のパラメータを提供するようになりました。したがって、Vehicle_Prototype
アセットは、特定の車両エンティティのプロトタイプ "type" のすべてのインスタンスの共有値を保持することができます。Vehicle
コンポーネントのPrototype
パラメータは、ComponentPrototypeRef
というタイプで、コンポーネント固有のAssetRef
に相当します。これを入力するには、パーシャルの MaterializeUser()
メソッドを使用して、Vehicle_Prototype
の参照を割り当てます。
C#
using Photon.Deterministic;
using Quantum.Inspector;
using System;
namespace Quantum.Prototypes
{
public unsafe partial class Vehicle_Prototype
{
// PUBLIC METHODS
[Header("Engine")]
public FP EngineForwardForce = 130;
public FP EngineBackwardForce = 120;
public FPVector3 EngineForcePosition;
public FP ApproximateMaxSpeed = 20;
[Header("Hand Brake")]
public FP HandBrakeStrength = 10;
public FP HandBrakeTractionMultiplier = 1;
[Header("Resistances")]
public FP AirResistance = FP._0_02;
public FP RollingResistance = FP._0_10 * 6;
public FP DownForceFactor = 0;
public FP TractionGripMultiplier = 10;
public FP AirTractionDecreaseSpeed = FP._0_50;
[Header("Axles")]
public AxleSetup FrontAxle = new AxleSetup();
public AxleSetup RearAxle = new AxleSetup();
[Header("Nitro")]
public FP MaxNitro = 100;
public FP NitroForceMultiplier = 2;
// PARTIAL METHODS
partial void MaterializeUser(Frame frame, ref Vehicle result, in PrototypeMaterializationContext context)
{
result.Prototype = context.ComponentPrototypeRef;
}
[Serializable]
public class AxleSetup
{
public FPVector3 PositionOffset;
public FP Width = 1;
public FP SpringForce = 120;
public FP DampingForce = 175;
public FP SuspensionLength = FP._0_10 * 6;
public FP SuspensionOffset = -FP._0_25;
}
}
}
Vehicle_Prototype
のパラメータは、Vehicle
コンポーネントが接続されているエンティティの動作に影響を与えるコンポーネントのインスタンスに見られる動的な値を計算するために必要な値を保持します。例えば、プレイヤーが追加の Nitro
を拾った場合、Vehicle
コンポーネントに保持されている値は、Vehicle_Prototype
にある MaxNitro
の値に固定されます。これにより、非同期化のペナルティによる制限が適用され、ゲームの状態がスリムに保たれます。
C#
namespace Quantum
{
public unsafe partial struct Vehicle
{
public void AddNitro(Frame frame, EntityRef entity, FP amount)
{
var prototype = frame.FindPrototype<Vehicle_Prototype>(Prototype);
Nitro = FPMath.Clamp(Nitro + amount, 0, prototype.MaxNitro);
}
}
}
マテリアライゼーションの順序
シーンプロトタイプを含むすべてのEntity Prototype
は、マテリアライゼーションによって、以下のステップを順に実行します。
- 空のエンティティが作成されます。
Entity Prototype
に含まれる各Component Prototype
に対して、以下の手順を実行します。- コンポーネントのインスタンスをスタック上に作成する。
Component Prototype
がコンポーネントインスタンスに実体化される。- ( Optional )
MaterializeUser()
が呼び出されます。 - コンポーネントがエンティティに追加され、
ISignalOnComponentAdded<MyComponent>
シグナルが発生します。
ISignalOnEntityPrototypeMaterialized
はマテリアライズされた各エンティティに対して呼び出されます。- マップ/シーンの読み込み:すべてのシーンプロトタイプがマテリアライズされた後、すべてのエンティティと
Entity Prototype
のペアに対してシグナルが呼び出されます。 Frame.Create()
で作成された場合:プロトタイプがマテリアライズされた直後にシグナルが発生します。
- マップ/シーンの読み込み:すべてのシーンプロトタイプがマテリアライズされた後、すべてのエンティティと
Component Prototype
マテリアライゼーション手順では、デフォルトのコンポーネントをあらかじめ決められた順序で具体化します。
C#
Transform2D
Transform3D
Transform2DVertical
PhysicsCollider2D
PhysicsBody2D
PhysicsCollider3D
PhysicsBody3D
PhysicsJoints2D
PhysicsJoints3D
PhysicsCallbacks2D
PhysicsCallbacks3D
CharacterController2D
CharacterController3D
NavMeshPathfinder
NavMeshSteeringAgent
NavMeshAvoidanceAgent
NavMeshAvoidanceObstacle
View
MapEntityLink
デフォルトのコンポーネントがすべてマテリアライズされると、ユーザー定義のコンポーネントがアルファベット順に実体化されます。
C#
MyComponentAA
MyComponentBB
MyComponentCC
...
Back to top