程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> (轉)在Unity3D中控制動畫播放,unity3d動畫播放

(轉)在Unity3D中控制動畫播放,unity3d動畫播放

編輯:C#入門知識

(轉)在Unity3D中控制動畫播放,unity3d動畫播放


用Unity3D也算是好久了,但是每次做項目總還是能學到新的東西。這次做一個TPS的項目就遇到了這樣一個問題,如何同時在上下半身播放不同的動畫?解決方法其實是很簡單,但由於對於動畫資源的了解不足導致問題不斷,最後是徹徹底底的研究了一遍Unity3D的動畫系統(Legacy),雖然4.0出了新的動畫控制系統,使用了一下功能相比原來確實強大不少,但還是將這次對於原先的動畫系統的學習總結記錄下來,畢竟這些動畫的概念與策略是通用的,而且因為4.0在mac上目前貌似還沒有破解所以項目還是得在3.5上做。相信對於深入理解新的動畫系統也會很有幫助。

一、Unity3D動畫系統相關類

1.1 AnimationClip

AnimationClip是Unity3D中播放動畫的最基本對象,通過FBX導入的各個動畫對象其實就是一個AnimationClip。這個類已關鍵幀的形式記錄了骨骼關節在各個時間節點上的位置、旋轉信息,根據幀頻率frameRate結合播放模式wrapMode通過插值計算即可播放出連續的骨骼動畫。

1.2 AnimationState

每個AnimationState包含了一個AnimationClip,並記錄這個動畫片段的一些播放控制屬性,實際上是一個AnimationClip的包裝器。

其中比較重要的參數有layer,weight, enabled, speed, blendMode這幾項。這些參數的具體含義將在自定義混合動畫控制中詳細解釋,在簡單的動畫控制時並不需要對AnimationState進行直接操作。

1.3 Animation

Animation是Unity3D的動畫播放控制組件,包含了一系列的AnimationState對象,提供各種動畫播放及控制方法。常用方法有Play(), CrossFade(), Stop()。在腳本中通過animation即可直接引用同一物體上的Animation控件。

 

二、簡單動畫播放控制

所謂簡單動畫播放控制就是同一時間只有一個動作,比如Standard Assets中的那個水管工,靜止idle,走walk,跑run,跳躍jump,攻擊attack這些動作都是全身動作,同一時間只應該做一種動作,只有在動作切換時需要將兩種切換動作進行混合以達到平滑過渡的效果,以上的操作使用Animation提供的CrossFade()方法即可達到。無論是CrossFade還是Play理論上都只需要在切換動畫時調用一次即可,當然重復的調用並不會影響動畫的播放,當Unity3D檢測到當前播放的動畫與函數調用使用的動畫一樣後會忽略該次調用。

 

三、自定義混合動畫控制

3.1 多動畫同時播放的需求

在大多數情況下簡單的動畫播放控制已經足夠,然而當游戲變得復雜時,單動畫播放帶來的問題就是美術工作量的急劇增加。

最為典型的就是第三人稱射擊(動作)游戲,通常來說游戲中的人物會有各種上身動作如瞄准、射擊、換子彈等,而下身則對應站立,行走(通常還是四個方向的行走動作)。這時候如果只能播放一個動作的話就需要美工制作大量的動作(站立瞄准、站立射擊、跑步瞄准、跑步射擊等等),其工作量可想而知。顯然,最為效率的方式是美工分別做出上半身以及下半身的動作,然後由程序根據游戲角色的操作將兩者動作混合起來同時播放。而這就涉及到了多動畫同時播放的需求。此時簡單的CrossFade()方法已經不能滿足了,我們需要通過AnimationState來對動畫播放進行自定義的控制。

3.2 使用AnimationState控制動畫播放

Unity3D的動畫播放實際上都是通過AnimationState來進行控制的,Animation組件中提供的CrossFade,Play等方法其實就是將一系列對AnimationState參數進行設置的操作進行了封裝。

其中主要相關的參數有四個:

layer: 該動畫片段(AnimationClip)所在的播放層次。

weight: 該動畫片段在動畫混合中所占的權重(0~1)

enable: 該動畫片段是否進行播放

blendMode: 混合方式,有兩種Blend和Additive

默認初始化情況下Animation組件中的全部AnimationState的layer=0,weight=0, enable=false。Animation組件默認播放的AnimationState的layer=0, weight=1, enable=true。

 

一、Unity3D動畫播放策略

Unity3D在進行動畫播放時按照下面的策略進行:

1.找到最高一層的全部AnimationState

2.將其中enable為true且weight > 0的AnimationState中的clip加入混合池(虛構的一個概念)

3.如果當前混合池中全部blendMode為Blend的clip的權重相加少於1,則找到下一層的全部AnimationState。重復2.

4.對混合池中的全部clip進行混合操作,生成最終的動作。

在進行最終混合時所有clip的實際權重會進行歸一化處理,即相加為1,處理時根據blendMode的不同結果也會有所差異,下面的例子會進一步說明。

 

二、使用AnimationState控制播放的實例

舉幾個實際的例子對Unity3D的動畫混合策略進行說明。對於AnimationState的設置全部放在Start或Awake中進行。並且注意把Animation組件中的默認播放動畫設為None,取消選中Player Automatically,原因正如前文所述,默認播放的AnimationState參數初始值與其他State不同,會對實驗造成影響。

1. 同一層動畫的混合播放

AnimationState right= animation[“run_right”];

AnimationState idle= animation[“idle”];

right.layer = 1;right.weight = 1; right.enable = true;

idle = 1; idle.weight= 1; idle.enable = true;

 運行結果是角色動畫介於行走與靜止之間,體現兩個動畫1:1的混合效果

