Entity View Component
概述
實體視圖框架的設計目的是快速將實體的模擬內部邏輯與視圖端代碼綁定。它是一個簡單的實體元件系統,類似於 MonoBehaviours,但專為 Quantum 實體視圖設計。
透過將衍生自QuantumEntityViewComponent
類別的腳本添加到 EntityView 下的任何遊戲物件,該腳本即可立即存取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
可以定義一個可選的泛型類型,用於上下文物件。上下文物件是一個簡單的類別(可以是 MonoBehaviour、單例等),衍生自IQuantumViewContext
。這是一個在遊戲不同部分之間共享數據的選項。
上下文必須是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()
,可能會被認為是較慢的操作。
ViewUpdater 也允許動態添加和移除場景視圖元件。雖然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