This document is about: QUANTUM 3
SWITCH TO

エンティティビューコンポーネント

はじめに

エンティティビューのフレームワークは、シミュレーション内部のエンティティとビュー側のコードを素早くバインドできるように設計されています。これは、Quantumエンティティビュー用のMonoBehaviourのようなものです。

QuantumEntityViewComponentクラスを継承したスクリプトをEntityViewのゲームオブジェクトに追加すると、スクリプトからEntityRefGamePredictedFrameVerifiedFrameを取得したり、様々なオーバーライド可能な仮想メソッドを使用したりできます。

すべてのビューコンポーネントはQuantumEntityViewUpdater(EVU)にまとめられ、そこから更新されます。

ビューコンポーネントはQuantumEntityViewPoolを使用しても正常に動作します。

ライフタイム

以下のコールバックは、(プールされた)エンティティビューとそのQuantumViewComponentsのライフサイクルを定義します。

OnInitialize() エンティティビューコンポーネントが初めて作成される際に呼び出されます。ここでは、ビューコンテキストは既に設定済みですが、GameVerifiedFramePredictedFramePredictedPreviousFrameはまだ取得できません。
OnActivate(Frame frame) エンティティビューの作成/有効(プールからの場合も含む)時に呼び出されます。例えば、新しいQuantumエンティティが作成されて、EVUが関連するEntityViewを作成した際です。
OnDeactivate() エンティティビューが無効化される前、つまり破棄/プールに返却される際に呼び出されます。
OnUpdateView() Unityの更新時に、EVUのOnObservedGameUpdated()から呼び出されます。
OnLateUpdateView() UnityのLateUpdate()メソッドが、EVUで呼び出されます。
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()を実行することもできますが、これは他の方法に比べて遅くなります。

EVUは、シーンビューコンポーネントを動的に追加/削除できます。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() {
      // おそらく実際の速度を使用すべきだが、現在はまだKCCにその変数は用意されていません
      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#

// コンテキスト、QuantumEntityViewUpdaterゲームオブジェクトに追加される
namespace Quantum {
  using UnityEngine;

  public class CustomViewContext : MonoBehaviour, IQuantumViewContext {
    public Camera MyCamera;
  }
}

// ビューコンポーネント、エンティティプレハブ(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