エンティティビューコンポーネント
はじめに
エンティティビューフレームワークは、エンティティのシミュレーション内部をビュー側のコードに迅速にバインドすることを目的として設計されました。これは、MonoBehaviourのようなシンプルなエンティティコンポーネントシステムであり、Quantumエンティティビュー用のものです。
QuantumEntityViewComponent
クラスを継承したスクリプトをエンティティビューの下にある任意のゲームオブジェクトに追加することで、スクリプトは即座にEntityRef
、Game
、PredictedFrame
、およびVerifiedFrame
にアクセスでき、さまざまなオーバーライド可能な仮想メソッドを使用できます。
すべてのビューコンポーネントはQuantumEntityViewUpdater
(EVU)にバンドルされ、そこから更新されます。
ビューコンポーネントはQuantumEntityViewPool
ともうまく連携します。
ライフタイム
以下のコールバックは、(プールされた)エンティティビューとそのQuantumViewComponents
のライフサイクルを定義します。
OnInitialize() |
エンティティビューコンポーネントが初めて作成されるときに呼び出されます。ビューコンテキストはすでに設定されていますが、Game 、VerifiedFrame 、PredictedFrame およびPredictedPreviousFrame へのアクセスはまだ利用できません。 |
OnActivate(Frame frame) |
エンティティビューが作成または有効になったとき(プールからの場合も含む)に呼び出されます。例えば、新しいQuantumエンティティが作成され、EVUが関連するEntityViewを作成したときです。 |
OnDeactivate() |
エンティティビューが非アクティブ化される前、つまり破棄されるかプールに戻る前に呼び出されます。 |
OnUpdateView() |
Unityの更新時に、EVUのOnObservedGameUpdated() から呼び出されます。 |
OnLateUpdateView() |
EVU内のUnityのLateUpdate()メソッドで呼び出されます。 |
OnGameChanged() |
EVU内で観測されるゲームが変更された後に呼び出されます。 |
コンテキスト
QuantumEntityViewComponent
は、コンテキストオブジェクトに対して1つのオプションのジェネリックタイプを持つように定義することができます。コンテキストオブジェクトは、IQuantumViewContext
から派生したシンプルなクラス(MonoBehaviour、シングルトンなど)が使用できます。ゲームの異なる部分間でデータを共有するためのオプションです。
コンテキストは、QuantumEntityViewUpdater
ゲームオブジェクトの子である必要があり、Awake()
の間に追加されなければ、自動的にロードされてビューコンポーネントで利用できるようにはなりません。
C#
namespace Quantum {
using UnityEngine;
public class MyGameContext : QuantumMonoBehaviour, IQuantumViewContext {
public GameObject Template;
}
}
コンテキストはその後、ViewContext
プロパティを通じてアクセス可能になります。
C#
namespace Quantum {
using UnityEngine;
public class MyViewScript : QuantumEntityViewComponent<MyGameContext> {
GameObject _go;
public override void OnInitialize() {
_go = Instantiate(ViewContext.Template);
}
}
}
ロードされた各コンテキストタイプの辞書には、EVUでアクセスできます: Dictionary<Type, IQuantumViewContext> Context
シーンビューコンポーネント
QuantumSceneViewComponent
は、関連するエンティティを持たないビューコンポーネントです。シーン内の任意のオブジェクトに追加することで、ビューコンポーネントのプロパティにアクセスできますが、QuantumEntityViewUpdater
に明示的に追加する必要があります。
Updater
フィールドを使用してEVUを直接参照することができます。
または、UseFindUpdater
をオンにすると、OnEnable()
中にFindFirstObjectByType()
が実行されますが、これは遅いと見なされることがあります。
ビューアップデーターは、シーンビューコンポーネントを動的に追加および削除することも可能です。OnInitialize()
およびOnDeactivate()
は直ちに呼び出されますが、OnActivate()
は次のUpdateコールに遅延されます。
QuantumEntityViewUpdater.AddViewComponent(IQuantumViewComponent viewComponent)
QuantumEntityViewUpdater.RemoveViewComponent(IQuantumViewComponent viewComponent)
例
キャラクターコントローラーの状態に基づいてキャラクターのアニメーションを設定します。
C#
namespace Quantum {
using UnityEngine;
public class CharacterViewAnimations : QuantumEntityViewComponent {
private Animator _animator;
public override void OnInitialize() {
_animator = GetComponentInChildren<Animator>();
}
public override void OnUpdateView() {
// probably should use RealSpeed, but the variable isn't been written to in the KCC code currently
var kcc = PredictedFrame.Get<KCC>(EntityRef);
var kinematicSpeed = kcc.Data.KinematicVelocity.Magnitude;
_animator.SetFloat("Speed", kinematicSpeed.AsFloat * 10);
_animator.SetBool("Jump", kcc.Data.HasJumped);
_animator.SetBool("FreeFall", !kcc.Data.IsGrounded);
_animator.SetBool("Grounded", kcc.Data.IsGrounded);
}
}
}
カメラ追従動作の例:
C#
// Context, added to QuantumEntityViewUpdater game object
namespace Quantum {
using UnityEngine;
public class CustomViewContext : MonoBehaviour, IQuantumViewContext {
public Camera MyCamera;
}
}
// View component, added to entity prefab (QuantumEntityView)
namespace Quantum {
using UnityEngine;
public class QuantumCameraFollow : QuantumEntityViewComponent<CustomViewContext> {
public Vector3 Offset;
public float LerpSpeed = 4;
private bool _isPlayerLocal;
public override void OnActivate(Frame frame) {
var playerLink = frame.Get<PlayerLink>(EntityRef);
_isPlayerLocal = Game.PlayerIsLocal(playerLink.Player);
}
public override void OnUpdateView() {
if (_isPlayerLocal == false) {
return;
}
var myPosition = transform.position;
var desiredPos = myPosition + Offset;
var currentCameraPos = ViewContext.MyCamera.transform.position;
ViewContext.MyCamera.transform.position = Vector3.Lerp(currentCameraPos, desiredPos, Time.deltaTime * LerpSpeed);
ViewContext.MyCamera.transform.LookAt(transform);
}
}
}
Back to top