unity anim(轉)


Unity4的Mecanim動畫很早以前就有體驗過,遲遲沒有加到項目中有兩個原因,今天寫這篇博客來記錄我在做的過程中遇到的一些問題。

1.以前的代碼代碼量比較多,修改起來動的地方太多了。

2.使用Mecanim動畫,還得需要美術的動畫做配合才行。

在3.x中播放動畫的時候使用Play()或CrossFade(),直接播放動畫 或淡入淡出播放動畫。

1 animation.Play("name");
2 animation.CrossFade("name");

也可以使用隊列播放,讓動畫形成一個隊列。

1 animation.Play("name");

2 animation.CrossFade("name");

我舉一個我現在項目的例子。主角攻擊敵人是一套連招,連招一共分為4套動畫。也就是當玩家連續按下4次攻擊鍵時這四套動畫是連續播放的,假如玩家只連續按下2次攻擊,可能只會播放前兩套動畫。代碼中你需要判斷其中某個動畫是否播放完畢,只有播放完畢才能繼續播放下一個動畫。

1 if(animation.isPlaying)

2 {
3
4 }
5
6 if(animation.IsPlaying("attack1"))
7 {
8
9 }

大家在仔細想想這個命題,我們可以把動畫分成4中可能的隊列,也只可能分為這幾種隊列。

站立動畫- 》攻擊動畫0 -》站立動畫

站立動畫- 》攻擊動畫0 -》攻擊動畫1 -》站立動畫

站立動畫- 》攻擊動畫0 -》攻擊動畫1 -》攻擊動畫2-》站立動畫

站立動畫- 》攻擊動畫0 -》攻擊動畫1 -》攻擊動畫2-》攻擊動畫3-》站立動畫

此時如果用unity3以前的動畫方式,無非就是上面這幾種方法加上一些邏輯判斷完成。現在Unity4加入了Mecanim動畫,可以很好的幫我們解決這個問題。詳細的動畫使用教程我就不多說了,網上已經有很多人寫過了。

如下圖所示,以前我們在使用模型的時候。一個原始模型,原始模型中沒有動畫。然后是動畫模型,每一個動畫都會依賴原始模型。動畫的名稱末尾用 名稱 + @name來表示。 這樣的做法使用起來非常方便,但是由於每一個動畫都會依賴原始模型所以文件會非常大。

屏幕快照 2013-04-16 下午2.14.57

Unity4已經將默認模型與動態導入的類型做了修改,你會發現你的模型拖拽入Hierarchy視圖中沒有Animation組件而是Animator組件。如果你還是想在Unity4中使用以前的動畫系統。你需要把每個模型和動畫的類型改成 Rig-> Animation Type -> Legacy,如下圖所示。

屏幕快照 2013-04-16 下午2.19.04

手動的改起來會非常的累。建議你將下面這條腳本放在項目Editor文件夾下(沒有創建一個)。這樣當你將模型或動畫拖入Project視圖中,程序會自動幫你修改它的類型,顯然Unity已經不建議大家繼續使用以前的動畫系統了。

01 using UnityEditor;
02
03 public class MyEditor : AssetPostprocessor
04 {
05 public void OnPreprocessModel()
06 {
07 ModelImporter modelImporter = (ModelImporter) assetImporter;
08 modelImporter.animationType = ModelImporterAnimationType.Legacy;
09 }
10 }

下面開始說說新的動畫。在Animations選項卡中先勾掉Import Animation 點擊Apply。如下圖所示,在Rig選項卡中修改Animation Type的類型為Humanoid。 如果你希望現在選擇的這個模型做為標准模型的話,在Avatar Definition中選擇Create From This Model。點擊下方的Configure可以預覽你的骨骼。

屏幕快照 2013-04-16 下午2.13.32

讓美術修改一下以前的動畫,將動畫中的原始模型去掉,這樣還可以減少文件的大小。然后在Porject視圖中找一個原始模型拖拽入右側Preview中,可以看到這個模型已經播放奔跑動畫。

屏幕快照 2013-04-16 下午2.33.35

此時換一個模型拖入同樣可以預覽奔跑效果。

屏幕快照 2013-04-16 下午2.36.51

如下圖所示,在動畫的.fbx中 因為動畫需要用剛剛生成的骨骼。所以這里Avatar Definition中你需要選擇Copy From Other Avatar 。在Source中選擇剛剛生成的Avatar 以后所有動畫都需要這樣來設置。。

屏幕快照 2013-04-16 下午4.38.57

下面我們來讓這個女模型和男模型共用男模型的那一套動畫,在游戲視圖中播放。在Project視圖中選擇Crate->AnimatorController。然后把Project中男模型和女模型都拖拽入Hierarchy視圖中。 將剛剛創建的AnimatorController放置在Controller處。

屏幕快照 2013-04-16 下午2.41.31

