エンティティビュー
イントロ
EntityViewUpdater
とEntityView
は、Unityのすべてのエンティティのビュー側の処理を担当します。これらのUnityコンポーネントは、シミュレーションからのデータに基づいて、エンティティのビューゲームオブジェクトの破壊、作成、更新などのロジックを実行します。EntityViewUpdater
はMonoBehavoiur
で、Mapを含むすべてのゲームシーンに存在する必要があります。
組み込みの実装はプロトタイピングや単純なユースケースには十分ですが、多くの場合はカスタム実装が必要になります。EntityViewUpdater
とEntityView
の多くの関数は仮想関数であり、オーバーライドすることができます。また、実装を完全にカスタム実装に置き換えることもできます。EntityViewUpdater
とEntityView
のソースはUnityプロジェクトで公開されています。
EntityViews
は View
Quantum コンポーネントを介して Entities
にリンクされます。このコンポーネントにはエンティティ用にスポーンするビュー GameObject への AssetRef
が含まれています。Unityで EntityPrototype
プレハブやシーンオブジェクトに EntityView
を設定すると、自動的に View
コンポーネントが正しいビューでプロトタイプに保存されます。
EntityView Pooling
デフォルトでは、EntityViewUpdater
はエンティティが作成されるたびにEntityView
プレハブの新しいインスタンスを作成し、エンティティが破棄されるとビューのGameObjectをそれぞれ破棄します。これは特にモバイルプラットフォームではCPU負荷が高くなります。手動でビューをプールすることでGameObjectをプールし、パフォーマンスを向上させることができます。
作成のオーバーライド
GameObjectをインスタンス化する代わりにプールから取得するには、CreateEntityViewInstance
関数をオーバーライドする。この関数には EntityViewAsset
パラメータがあり、スポーンするビューを指定する。EntityView.AssetGuid
はプールされたオブジェクトの辞書のキーとして使用することができます。
実装例
C#
protected override EntityView CreateEntityViewInstance(EntityViewAsset asset, Vector3? position = null, Quaternion? rotation = null) {
Debug.Assert(asset.View != null);
EntityView view = _myObjectPool.GetInstance(asset);
view.transform.position = position ?? default;
view.transform.rotation = rotation ?? Quaternion.identity;
return view;
}
CreateEntityViewInstance
の結果は、OnEntityViewInstantiated
でEntityに割り当てられます。このメソッドも仮想メソッドでオーバーライドすることができますが、ほとんどの場合、オーバーライドする必要はありません。オーバーライドする場合は、EntityRef の割り当てを維持することが重要です。
デストロイのオーバーライド
ビューを破棄せずにプールに戻すには DestroyEntityViewInstance
をオーバーライドします。
*実装例
C#
protected virtual void DestroyEntityViewInstance(EntityView instance) {
_myObjectPool.ReturnInstance(instance);
}
マップエンティティ
マップエンティティでは ActivateMapEntityInstance
がビューをアクティブにします。これはビューのアクティブ化を担当し、必要に応じてカスタム動作のためにオーバーライドできます。
DisableMapEntityInstance
はデフォルトでGameObjectを無効にするために呼ばれます。この関数はカスタムの動作のためにオーバーライドすることができます。
Manual Disposal
EntityView
には Manual Disposal
プロパティがあり、インスペクタで切り替えることができます。有効にすると EntityViewUpdater
の破棄メソッドがスキップされます。これにより、 EntityView
の OnEntityDestroyed
コールバックを使用して手動で破棄したり、カスタムの破棄イベントを使用して破棄することができます。
エンティティビューの検索
非常に一般的なユースケースは、特定のエンティティのビューを見つけることです。シミュレーション側では EntityViews
を認識できないため、イベント経由で EntityRef
をビューに渡す必要があります。EnityViewUpdater
には GetView(EntityRef)
関数があり、これを使用してビューを見つけることができます。ビューは辞書にキャッシュされるので、検索は非常に効率的です。
イベントとEntityViewの更新順序
EntityView
の作成、破棄、更新を行う EntityViewUpdater
の OnUpdateView
関数は、イベントが処理される前に呼び出されます。つまり、イベントの中で破壊されたエンティティは既にビューが破壊されている可能性があります。
カスタムでイベントを破棄
エンティティを破棄しても、破棄に関する追加情報を含むイベントをビューに実行したい場合 があります。イベントが処理される前に EntityView
が破棄されないようにするには、EntityView
に Manual Disposal
を true に設定します。
これにより、デフォルトではGameObjectを破壊する EntityViewUpdater
の DestroyEntityViewInstance
関数に渡す代わりに EntityView
を保持することができます。
それで、イベントハンドラはまだビューを見つけることができ、ビューが存在する状態でdestroyイベントを実行することができる。EntityView
は破棄するかオブジェクトプールに戻すかして手動でクリーンアップする必要があります。
AutoFindMapData
EntityView
を持つマップを使用する場合、AutoFindMapDataを有効にする必要があります。有効にすると、ビューは対応するMapDataオブジェクトを検索し、マップエンティティとそのビューをマッチさせます。MapData
コンポーネントが存在しないシーンを可能にするために、エンティティでマップを使用していない場合は、これを無効にしてください。
カスタム補間とテレポートエントリ
EntityView
コンポーネントはデフォルトでエンティティ GameObject
のビジュアルを補間します。これはシミュレーションレートとレンダリング(更新)レートの差を調整するため、および予測ミスのエラー修正のためです。
大きな距離でエンティティをテレポートする場合、この補間はビューをテレポートするのではなく、開始位置と終了位置の間でビューを補間します。この動作をオーバーライドするには、EntityView
を継承し、ApplyTransform
関数をオーバーライドします。UpdatePostionParameterパラメータ
には、エンティティを表示するために必要なすべての情報が含まれます。param.UninterpolatedPosition
とparam.UninterpolatedRotation
を使用して、カスタム補間を実装し、ビジュアルを正しく表示するためにテレポート中に補間されていない位置にスナップします。
さらに、すべてのエンティティの補間をリセットするために、EntityViewUpdater
にある TeleportAllEntities
を使用することで、マップをリセットする際に、1フレームのすべてのエンティティの補間を無効にすることができます。