Cinemachine簡介

  • 2020 年 3 月 10 日
  • 筆記

  先貼一下官方的Cinemachine文檔Cinemachine Documentation

簡介

使用

  我們第一次使用Cinemachine時大概是這樣一個流程:

  1. 在需要被控制的Camera上添加一個CinemachineBrain。
  2. 創建一個自己需要的VirtualCamera。
  3. 調整VirturalCamera上的Follow、Look At等參數。
  4. 調整VirtualCamera上Body、Aim對應Component的類型和參數。

3個關鍵類簡介

  1. CinemachineBrain
      CinemachineBrain是掛在相機對象上去真正修改相機位置的腳本。負責通過VirtualCamera來計算真實相機的位置。
  2. VirtualCameraBase
      通過CinemachineCompoent來計算相機位置。
  3. CinemachineComponentBase
      主要分三大類Body、Aim、Noise,分別計算相機的位置、方向、噪音。

執行過程


  簡單說就是CinemachineBrain每幀通過VirtualCamera計算真實相機的位置,並同步到真實相機上。
  真正的數據計算又是通過VirtualCamera上的流水線來計算的。
  這裡只是一個簡化的流程說明,真實計算還有相機切換時的混合、流水線之外的Extension、和CinemachineCore對Cinemachine的全局管理等。

重要腳本

  簡單了解運行流程後,在詳細的說一下這幾個類的實現與功能。

CinemachineBrain

  CinemachineBrain是掛在相機對象上去真正影響相機位置的腳本。主要負責以下三件事:

  • 維護虛擬相機的狀態(主要包括當前Brain受哪個虛擬相機控制、虛擬相機切換時的切換進度、Timeline對Brain的影響)。
  • 通過虛擬相機計算State(虛擬相機通過各種參數計算出來的真實相機的狀態,包括位置、旋轉等)。
  • 將虛擬相機的State同步到真實相機上,可能是多個虛擬相機的State混合後的結果。

重要變量

  1. UpdateMethed
      更新所有與該Brain相關的虛擬相機,主要是計算每個VirtualCamera的State。
    • SmartUpdate:判斷在一定時間(具體是通過UpdateTracker實現的。這個一定時間其實是一個固定的幀數:UpdateStatus.kWindowSize,是個常數30)該虛擬相機的target在fixedUpdate移動次數多還是在lateupdate移動的次數多。來判斷下一段時間用fixedUpdate還是lateUpdate。
    • FixedUpdate:在FixedUpdate之後對虛擬相機進行更新。
    • LateUdpate:在LateUpdate時對虛擬相機進行更新。
  2. BlendUpdateMethod:把VirtualCamera計算的結果同步到CinemachineBrain的時機。
    • FixedUpdate:在FixedUpdate之後對將計算的數據同步到真實相機。
    • LateUdpate:在LateUpdate時計算的數據同步到真實相機。

重要類

  1. BrainFrame
      更新並記錄當前Brain受哪個虛擬相機的的控制、同時計算虛擬相機的切換狀態。
      Brain中的mFrameStack是用來處理多Timeline同時生效的情況。
      FrameStack中的第一個Frame是Brain每幀Tick遊戲中虛擬相機的結果。其他的是TimeLine的。
  2. CinemachineBlend
      相機混合類,用於描述從相機A切換到相機B的過程。
  3. BlendSourceVirtualCamera
      將CinemachineBlend封裝成一個VirtualCamera,可以讓A相機在切換到B相機的過程中又切換到C這種情況有一個平滑的過度。

Tips

  在做一些相機跟隨、3DUI跟隨時,要注意一幀中跟隨對象位置計算、虛擬相機State的計算、State結果同步、3DUI位置計算的順序,否則容易出現相機抖動的問題。
  如果確定相機跟隨的物體運動的時間點,可以選擇LateUpdate或FixedUpdate兩種模式。能省去SmartUpdate時對目標物體的追蹤開銷(就是那個UpdateTracker)。

虛擬相機的基類VirtualCameraBase

  通過流水線的方式調用CinemachineComponent,同時在流水線中插入CinemachineExtension來計算相機的位置,具體是通過掛載的CinemachineComponent和CinemachineExtension來流水線式的計算一個CameraState(包含了位置、旋轉、視角、額外偏移值等數據),通過CinemachineBrain將其中的數據同步到真實相機上。

虛擬相機組件的基類CinemachineComponentBase

  通過VirtualCamera來創建、刪除、調用,主要分三大類Body、Aim、Noise(還有一個Final,很少用)。

  • Body主要用來計算相機的原始位置,也就是state中的RawPosition。
  • Aim主要用來計算相機的原始旋轉,也就是state中的RawRotation。
  • Noise主要用來計算相機的額外偏移值,也就是state中的PositionCorrection和RotationCorrection。

CinemachineExtension

  插入在流水線中間調用,也用於維護CameraState。

CinemachineCore

  一個全局的管理類,保存當前所有有效的CinemachineBrain、VirturalCameraBase對象引用,定義了各種全局類和函數,用於Cinemachine系統的整體調度。

運行過程

CinemachineBrain詳細調用流程

  主要可以分為兩個時間節點和三件事。

  1. 時間節點
    • FixedUpdate之後
    • LateUpdate
  2. 三件事
    • 維護虛擬相機的狀態,永遠在LateUpdate。
    • 通過虛擬相機計算State,根據UpdateMethod的設置,在FixedUpdate之後或LateUpdate。
    • 將虛擬相機的State同步到真實相機上,根據BlendUpdateMethod的設置,在FixedUpdate之後或LateUpdate。

流程:
  用UpdateMethod和BlendUpdateMethod都為LateUpdate時舉例。

Tips

  1. 在更新相機時,會通過UpdateStatus來保證每個相機每幀不會被多次更新。以免造成性能浪費。

VirtualCamera中State計算流程

  先看一下這個流水線在Hierarchy里長什麼樣子。
  把CinemachineCore.sShowHiddenObjects設置為為true,可以看到虛擬相機下有一個cm節點。


  可以看到cm對象上掛了一個CinemachinePipeline腳本和對應的兩個CinemechineComponent。
  CinemachinePipeline並沒有實際的邏輯作用,只是起一個標記作用,代表這個節點是一個Pipeline節點。
  另外兩個CinemachineComponent就是流水線中用於計算State的腳本。
State計算流程:

  State被一環一環的傳遞下去,每一步的計算都依賴於上一步計算出的State結果。
  比如在Aim計算旋轉角度時,就會依賴上一步Body計算出來的位置,以此位置為基礎來計算旋轉。

小結

  這裡只是基本的講了一下Cinemachine的工作流程。沒有深入到每個類型的虛擬相機。但是對基本流程有一個大體的把握後,再去看其他部分應該會輕鬆一點。
  其次我們也了解到Cinemachine的核心工作流並不複雜,就那麼幾步。代碼的複雜度主要集中在各種邊界情況和優化上。比如:

  1. 對相機切換過程中的再次切換,多Timeline情況的處理,使相機的移動總是平滑的。
  2. 在Component的基礎上加入Extensions來增加靈活度。
  3. 增加SmartUpdate來對相機的更新時機做動態調整。
    等等。