エンティティビュー
はじめに
**QuantumEntityViews
**は、QuantumのView
コンポーネントを介してEntities
にリンクされています。これは、ビューを表すGameObjectへのAssetRef
を含み、その特定のエンティティのためにインスタンス化されるべきです。UnityでQuantumEntityView
を持つエンティティプロトタイププレハブまたはシーンオブジェクトを設定する際、QuantumのView
コンポーネントはプロトタイプに自動的に記入されます。
![](/docs/img/quantum/v3/manual/entity-view-self.png)
**QuantumEntityViewUpdater
**は、Unity内のすべてのエンティティのビュー側を処理する役割を担っており、シミュレーションからのデータに基づいて関連するエンティティのビューゲームオブジェクトを作成、破棄、更新します。QuantumEntityViewUpdater
スクリプトは、QuantumMapを含むすべてのシーンに追加する必要があります。
**QuantumEntityViewComponents
**を使用して、個々のEntityViewsにビュー関連の機能を追加できます。詳細はEntity View Componentセクションを参照してください。
プール
デフォルトでは、QuantumEntityViewUpdater
はエンティティが作成されるたびに新しいQuantumEntityView
プレハブのインスタンスを作成し、それに応じてビューゲームオブジェクトを破棄します。
エンティティビューのプールを有効にするには、QuantumEntityViewUpdater
ゲームオブジェクトにQuantumEntityViewPool
スクリプトを追加します。このプールはEVUとシームレスに連携し、IQuantumEntityViewPool
インターフェースを使用することでカスタム実装に置き換えることができます。
HidePooledObjectsInHierarchy | トグルをオンにすると、プールされたオブジェクトにHideFlags.HideInHierarchy が設定されます |
ResetGameObjectScale | トグルをオンにすると、オブジェクトのローカルスケールが1にリセットされます |
Precache Items | オブジェクトはAwake() 中にインスタンス化され、プール内で利用可能になります |
QuantumのコールバックやイベントにサブスクライブしているEntityViewsは、以下のいずれかを確実に行う必要があります:
- ゲームオブジェクトがプールに戻される前に、サブスクライブを解除する
- 下記のように
onlyIfActiveAndEnabled
パラメータを有効にする
C#
QuantumEvent.Subscribe<EventPlayerKilled>(this, OnKilled, onlyIfActiveAndEnabled: true);
バインドビヘイビア
UnityのQuantumEntityView
スクリプトには、Bind Behaviour
というプロパティがあり、次のいずれかに設定できます:
Non Verified
: ビューゲームオブジェクトは予測フレーム内で作成できますVerified
: ビューゲームオブジェクトは確認フレーム内でのみ作成できます
Non Verified
を使用することは、エンティティのビューが高頻度でインスタンス化される場合や、ゲームプレイの反応時間メカニクスにより、できるだけ早くプレイヤーの画面に表示する必要がある場合に通常は推奨されます。例えば、高速で進行するシューティングゲームにおける弾丸の作成は、この選択肢を使用すべきです。
一方で、Verified
は主に即座に表示する必要がないエンティティのビューに対して有用であり、確認フレームを待つための小さな遅延が許容できる場合に役立ちます。これは、ミス予測の間にビューオブジェクトを作成/破棄するのを避けるために使われることがあります。プレイ可能なキャラクターエンティティの作成の際に使用する良い例です。
マニュアル廃棄
Manual Disposal
プロパティがオンの場合、QuantumEntityViewUpdater
の破壊メソッドはスキップされます。これにより、QuantumEntityView
のOnEntityDestroyed
コールバックを使用して手動で破棄することや、カスタム破棄イベントを介して破壊することが可能になります。
ビューフラグ
ビューフラグは、エンティティビューの詳細設定を行い、パフォーマンスの調整を可能にします。
| DisableUpdateView | QuantumEntityView.UpdateView()
およびQuantumEntityView.LateUpdateView()
は処理されず、エンティティビューコンポーネントに転送されません。 |
DisableUpdatePosition | エンティティビューの位置更新を完全に無効にします。 |
UseCachedTransform | Transformプロパティを呼び出さず、キャッシュされたトランスフォームを使用してパフォーマンスを向上させます。 |
DisableEntityRefNaming | デフォルトでは、エンティティゲームオブジェクトはそのEntityRef値に似た名前が付けられます。このフラグを設定するとこの動作が無効になります。 |
DisableSearchChildrenForEntityViewComponents | エンティティビューゲームオブジェクトの子オブジェクトからエンティティビューコンポーネントを検索することを無効にします。 |
予測エラー修正
エンティティビューのエラー修正設定を微調整します。各パラメータの詳細な説明は、Unityインスペクターに記載されています。
イベント
エンティティビューの作成(プールからの作成も含む)および破棄にUnityイベントを追加します。UnityEvent<QuantumGame>
を使用します。
![](/docs/img/quantum/v3/manual/entity-view-events.png)
エンティティのテレポート
QuantumEntityView
スクリプトは、デフォルトでエンティティのGameObject
の視覚を補間します。これにより、シミュレーションレート、レンダーレートの違いや、ミス予測におけるエラー修正に対応します。
エンティティを1フレーム内で遠方の位置に移動させる(つまり「テレポート」する)と、シミュレーション内のエンティティデータはターゲット位置に即座にスナップしますが、ビューの補間は数フレームにわたって開始位置と終了位置の間を線形補間するため、視覚的に非常に速く動いているように見えることがあります。これは望ましくありません。
この問題を防ぐために、エンティティの位置が大きく変わる必要がある場合(通常、エンティティが再出現するか、ゲームにテレポート機能がある場合に移動する際)は、transform->Teleport(frame, newPosition);
を使用します。これにより、エンティティビューコンポーネントは自動的に補間されない移動を適用します。
ビューの検索
特定のエンティティのビューを見つけるのは非常に一般的なユースケースです。シミュレーション側はQuantumEntityViews
の存在を認識していないため、EntityRefs
はイベントを介してビューに渡すか、フレームからポーリング(読み取り専用)する必要があります。QuantumEntityViewUpdater
には、特定のEntityRef
のビューを見つけるために使用できるGetView(EntityRef)
関数があります。ビューは辞書にキャッシュされているため、検索は非常に効率的です。
イベントと更新順序
QuantumEntityViewUpdater
のOnObservedGameUpdated
関数は、EntityViews
の作成、破棄、更新を担当しており、イベントが処理される前に呼び出されます。これは、イベント内で破棄されたエンティティが、すでにそのビューを破棄している可能性があることを意味します。
カスタム破棄イベント
一般的なパターンとして、エンティティを破棄したいが、破棄に関する追加情報をビューに渡すイベントを実行したい場合があります。イベントが処理される前にQuantumEntityView
が破棄されないように、そのManual Disposal
フィールドをtrueに設定します。
これにより、ビューは生存し続け、デフォルトでGameObjectを破棄するQuantumEntityViewUpdater
のDestroyEntityViewInstance
関数に渡されることはありません。
これにより、イベントハンドラはまだビューを見つけて、ビューが存在する状態で破棄イベントを実行できます。QuantumEntityView
は手動で清掃する必要があり、破棄するか、オブジェクトプールに戻す必要があります。
AutoFindMapData
QuantumEntityView
を使用しているマップでAutoFindMapData
を有効にする必要があります。これを有効にすると、ビューは対応するMapDataオブジェクトを検索し、マップエンティティとそのビューを一致させます。エンティティを使用しないマップを使用している場合は、MapData
スクリプトが存在しないシーンを可能にするためにこれを無効にしてください。
カスタマイズ
QuantumEntityViewUpdater
は、以下のカスタマイズの可能性を提供します。
Createのオーバーライド
GameObjectsをインスタンス化するのではなく、プールから取得するには、CreateEntityViewInstance
関数をオーバーライドします。この関数には、どのビューを生成するかを示すQuantum.EntityView
パラメータがあります。QuantumEntityView.AssetGuid
を使用してプールされたオブジェクトの辞書のキーとして使うことができます。
C#
protected override QuantumEntityView CreateEntityViewInstance(Quantum.EntityView asset, Vector3? position = null, Quaternion? rotation = null) {
Debug.Assert(asset.View != null);
// view pooling can also be customized by using IQuantumEntityViewPool
EntityView view = _myObjectPool.GetInstance(asset);
view.transform.position = position ?? default;
view.transform.rotation = rotation ?? Quaternion.identity;
return view;
}
CreateEntityViewInstance()
の結果は、OnEntityViewInstantiated()
内でエンティティに割り当てられます。このメソッドも仮想であり、オーバーライドすることができますが、ほとんどの場合、これは必要ありません。オーバーライドする際は、EntityRefの割り当てをそのまま維持することが重要です。
Destroyのオーバーライド
ビューを破棄するのではなく、プールに戻すには、DestroyEntityViewInstance()
をオーバーライドします。
C#
protected virtual void DestroyEntityViewInstance(QuantumEntityView instance) {
_myObjectPool.ReturnInstance(instance);
}
マップエンティティ
マップエンティティの場合、ActivateMapEntityInstance()
はビューをアクティブにする責任があり、必要に応じてカスタムの動作のためにオーバーライドすることができます。
DisableMapEntityInstance()
は呼び出され、デフォルトではGameObjectを無効にします。この関数もカスタムの動作のためにオーバーライドすることができます。