此時在Unity導航菜單欄中選擇Window -》 Animator。 將動畫文件拖入Animator窗口中,你會發現兩個模型都開始發生運動。如下圖所示,黃顏色表示它為原始動畫,也就是根動畫。用箭頭將它們一一前后相連,箭頭實際上就是動畫播放的條件。請注意看圖中兩個藍色的箭頭,A播放完后將會播放B動畫,可是B卻對應了兩個箭頭,也就是說B播放完后可以播放C也可以回過頭來播放A。

屏幕快照 2013-04-16 下午3.00.59

那么B播放完到底是播放C還是播放A呢?用鼠標點擊一下箭頭,看看這這兩個箭頭的條件吧。分別點開BA 和BC的兩個箭頭,在右側監測面板視圖中你都會發現Conditions下有一個Exit Time的條件。根據動畫的不同對應數值也會不同,我的數值是0.94。也就是當B動畫播放0.94s后將播放下一個動畫。默認BA和BC的動畫時間是一樣的,Unity會有限選擇下一個動畫,也就是A -》 B-》-》C-》D-》A這樣循環播放下去。假設我現在需要動畫是 A-》B-》A這樣循環播放,只需要修改一下BA箭頭的條件,將Exit Time改小一點只要比BC箭頭上的小就可以。。 其它的播放虛列原理類似。

屏幕快照 2013-04-16 下午3.09.50

接着還有問題了,用時間來做動畫切換的條件是不是有點太限制了。Animator還支持自定義條件,在Animator窗口的左下角處,點擊“+”按鈕就可以添加變量。這里我添加三組變量, float 、int、bool。

屏幕快照 2013-04-16 下午3.17.50

變量添加完畢后,繼續點擊箭頭的條件,箭頭上可以有一個條件 或者多個條件。如果是多個條件需要多個條件同時滿足才可以。 Conditons左鍵是變量名稱,中間是變量條件,右邊是變量值。

Greater 表示左邊變量大於右邊時觸發

Less 表示左邊變量小於右邊時觸發

Equals 表示左邊變量等於右邊時觸發

NotEquals表示左邊變量不等於右邊時觸發。

int 變量上述四種都有,float變量只有Greater 和Less, bool變量只有true和false。

屏幕快照 2013-04-16 下午3.20.38

此時我們在加深一下理解。選擇AB的箭頭,也就設置A動畫切換B動畫的條件。

ft     Greater      5 表示 當ft的值大於5的時候觸發。

it      Less           3 表示 當 it的值小於3的時候觸發。

ib     true            表示 當ib的值等於true的時候觸發。

只有上述三種條件全部達成時將A動畫將切換播放B動畫。否則將一直停留在播放A動畫處。

屏幕快照 2013-04-16 下午3.26.38

那么ft it ib的這三個變量到底在那里設置呢?如下圖所示,才記得前面我們創建的三個變量嗎? 這三個變量對應的值就是右邊的 0.0 0 false 。在編輯器中你可以通過修改這三個數值來滿足播放動畫的條件。可是在代碼中怎么辦呢?

屏幕快照 2013-04-16 下午3.17.50

在代碼中你可以這樣來設置或變更它們的條件。 如果說你需要在程序中判斷當前動畫的一些信息,可以使用 GetCurrentAnimatorStateInfo(0),我查了一下Animator不能直接拿到當前播放動畫的名稱, 只能拿到它對應的Has值,也就是說你需要將原始的動畫名稱轉換成Hash來判斷。

01 using UnityEngine;
02 using System.Collections;
03
04 public class NewBehaviourScript : MonoBehaviour {
05
06 private Animator animator ;
07 void Start()
08 {
09 //得到Animator對象
10 animator = GetComponent<Animator>();
11 }
12
13 void OnGUI()
14 {
15 if(GUILayout.Button("play",GUILayout.Width(50)))
16 {
17 //在這里設置變量的條件
18 animator.SetFloat("ft",6f);
19 animator.SetInteger("it",2);
20 animator.SetBool("ib",true);
21
22 }
23 }
24
25 void Update()
26 {
27 AnimatorStateInfo animatorState = animator.GetCurrentAnimatorStateInfo(0);
28
29 if(animatorState.IsName("Base Layer.Run_FastStop_Idle"))
30 {
31 Debug.Log("動畫相等");
32 }else
33 {
34 Debug.Log("動畫不等");
35 }
36
37 }
38 }

另外Mecanim還支持多個動畫的混合。目前Mecanim還有一個最大的難題,也是文章最上面我說的需要美術配合的那部分。之前我們看到的動畫都是應用於人型模型,也就是說它支持人形的骨骼, 舉個例子我們的項目人和武器是兩個骨骼,這樣在用Mecanim就悲劇了。因為不同模型武器的骨骼不一樣所以公用模型的話會出現武器位置不對的情況。最后我想到的辦法就是美術將以前做的武器骨骼重新導出,每個人對應一套自己武器骨骼(或者一些特殊的骨骼)最后生成武器的動畫 ,比如 站立動畫、攻擊動畫、死亡動畫等。當Mecanim播放動畫的時候,同時在播放該模型對應的武器動畫,我想這樣就可以解決這個問題吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM