Unity3D中角色的動畫腳本的編寫(一)

已有好些天沒寫什麼了,今天想起來該寫點東西了。此次我所介紹的內容主要是爲了配合我前面所寫的角色運動控制有關的文章,那就是動畫。這是一個很複雜的概念,今天,我就把我所理解的有關動畫方面的觀點跟你們說說,不對的地方請你們指出,在下萬分感謝。
老實說,我學Unity時,角色控制真的是一個難點,尤爲是動畫方面。想要在Unity中控制好一個角色且讓這個角色的動做協調,不是一個簡單的問題,須要咱們深刻理解其原理。只有這樣,咱們纔有能力寫一套精湛的角色控制腳本。Unity裏面的動畫系統至關複雜(也許是個人程度不夠吧),咱們不要指望本身不用將Unity動畫系統的一些原理搞清楚就可以寫出一套很棒的角色控制腳本,這是很愚蠢的。僅僅只是角色移動就播放跑步的動畫,角色停下來就播放站立的動畫,具備這種想法的程序員應該注意一下了。
那麼怎麼開始呢?我認爲咱們必須瞭解一些基本的概念。首先咱們來了解一些基本的知識。首先是動畫的導入。相信大部分讀者在讀本帖以前就已經對動畫的導入有必定的瞭解了,這裏我可能會從頭開始講解,由於我的程度不一樣嘛。通常角色動畫是在三維軟件中設計好了以後,再導入到unity3d中去的,且文件格式通常是*.FBX。Unity3D中導入角色動畫的方式主要有兩種,這兩種方式分別以下:
1.分割動畫。美術在三維軟件中對角色的動做設計完成以後將全部動畫集中在一個FBX文件上。咱們只需知道其製做的動畫片斷的個數與其對應的幀數就能夠對存儲在這個FBX文件上的動畫進行準確的分割。詳細過程官方文檔上寫的很清楚,咱們只須要循序漸進的執行就行。可是要注意一點,咱們能夠在分割動畫的時候會遇到這樣一個選項:WrapMode,圖以下:





這個WrapMode(循環模式)很重要,默認狀態下系統選擇的是Default,你能夠調節其爲其餘選項,好比Loop。咱們也能夠利用腳原本動態的操做它。關於其用法,咱們會在後面的代碼中得以體現。

2.多重動畫文件。這是一個很方便的動畫導入方法。在項目中,美術有可能將動畫數據與模型分開製成FBX文件,那麼此時咱們只需找到動畫的FBX模型,對它們以一個通用的方式命名便可。即"模型名@動畫名",例如一個模型的名字叫作gam,而且這個模型有一個名爲「idle」的動畫的FBX文件,那麼咱們能夠將這個FBX模型的名字命名爲:
"gam@idle"。須要注意的是這個根模型中的各個動畫的循環模式是Default,並且在Inspector面板中沒法修改,只能在腳本中修改,有點坑吧。並且方式二中的文件佔用大小對於方式一來講確實增大很多,這對於移動設備類遊戲來講確實是一件必須斟酌的事情。望讀者務必注意一下。


瞭解完這些以後,咱們該重點的談一談Unity裏面的與動畫相關的API了,重點有如下三個:Animation,AnimationClip,AnimationState。此次咱們先看一下Animation這個類,我估計此次還講不完,若是是這樣,那我就儘可能講得多一點吧。

Animation,官方是這樣介紹的:The animaiton component is used play back animations.翻譯過來就是:動畫租金按是被用來播放動畫集合的。說到這裏,談到了組件,對沒錯,這個類對應的就是咱們的Animation組件。咱們將Project面板下的任何一個FBX模型拖拽到Hierarchy面板中,你會在其對應的Inspector面板中發現其被自動添加了一個Animation組件,只不過其動畫片斷的數量默認爲0。你能夠調節這個動畫的Size,而後從Project面板中找到相應的動畫片斷,此動畫片斷截圖以下:




動畫片斷,即AnimationClip,實際就是上圖中的那個白色右下角有個圓形的idle文件。你能夠將這個動畫片斷拖拽到Animation組件中的Animations下面,前提是其Size不爲0,以下圖: 



下面咱們來深刻了解一下這個組件在腳本中的運用,首先咱們看一下這個類的變量: 



第一個變量是指的這個Animation組件的默認播放的動畫片斷。第二個指的是該動畫組件中默認的動畫片斷是否在遊戲運行時自動播放。第三個變量很重要,咱們能夠用腳原本控制全部動畫片斷的循環狀態,好比咱們能夠這樣寫 :
animation.wrapMode = WrapMode.Loop; 注意,小寫的animation指的是該腳本附着的GameObject上的Animation組件。這句代碼的功能是將該GameObject身上全部的動畫片斷的播放方式設置爲循環播放。且能夠再後續的腳本中進行相應的修改。那麼咱們有必要了解一下這個變量的類型:WrapMode。我截了一個圖,以下:


