你好,我是鄭洪智,你可以叫我大智。
先問你一個問題:播放動畫不想用Animator搞一堆Animator Controller,怎麼做?
Unity老玩家可能會先想到:Legacy Animation組件。也就是原來那個賊簡單的Animation組件,只要把Animation Clip拖上去就能播放的那個。
雖然現在Legacy Animation還能用,而且還有大把的童鞋在用,但並不是一個完美地答案。
你可能會問了:爲什麼呢?用着挺不錯呀,而且也很順手。
Legacy Animation對於程序來說是比較直觀的,但這就意味着沒辦法(很麻煩)使用Mecanim動畫系統的一些高級功能,例如:動畫重定向、Blend Tree、Avatar Mask等功能。
那有沒有既能用到新的Mecanim動畫系統裏的這些新功能,又不用搞那些Animator Controller呢?答案是有的。(小新:都是廢話,沒有的話這篇文章存在的意義是啥???)
下面就要請出這位神祕嘉賓:Playable。Playable是Unity中的一位隱士高人,可能很多同學對他都不瞭解。
Playable是一組API,可以用來組合、混合、修改多個數據源,然後通過一個輸出,將這些數據源處理完的結果播放出來。
這麼說,可能有些難懂。
下面回到最開始的那個問題,用Playable如何解決呢?接下來我們就用Playable API來實現一個Legacy Animation組件。
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;
// 需要同物體上有Animator組件,但是不需要給他賦值Animator Controller
[RequireComponent(typeof(Animator))]
public class PlayAnimationSample : MonoBehaviour
{
public AnimationClip clip;
PlayableGraph playableGraph;
void Start()
{
// 創建一個PlayableGraph並給它命名
playableGraph = PlayableGraph.Create("PlayAnimationSample");
// 創建一個Output節點,類型是Animation,名字是Animation,目標對象是物體上的Animator組件
var playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", GetComponent<Animator>());
// 創建一個動畫剪輯Playable,將clip傳入進去
var clipPlayable = AnimationClipPlayable.Create(playableGraph, clip);
// 將playable連接到output
playableOutput.SetSourcePlayable(clipPlayable);
// 播放這個graph
playableGraph.Play();
}
void OnDisable()
{
// 銷燬所有的Playables和PlayableOutputs
playableGraph.Destroy();
}
}
上面的幾行代碼創建了一個PlayableGraph。運行時你可以在PlayableGraph Visualize(可以在Package Manager中安裝,安裝後在菜單欄Windows > Analysis > Playable Visualizer中打開)中看到它的圖(注意左上角選擇對應名稱的圖):
可以看到這裏有兩個節點:一個Animation clip節點和一個Animation Output節點。這裏實現的功能很簡單,就是播放一個動畫。這是由一個Playable節點形成的一個非常簡單的樹形結構,每一個PlayableOutput都會形成一個樹形結構。
上面的代碼可以使用Playables API中的工具類進行簡化:
using UnityEngine;
using UnityEngine.Playables;
[RequireComponent(typeof(Animator))]
public class PlayAnimationUtilitiesSample : MonoBehaviour
{
public AnimationClip clip;
PlayableGraph playableGraph;
void Start()
{
// 使用AnimationPlayableUtilities中的方法簡化代碼
AnimationPlayableUtilities.PlayClip(GetComponent<Animator>(), clip, out playableGraph);
}
void OnDisable()
{
// 銷燬所有的Playables和PlayableOutputs
playableGraph.Destroy();
}
}
**爲什麼還需要一個Animator組件呢?**因爲在底層,PlayableGraph的AnimationOutput依然是基於Animator組件的,不過你可以不用關心它了。
到這呢,咱們開始的問題已經解答完了。當然了,這是最簡單的播放一個動畫的代碼,更復雜的適合你項目的代碼當然需要你自己擼嘍。
不過下面再稍微拓展一下。
用Playable有什麼好處?
-
Playable結構簡單。
Playable沒有複雜交疊的狀態機。如果只是播放動畫,幾行代碼就夠了,用起來就像舊的Animation組件一樣。如果是複雜的動畫,也可以預先創建好PlayableGraph子圖,在需要時添加到主圖中。 -
Playable可以運行時修改。
Animator狀態機是沒辦法運行時修改的,而且只能使用OverrideController來替換動畫,有時候不太方便。因爲當動畫數量非常多的時候,如果不能動態添加、刪除State,那就需要預先製作一個巨大的狀態機來滿足所有狀態,維護起來非常麻煩。但是Playable API允許你運行時修改動畫的邏輯結構。 -
Playable更加靈活,可以直接控制動畫各種屬性。
Animator中是通過變量來間接控制權重的,而Playable中,你可以直接控制動畫的權重和時間。不過需要注意的是,雖然這樣很靈活,但是大多數情況下沒有Animator的變量控制方便。 -
Playable有強大的混合(blend)能力
使用Playable不僅能在兩個Animation Clip之間混合,還能在Clip和Animator Controller之間混合,甚至多個Animator Controller之間混合。在Animator中,兩個State Machine之間是不能過渡的,但是使用Playable就可以。還可以同時使用狀態機和Playable,固定的動畫狀態轉換用狀態機,需要動態變化的使用Playable。
PlayableGraph的基本結構
PlayableGraph主要由兩部分組成:各種Playables和PlayableOutput。這些元素組成的那個抽象的圖就叫PlayableGraph。
Playables是基本組成元素。Playable Output是每個Graph必須的組成元素,至少需要一個。而且Playable Output必須連接至少一個Playable,否則是沒有任何作用的。
爲了避免GC,所有類型都是使用struct實現的。
構建PlayableGraph一般有如下的流程:
- 創建一個PlayableGraph,方法是
PlayableGraph.Create("graph的名字")
- 創建輸出節點,常用的有
AnimationPlayableOutput.Create(playableGraph, "name", GetComponent<Animator>());
AudioPlayableOutput.Create(playableGraph, "name", GetComponent<AudioSource>());
- 還可以創建自定義的輸出節點
- 創建各種playables。所有的Playable都有一個靜態的
Create()
方法,用來創建playable實例。需要注意的是自定義的PlayableBehaviour需要使用ScriptPlayable<T>.Create(playableGraph);
來創建。AnimationClipPlayable.Create(playableGraph, animationClip);
AudioClipPlayable.Create(playableGraph, audioClip, true);
ScriptPlayable<T>.Create(playableGraph);
- 連接playable和output:
PlayableOutput.SetSourcePlayable()
- playable之間的連接:
PlayableGraph.Connect()
。 - 播放graph:
PlayableGraph.Play()
- 如果graph不再使用,記得銷燬:
PlayableGraph.Destroy()
。調用這個方法後會銷燬所有的playbles和output。
好了,到這說的差不多了,再多的內容可以等我後續的更新。着急的話可以在Unity文檔或者官方blogs中搜索Playable
。
在使用Timeline時,如果想要擴展Timeline,需要大量用到Payable API。如果你對Timeline和Playable感興趣,可以到洪流學堂公衆號中回覆timeline
,查看該專題所有內容。