2. 高層動畫覆蓋下層動畫

 right.layer = 1; right.weight = 1;right.enable = true;

idle = 0; idle.weight = 1; idle.enable = true;

 運行結果是角色行走

3. 高層動畫與下層動畫混合

right.layer = 1; right.weight = 0.5f; right.enable = true;

idle = 0; idle.weight = 1; idle.enable = true;

運行結果與1相同,idle的實際weight為1 * (1 – 0.5f)

4. 使用Additive混合不同層動畫

right.layer = 1; right.weight = 1; right.enable = true;

right.blendMode = BlendMode.Addictive;

idle = 0; idle.weight = 1; idle.enable = true;

 運行結果與1相同,idle的實際weight為1/(1+1)

 

三、其他的動畫播放控制參數

speed: 控制動畫播放速度,比如調整射擊速度就是將該值提高

time: 當前動畫所在時間點

warpMode: 動畫循環方式,有一次、循環、鏡像循環PingPong

3.3 自定義動畫過渡

動畫過渡實際上就是兩種動畫混合權重的過渡,前一種動畫的權重由1漸變為0,後一種由0變為1,由此實現動畫的平滑過渡。在實際操作時,並不需要過渡時在Update()中每幀去調整兩種動畫AnimationState的權重weight。Animation控件提供了Blend()方法幫助在後台自動計算這種過渡,其使用方法與CrossFade類似,詳見Unity3D的script手冊。

3.4 Play(), CrossFade()背後的操作

了解這些基本方法背後進行的操作在同時使用AnimationState對動作進行控制時十分有用。

首先是Play(stringanimationName)(Play() = Play(default Animation name))這個方法實際上是將animationName所在層的全部其他AnimationState的weight置為0,enable置為false,將animationName的weight置為1, enable置為true。

CrossFade()與Play()大致相同,只不過他並不直接將其他的AnimationState的weight置為0,而是調用Blend()方法將其向0進行漸變,一旦該AnimationState的weight變為0再將其enable設置為false。

由此可見,當你設置了多層AnimationState後,僅僅調用這兩個方法很可能並不能達到你想要的動畫控制效果。當然,這兩個方法最後有一個默認參數PlayMode來調整執行策略(區別就在於操作對象僅僅在該層還是全部AnimationState對象),總之這一節通過闡述Play與CrossFade背後的操作,希望使我們在使用AnimationState進行混合動畫控制編程時能夠正確的使用這兩個方法以達到期望的效果。

3.5 局部動畫

以上所介紹的AnimationState操作只是多動畫的手動播放及混合控制,還並沒有涉及到如何向開頭所講的上下半身播放不同的動畫。要在同一個角色上同時播放兩個不同的動作使用局部動畫即可。

一、生成局部動畫

在Unity3D中有兩種方式實現局部動畫,一是使用AnimationState的AddMixingTransform方法,該方法傳入一個骨骼節點的Transform,調用後該動畫片段AnimationClip便只會影響該節點及其子骨骼,而對其他骨骼關節並不再影響。

另一種方法是在動畫模型制作時就只對局部的骨骼制作動畫,其他骨骼在整個動畫片段中都保持不變,這樣生成的動畫片段AnimationClip中就不會包括對那些不變骨骼的關鍵幀信息,也就不會對其他骨骼關節進行影響。(這是我根據動畫播放的實際控制結果進行的推測,在Unity3D的官方文檔中好像並沒有直接說明,仍需查證)

了解第二種方法十分重要,雖然還只是推測。因為在與美術溝通前你可能並不知道導入的是一個局部動畫,而將其當成全身動畫,使得在進行動畫混合控制時產生了意想不到的結果。我在一次項目中發現明明角色應該進入idle狀態,但是雙腿仍然在跑動,為此花了兩天時間查證,也是直接促成了這篇文章的誕生,最終發現原來美術給的idle只有上半身有動畫,下半身沒有,因此雖然idle比跑動高一層,但下半身並不能覆蓋。

 

二、局部動畫的混合

局部動畫的混合策略與前述Unity3D動畫播放策略相同,只不過只是影響局部骨骼。這也就是說,上半身與下半身的動畫無論誰所在的層更高,權重多少都不會影響另外半身的動畫播放。但是上層的半身動畫會覆蓋下層的全身動畫或與之混合,而全身動畫中不包含在半身動畫中的骨骼則完全不受影響。

 

四、射擊類游戲應用

參考Unity3.5的官方例子Angry Robot。在這個例子中很好的實現了上下半身的獨立旋轉,射擊動作與跑步動作的半身分離。這一節以此作為樣例進行分析。

動作資源:

run_forward,fun_backward, run_left, run_right。四方向的跑動,全身動作,全部置於第1層。

Idle。靜止,全身動作,位於第2層。

Attack。攻擊,半身動作,位於第4層。混合方式Additive

操作控制:

初始化,全部動作的weight置為1,Attack的enable置為false,其余為true。這樣初始狀態下Attack不播放,Idle覆蓋跑動動作,角色表現為靜止站立動作。

移動時將Idle的weight根據速度向0漸變,開放跑動動作。使用CrossFade()在四個跑動動作中選擇合適的動作進行播放。停止時再將Idle的weight逐漸置為1,重新覆蓋跑動動作。

攻擊時將Attack的enable置為true,停止攻擊時置為false。由於Attack動作在最高層,且混合模式為Additive,因此站立攻擊時Attack動作與行走動作上半身進行混合,跑動攻擊時Attack動作與跑動動作上半身進行混合。

 

轉載自 http://blog.csdn.net/sparrowfc/article/details/8240165

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved