1. 程式人生 > >如何中斷Unity動畫狀態機的轉換過程?

如何中斷Unity動畫狀態機的轉換過程?

本文將由Unity工程師Catherine Proulx,為大家深入講解狀態機的轉換和中斷相關的細節。

最近處理了一個使用者報告的很棘手的Bug,這個Bug涉及到空狀態、覆蓋層和轉換中斷的組合。當進一步深入研究這個Bug的時候,我注意到動畫系統文件中關於轉換中斷的描述太抽象了。在和團隊進行深度溝通後,我們決定釋出博文說明一下轉換中斷。

下面我們來深入研究一下狀態機的轉換和中斷的細節。

預設情況下,在動畫系統中,轉換是不能被中斷的:一旦開始由一個狀態轉換為另一個狀態,這個過程沒有出口。就像一個乘坐飛越大西洋航班的乘客,只能舒適的靠在座位上直到抵達目的地,不能改變自己的目的地。對大多數使用者來說,這是好事。

但是如果需要對轉換過程有更多控制,也可以通過使用多種不同方式配置Mecanim來滿足需求。如果對當前目的地不滿意,可以跳到駕駛員的位置在中途改變飛行計劃。這意味著響應動畫更多,同時也意味著很有可能會迷失在這複雜的情況中。

下面通過幾個例子來說明一下。首先是一個簡單的包含4個狀態的狀態機,標記為A到D,並且觸發器都對應了狀態機上的每個轉換。


預設情況下,當觸發了A->B的轉換後,狀態機會將狀態從A轉換為B,並且沒什麼可以阻止它最終變為狀態B。但是如果開啟A->B轉換的檢視面板,並將Interruption Source(中斷源)從“None(無)”變為“Current State(當前狀態)”後,從A到B的這個過程就可以被狀態A的某些觸發器中斷了。


為什麼是“某些”觸發器?因為“Ordered Interruption(順序中斷)”預設情況下是勾選的。這意味著在狀態A的轉換過程中,只有比當前轉換優先順序更高的轉換能夠被執行。通過檢視狀態A的檢視面板可以知道,只有 A->C這個轉換的優先順序比A->B高。



因此如果觸發了A->B,馬上又觸發了A->D,那麼轉換過程不會被中斷。然而如果後觸發的是A->C,那麼A->B的轉換會被馬上中斷並且狀態機會轉換至狀態C。

在內部,動畫系統記錄了中斷髮生時的姿勢,並且將靜態的姿勢(X)和新的目標動畫進行合成。



為什麼是靜態姿勢,而不是在當前轉換和新轉換之間進行可能更流暢的融合?簡單來說:效能原因。當遊戲面臨中斷的級聯時,同時持續追蹤很多正在進行的動態轉換將使得動畫系統不可擴充套件(因為每增加一個新狀態都會消耗更多的系統資源)

現在,如果取消勾選“Ordered Interruption(順序中斷)”,那麼A->C和A->D都可以中斷A->B的轉換。但如果它們在同一幀觸發,那麼A->C仍然會優先執行,因為A->C的優先順序更高。

如果將中斷源改為“Next State(下一狀態)”,A->C和A->D將不再中斷轉換,不論它們的順序如何。但是如果觸發了B->D,則會馬上開始A到D的轉換,並不會完成到B的轉換。

轉換順序對於狀態B來說也很重要。“Ordered Interruption(順序中斷)”的勾選已經不能用了(任何從狀態B觸發的轉換都可以中斷A->B的轉換,因為它們都沒有相對於A->B的優先順序排序),但狀態B的轉換順序會決定在同一幀都被觸發的情況下最終將轉換到哪個狀態。在這個例子中,如果B->D 和 B->C在同一幀觸發了, 則B->D會被選中。


最後,為了實現完全控制,可以將中斷源設定為“Current State Then Next State(先當前狀態再下一狀態)”或者“Next State Then Current State(先下一狀態再當前狀態)”。在這種情況下,轉換會先在一個狀態下獨立分析,然後再到另一個狀態。

所以,如果使用如下配置:



在狀態A到B的轉換過程中,有個很激動的玩家在同一幀觸發了4次轉換:A->C,A->D,B->C,B->D。結果如何呢?

首先,勾選了“Ordered Interruption”,所以可以直接忽視A->D,因為它的優先順序不如A->B高。當前狀態會最先處理,所以不用看A->B了,這裡進行的是A->C的轉換。


但是,相同配置條件下,如果只觸發了B->C和B->D,那就會進行B->D的轉換(它比B->C的優先順序高)。

現在還只是一個轉換,所有其他的轉換也是可能以其特定的規則被中斷的。所以如果讓A->C的轉換從下一個狀態中斷,那可能A->B的轉換會被A->C中斷,而反過來A->C的轉換也可能會被C->D中斷。

有一點很重要,不管中斷在何處發生,原狀態會保持不變直至轉換結束,而Animator.GetCurrentAnimatorStateInfo()將始終返回起始狀態。

簡而言之,狀態轉換的中斷設定非常強大,也提供了極高的靈活性,但也會讓人非常迷惑。所以要明智地使用狀態轉換中斷,有疑問一定要現在編輯器中測試。

轉載:2016-07-23Unity官方Unity官方平臺