Custom Animator
developer@photonengine.com
。概述
Quantum的確定性動畫工具的工作方式是,從Unity的Mecanim控制器來嵌入資訊。它匯入每個設定,比如狀態、狀態之間的轉換、動作片段等等。
使用它的主要優勢 是,它可以控制在不同的機器之間100%同步動畫。如果一個復原告知了在幾個幀之前發生一個轉換,則動畫將貼齊到正確的狀態。所以它提供非常 準確的基於刷新的動畫,其通常是格鬥及一些運動遊戲需要的東西,因為動畫需要在所有客戶端模擬之間準確地同步。
動畫工具不是預設Quantum SDK 2.0版本的一部分,但是它曾經在SDK 1.2.x版本上。但是 我們決定停止改進這個動畫工具,這是因為它目前在Unity的Mecanim上的相依性,以及因為在寫下這份文件的日期時,Unity仍然還沒有啟動任何穩定的動畫工具。請注意,如果您使用工具,您的團隊可能需要基於您的遊戲的動畫需求來改進它。
因此,我們決定將動畫工具作為開源程式碼,您可以將其匯入到您的quantum.code專案,根據您的需要來更改及重新建立它。
這份文件說明了在您自己的專案上應該匯入及使用自訂動畫工具的方式。
本套件最後以Quantum SDK 2.1.0 A1每夜組建版659來進行測試
匯入自訂動畫工具套件
- 在這裡下載自訂動畫工具;
- 解壓縮它並且將資料夾
QuantumCustomAnimator_state
及QuantumCustomAnimator_systems
的內容放在您的quantum.code
專案上的您所希望的位置; - 套件附有一個
Frame.InitUser
方法的部分執行方式,其負責初始化CustomAnimatorUpdater
。如果您的專案已經有一個相同的方法的部分執行方式,請確認在您自己的InitUser
之中包含一個調用到InitializeAnimatorUpdater
方法,並且不要從這個套件來匯入Frame.User.cs
檔案; - 在您的解決方案中包含了所有東西之後,組建您的
quantum.code
專案; - 在Unity上,匯入
QuantumCustomAnimator.unitypackage
檔案到專案;
這樣完成了初始步驟以完全地組建及運行它。現在,為了實際上使用元件、資產及內嵌工具,這裡是指引:
使用自訂動畫工具
- 為了使用元件,您可以直接新增它到一個Unity上的實體原型。另一方面,可以建立一個新的
CustomAnimator
元件的執行個體,並且直接透過程式碼來新增它到您的實體:
C#
var customAnimator = new CustomAnimator();
f.Set(fighter, customAnimator);
- 在Unity上,您將建立一個
CustomAnimatorGraph
類型的新的資料資產。這是負責儲存關於Unity的Mecanim控制器的資料的資產。所以如果您正在使用 實體原型 以設定您的自訂動畫工具,那麼您可以在那裡在AnimatorGraph
欄位上參照動畫工具圖表資產。如果您希望在程式碼上尋找資產,這是方法:
var animatorGraphAsset = f.FindAsset<CustomAnimatorGraph>(assetGuid);
- 初始化自訂動畫工具元件:如果您正在使用實體原型,並且在Unity上您已經定義了上述的自訂動畫工具要使用的自訂動畫工具圖表,那麼您不需要初始化它,因為它已經在
CustomAnimatorSystem
層級上使用一個回應式回調來完成了。但是如果您沒有使用一個實體原型來定義元件,或如果您沒有選擇圖表資產,那麼您可以找到資產,並將其設定到動畫工具,如下所述:
C#
CustomAnimator.SetCustomAnimatorGraph(&knight->CustomAnimator, animatorGraphAsset);
f.Set(fighter, customAnimator);
- 與在Unity上的情況相似,使用取得器及設定器以讀取/寫入動畫工具:
C#
// Getters
CustomAnimator.GetBoolean(frame, &fighter->Animator, "Defending");
CustomAnimator.GetFixedPoint(frame, &fighter->Animator, "Direction");
CustomAnimator.GetInteger(frame, &fighter->Animator, "State");
// Setters
CustomAnimator.SetBoolean(frame, &fighter->Animator, "Defending", true);
CustomAnimator.SetInteger(frame, &fighter->Animator, "Direction", 25);
CustomAnimator.SetFixedPoint(frame, &fighter->Animator, "Speed", FP._1);
CustomAnimator.SetTrigger(frame, &fighter->Animator, "Shoot");
取得器/設定器方法有一系列的方法多載,如果您已經有動畫工具圖表或變數ID,則您可以使用它。這是非常有用的,您可以一次取得動畫工具圖表,並且針對每個取得器/設定器來重新使用它。不然的話,將需要在每一幀時尋找圖表資產。舉例而言:
var animatorGraph = frame.FindAsset<CustomAnimatorGraph>(animator->animatorGraph.Id); CustomAnimator.SetTrigger(frame, animator, animatorGraph, "Shoot"); CustomAnimator.SetFixedPoint(frame, animator, animatorGraph, "Speed", 0); CustomAnimator.SetBoolean(frame, animator, animatorGraph, "Defending", true); // This way you will only need to find the asset one time, instead of 3 times
一個重要的注意事項是,Unity的觸發程序參數 在此的工作方式類似於布林值。所以,為了觸發某些參數,您需要使用
SetBoolean(&fighter→Animator, "MyTrigger", true)
以設定它為真,以及在下一個刷新使用一個SetBoolean(&fighter→Animator, "MyTrigger", false)
,這樣就不會再次啟用觸發程序。套件已經包含了一個在動畫系統之前運行的系統,其在每個刷新時將每個觸發程序參數設定為偽。請插入這個程式碼new CustomAnimatorResetTriggersSystem(),
到您的SystemSetup.cs檔案之中;每個
AnimatorState
都有一個AssetRef
,您可以使用它來參照到自訂資產。您可以在Unity上擴展嵌入流程,從Unity的動畫工具來擷取更多資訊,在您的自訂資產上儲存這些資訊,並且在狀態上參照它,這樣您可以在模擬上讀取它。舉例而言,您可以建立有著以FPAnimationCurves
的形式來嵌入的命中判定/受擊判定的資訊的資產。您可以儲存Unity事件名稱/時間到資產之中,這樣在模擬上您知道某些動畫事件何時發生等等;在您的SystemSetup.cs檔案上,在您自己的系統之後插入這一行程式碼:
C#
new CustomAnimatorSystem(),
- 在Unity上,建立自訂動畫工具圖表資產,從內容選單建立:
Create/Quantum/CustomAnimatorGraph
;
在其預設狀態下,這是它看起來的樣子:
- 使用
Controller
欄位來參照一個Unity的動畫工具控制器資產,並且按下Import Mecanim Controller
按鈕。您隨後應該看到已填入的動畫資訊,比如狀態、轉換、參數等等:
開啟您的
EntityView
層級,並且新增這個欄位:C#
public CustomQuantumAnimator CustomQuantumAnimator;
新增元件
CustomQuantumAnimator
到將加入動畫的遊戲物件。當然,它需要有一個EntityPrefabRoot
在其上,所以使用您按照上述指示建立的欄位,參照到您剛才加入的元件;
- 開啟您的實體檢視更新程式層級,並且在其更新時檢視方法上,它有一個Foreach迴圈,其迭代啟用的檢視。它現在應該包含自訂動畫工具更新,所以您的
foreach
應該看起來如此:
C#
// Iterate over all view instances and update components using only entities from current frame.
foreach (var kvp in _activeViews) {
// ... updates 2D and 3D transforms
// At the end of the foreach, add this.
// This is responsible for actually animating the entity views
if (instance.CustomQuantumAnimator)
{
if (game.Frames.Current.Unsafe.TryGetPointer<CustomAnimator>(instance.EntityRef, out var animator))
{
instance.CustomQuantumAnimator.Animate(game.Frames.Current, animator);
}
}
}
- 最後一步是新增一個Unity的動畫工具元件到您的物件。它可以放在有著
EntityPrefabRoot
的相同的物件上,或是它可以放在一個子物件上:
現在您已經完成了您的Quantum程式碼的替換,在Unity側上需要的替換,並且您有了從一個Unity的Mecanim控制器來直接嵌入資訊的自訂動畫工具圖表,您已經準備好了。
一部分的程式碼已經附有簡單的註解。在Quantum側,您將找到關於內部狀態機器本身的所有東西,比如動畫工具條件,其用於動畫工具轉換,動畫工具變數(參數),圖層,動作等等。
在Unity側,您將找到針對自訂動畫工具圖表資產的繪製自訂編輯器的相關程式碼,以及負責嵌入流程的所有程式碼,您可以擴展這些程式碼,來嵌入更多的資料到您的動畫工具資產中,比如針對碰撞資訊的FPAnimationCurves
,來自Unity的動畫事件等等。
已知問題/限制
預設的自訂動畫工具,有這些已知限制:
- 不支援階層式狀態;
- 不支援Unity的動畫事件;
- 不支援沒有動作的狀態(沒有動畫片段集);
- 不支援圖層選單,這意味著不可以在一個或多個圖層之間混合動畫,比如使用虛擬人偶遮罩,混合等等;
- 當使用混合樹時,對於1D及2D混合樹,混合值強制為[-1, 1]之間;
- 在3D轉換/物理實體上,不支援根動作。