WrapMode主要是用來對動畫片斷的播放模式來進行修改的,這五個變量表明瞭5中播放模式。第一個Once,後面的解釋是這樣的:當這個動畫片斷播放到告終尾,若是程序沒有修改它的wrapMode,那麼這個動畫片斷將會自動中止播放,並且其此時播放的幀數被重置爲第一幀,也就是該動畫片斷的開頭。此播放方式能夠應用在射擊類動畫片斷的wrapMode中。第二個是Loop,咱們應該是比較熟悉了吧。若是程序沒有修改它的wrapMode,該動畫片斷播放完最後一幀以後並不會中止,而會回到第一幀並重復播放,知道當前的動畫狀態的改變。第三個變量是PingPong,意思是噹噹前動畫片斷播放完最後一幀以後,若是程序沒有修改它的wrapMode,將隨機的在第一幀與最後一幀之間來回播放。第四個變量咱們以前遇到過,在上面的動畫導入方式中,若是是以分割動畫的導入方式,那麼默認每一個動畫片斷的wrapMode爲WrapMode.Default,即讀取默認的設置,不過能夠在Inspetor面板中修改。可是若是是多重動畫文件的導入方式,那Unity連給你在Inspector中修改的機會都不給你,此時你只能在腳本中進行動態修改其wrapMode。最後一個變量,ClampForever。若是當前播放的動畫的wrapMode的值爲WrapMode.ClampForever,那麼當這個動畫片斷播放完最後一幀時,若是程序沒有修改它的wrapMode,那麼它將會一直播放這個動畫狀態的最後一幀。除此以外,咱們還能夠在官方的CharacterAnimation工程中發現這樣一個變量:WrapMode.Clamp,後來經我驗證,發現這個變量就是WrapMode.Once。若是讀者不信的話,能夠準備一個角色。加入這個角色具備名爲「idle」(其餘也行)的動畫片斷,那麼咱們能夠寫這樣一個腳原本驗證一下咱們的猜測:

using UnityEngine;
using System.Collections;

public class TestWrapMode : MonoBehaviour {

// Use this for initialization
void Start () {
animation.Stop();//禁用Animaton組件中的Play Automatically。
animation["idle"].wrapMode = WrapMode.Clamp;//設置名爲idle的動畫片斷的wrapMode屬性爲WrapMode.Clamp。

}

// Update is called once per frame
void Update () {

if(animation.IsPlaying("idle")){//若是當前有播放idle動畫那麼就執行下面

Debug.Log(animation["idle"].wrapMode);
}

if(Input.GetKeyDown(KeyCode.A)){

animation.CrossFade("idle");//淡入淡出名爲idle的動畫。
}
}
}

整個腳本很是簡單。咱們將這個腳本綁定在咱們準備好的角色身上,當咱們按下「A」鍵時,會在Console上打印idle的wrapMode屬性,那麼該屬性會是什麼呢?


果真是Once,哎,奇怪了,不是有一個Once嗎?怎麼還要加個Clamp呢?估計是當時設計API時出現的一些歷史遺留問題吧。沒必要管它,咱們只需知道這個Clamp到底屬於那種效果就好了。
好了,WrapMode這個類介紹完了,下面咱們該繼續介紹Animation這個類。讀者可能以爲我應該結合具體工程來說解這些知識,其實否則,若是你連最基本的概念都半生不熟的話,就不要期望寫出好的控制腳本。接下來我儘可能挑選一些重要的屬性和函數來進行講解。


類:Animation
屬性:
isPlaying 角色此時是否在播放動畫?
this[string name] 這個屬性很是重要,他的返回值類型是AnimationState,咱們叫他動畫狀態。
剩下的幾個變量通常不多用到,讀者感興趣的話本身能夠研究一下,好比animatePhysics,是用來結合運動學剛體來實現的。culling Type這個屬性你能夠在Inspector面板中的Animation組件中看到,有幾個選項可選,那幾個選項讀起來也不難,這裏我也就很少說了,接下來咱們來看幾個重要的函數:


1.Stop( ) 顧名思義,就是中止全部當前正在播放的動畫。

2.Rewind (string AnimationName) 導播名爲AnimationName的動畫片斷。

3.Sample() 在當前狀態對動畫進行採樣,說實話,這個函數我還真沒用過。

4.IsPlaying( string AnimaitonName ) 這個函數的拼寫和上面講到的isPlaying屬性是同樣的,只是該函數的首字母是大寫的。若是當前正在播放名爲AnimationName的動畫,那麼此函數則返回***e,不然爲false。這是一個很是重要的函數。我至今沒發現Unity裏面的動畫相關的類中有一個函數或者屬性可以取得當前正在播放的動畫名稱,後來我才發現這個是得不到的,後面我會說明緣由的。

5.Play( string AnimationName )
沒有任何混合的播放名爲AnimationName的動畫片斷。老實說,如今的動畫若是不混合,真的沒什麼看頭,因此這個函數通常咱們也不用。

6.CrossFade( string animation , float time , PlayMode mode )
這個函數咱們得注意了,它具備淡入名爲animation的動畫並淡出當前正在播放的動畫的效果,這種效果然的很棒,他使咱們的動畫播放更爲平滑。而且這個函數還有兩個重載的方法。好比咱們角色的Animation組件中有一個名爲「Walk」的動畫片斷 。那麼咱們要淡如這個動畫片斷就有一下三種 寫法:
1. animation.CrossFade( "Walk" ); 以默認方式淡入名爲「Walk」的動畫,
2. animation.CrossFade( "Walk",0.3f );在0.3秒左右淡入名爲「Walk」的動畫;
3. animation.CrossFade( "Walk",0.3f,PlayMode.StopSameLayer ) 這句代碼與上句是同樣的,只是第二句省略了第三個參數。這個參數的類型爲PlayMode,裏面有兩個屬性:PlayMode.StopSameLayer,StopAll,第一個屬性
表示中止同一層的動畫,當函數中沒有此參數時,默認用的就是這個屬性;第二個屬性表示中止全部的動畫。
 程序員

 還剩下幾個函數,有點晚了,下一篇我在介紹吧。這篇文章我確實是費了很多心思的。接下來的幾篇我會盡可能將個人心得奉獻給你們,對此感興趣的讀者不妨留意一下函數

相關文章
相關標籤/搜索