Unity3D 的 Mecanim 動畫系統能夠直接複用 3DS MAX 中製做的動畫文件中的位移,這個就是經過 applyRootMotion 來達成的,咱們只須要在使用 Animator 控制動畫播放的同時,設置 Animator 的 applyRootMotion 字段爲 True 就 OK 了。app
那麼怎麼來利用這個特性達成咱們想要的一些效果呢?這個 applyRootMotion 到底指的是啥呢?編輯器
ApplyRootMotion,從字面上理解來看,是『應用根節點的運動』,聽起來貌似像那麼一回事。但是咱們能夠從官方文檔上看到這樣一段話:函數
The Root Transform is a projection on the Y plane of the Body Transform and is computed at runtime. At every frame, a change in the Root Transform is computed. This change in transform is then applied to the Game Object to make it move.oop
翻譯過來的意思,應該是這樣的:優化
根節點的運動變換其實就是整個物體運動變換經過 Y 軸垂直在水平面上的一個投影。根節點的運動變換在動畫的每一幀中都會進行計算。計算出來的根節點變換結果都會應用在播放動畫的對象上,讓該對象按照根節點的運動變換進行移動。動畫
這段話大致的意思就是,RootMotion 這個玩意就是做用於動畫物體在 X 軸和 Z 軸上的位移的,並且這個位移是根據實際播放的動畫中每一幀物體的位移在 X 和 Z 軸上投影計算出來的。spa
這個特性很是贊特別是對於某些技能動畫,整個動畫是有必定位移的,可是動畫的位移是動做設計師在設計時根據動做須要調出來的,位移是跟動做的幅度直接相關和匹配的。翻譯
那麼在釋放技能的時候就只須要直接播放動畫,而且應用這個 Root Motion 的特性就能夠很好的完成角色在播放攻擊動做的同時進行移動,動做播放完畢以後就在動畫結束幀角色所在的位置,切換爲待機動做就 OK 了。設計
看起來很牛逼的樣子對不對?是的,確實很牛逼。可是還有不少事情須要咱們都一一瞭解之後,咱們才能作出咱們想要的東西的。orm
下面咱們先岔開一下話題,好好說說這個 Animation Import Settings 中『Animations』Tab 頁中各項設置的做用。
- Import Animation,勾選這個才能夠導入動畫到 Unity 工程中;
- Bake Animations,這個選項只在使用 Humanoid 動畫而且使用到了 IK 特性的時候纔可用;
- Anim.Compression,這個是關於動畫壓縮選項的,默認會選擇 Keyframe Reduction 這個是『壓縮關鍵幀』,就是 Unity 會自行重採樣動畫的關鍵幀,還有兩個選項『Off 和 Optimal』,一個是關閉動畫壓縮,一個是最優化壓縮(應該是壓縮效率最高,動畫效果失真度可能也較高)
- 選擇了 Keyframe Reduction 或者 Optimal 壓縮選項,就會有三個用於控制壓縮選項的係數配置, Rotation Error,Position Error 和 Scale Error,這個三個參數默認都是 0.5,越小呢精度就越高也就是說動畫的失真度越小。
- Clips,這個下面列出了這個 FBX 文件下包含的全部動畫,咱們在默認的動畫文件基礎上新建和刪除動畫片斷 (Animation Clip),固然每一個動畫片斷都是能夠指定起始幀和結束幀的; 如下的設置都是針對單個動畫片斷滴:
- Loop Time,勾選這個選項以後,若是 Animator 處於播放這個動畫狀態時,在播放完第一遍這個動畫片斷以後,會自動循環從起始幀再次開始播放動畫,如此循環往復。若是咱們不勾選這個選項,例如 Animator 一直處於播放這個動畫的狀態,那麼動畫會定格在動畫的結束幀,直到咱們經過 Animator 切換這個 Animator 狀態機的狀態,切換到其餘的動畫;
- Loop Pose 和 Cycle Offset,在勾選了 Loop Time 以後生效的兩個選項,Loop Pose 用於控制動畫循環播放時,從結束幀切換到起始幀時,動畫的動做能夠無縫的銜接上,Cycly Offset 就是用於控制循環的時候起始幀偏移用的;
- Root Transform Rotation,根節點的旋轉信息
- Bake Into Pose,勾選後會將根節點每一幀的旋轉方向信息烘焙到動畫的骨骼運動中,在整個動畫播放的過程當中,根節點的旋轉信息就不會在經過 Root Motion 做用到播放該動畫的 GameObject 上了,這就意味着這個動畫播放的過程當中,該物體的 Transform 中的 Rotation 值不會由於動畫中物體作了任何旋轉而發生改變,而是會保持一個恆定的值,和該動畫播放以前的旋轉值保持一致;
- Based Upon (at Start) 或者 Based Upon,根節點旋轉的參考基準,有兩個選項『Original 和 Root Node Rotation』這兩個分別指的是動畫文件中指定的旋轉值和根節點旋轉信息,其實我更願意將 Original 理解爲動畫中原點的旋轉值,由於在整個動畫播放的過程當中,全部骨骼確定都會有旋轉和位移的變換,可是動畫的原點其實必定都是肯定的,這樣理解感受更簡單也更形象一些,勾選了 Bake Into Pose 以後,就會變成 Based Upon 而不勾選 Bake Into Pose 就會保持爲 Based Upon (at Start),這個目前還木有理解爲啥;
- Offset,旋轉角度與參考基準的偏移(以度爲單位);
- Root Transform Position(Y),根節點位移信息(Y 軸)
- Bake Into Pose,勾選後會將根節點每一幀在垂直 Y 軸方向上的運動信息烘焙到動畫的骨骼運動中,在整個動畫播放的過程當中,根節點在 Y 軸方向的全部位移信息不會經過 Root Motion 做用到播放該動畫的 GameObject 上,這就意味着咱們在場景中看到物體在 Y 軸上有位移,例如向上或者向下移動,可是該物體的 Transform 中的 Position 信息不會發生改變,會跟動畫播放以前的 Position 信息保持一致;
- Based Upon 或者 Based Upon (at Start),這個貌似有點不同哦,在選中 Bake Into Pose 以後會變成 Based Upon (at Start),不勾選的時候是 Based Upon,不過這個就能理解了。不烘焙的話,那麼 Root Motion 中 Y 軸的變化就依賴於選擇的『Original 或者 Root Node Position』的 Y 軸位移變化,若是選擇烘焙的話,那麼就以這個動畫的起始幀的 Y 軸做爲整個動畫 Root Motion 的 Y 軸位移,在整個動畫播放的過程當中,Y 軸的位移都是恆定不變的;
- Offset,垂直方向上的偏移;
- Root Transform Position(XZ),根節點位移信息(水平面,XZ 軸)
- Bake Into Pose,勾選後會將根節點每一幀在水平面(X 和 Z 軸)方向上的運動信息烘焙到動畫的骨骼運動中,在整個動畫播放的過程當中,根節點在 X 和 Z 軸方向的全部位移信息不會經過 Root Motion 做用到播放該動畫的 GameObject 上,這就意味着咱們在場景中看到物體在水平面上移動,可是該物體的 Transform 中的 Position 信息不會發生改變,會跟動畫播放以前的 Position 信息保持一致,假如動畫中物體會向前移動 3 米,咱們會看到物體在整個動畫播放過程當中確實在向前移動,播放到最後一幀時確實向前移動了 3 米,可是當這個動畫播放完畢以後,切換到任何其餘的動畫時,物體會直接閃回這個動畫播放前物體所在的位置,因此一般咱們須要保留動做位移的動畫都不會勾選這個選項。那這個選項有神馬用捏?例如某些待機動畫,咱們其實但願物體只是作一個待機動做,可是實際上不想讓物體在水平方向上有位移,這個時候就能夠勾選這個選項了,到時候看起來物體就像是釘在水平面上了;
- Mask,這個掩碼主要是用於控制動畫播放過程當中,各個骨骼之間的運動變換的
- Definition,能夠選擇從動畫文件建立也能夠選擇使用其餘動畫文件中已經建立好的配置;
- Transform,這個就是動畫文件中全部骨骼的層級關係,能夠選擇勾選那些須要應用動畫中運動變換的骨骼;
- Curves,這個主要用於設置某些跟動畫相關的參數用,例如控制整個動畫播放過程當中的速度參數之類的,在動畫播放的過程當中能夠經過 Animator.GetFloat(ParamName) 函數來讀取曲線的值,曲線的 X 軸爲動畫的時間軸,Y 軸爲曲線的值,曲線能夠經過曲線編輯器進行增長關鍵點,調整曲線斜率進行編輯,讀取時默認會根據當前動畫播放的進度做爲 X 軸的值進行讀取,一個動畫片斷能夠有多個曲線;
- Events,這個是用於在動畫播放的過程當中觸發事件的,例如整個動畫中有起跳和落地兩個事件須要在準確的時間點觸發並通知到遊戲中其餘的對象,那麼就能夠在 Events 時間軸上新增事件通知,設置好觸發的方法名稱和參數,在播放該動畫的 GameObject 上確保有某個腳本中有與該事件通知的方法簽名一致的方法就行了,當動畫播放到觸發通知時間時,就會向 GameObject 廣播該時間通知,腳本中方法簽名一致的方法就會被回調了,那咱們就能夠作咱們須要作的事情了。
- Loop Time,勾選這個選項以後,若是 Animator 處於播放這個動畫狀態時,在播放完第一遍這個動畫片斷以後,會自動循環從起始幀再次開始播放動畫,如此循環往復。若是咱們不勾選這個選項,例如 Animator 一直處於播放這個動畫的狀態,那麼動畫會定格在動畫的結束幀,直到咱們經過 Animator 切換這個 Animator 狀態機的狀態,切換到其餘的動畫;
說了這麼多貌似跟 Root Motion 不是很相關的東西,那麼究竟咱們今天的主題是啥呢?確定仍是 Root Motion 這貨。主要由於動畫導入時的設置對於 Root Motion 的應用影響很是直接,因此前面絮絮不休地把這個動畫導入設置都羅列了一遍。
回到正題,Generic 動畫應用 Root Motion 有如下幾個特色:
- Root Motion 僅僅做用於 GameObject 在 X 和 Z 軸上的位移變換,不影響 Y 軸上的位移。例如如今播放一個從地上向前空翻以後落地的動畫,設置 Animator 的 applyRootMotion 爲 True,也就是應用 Root Motion,那麼動畫在播放過程當中,物體會在水平方向和垂直方向上都按照實際動畫的運動軌跡進行運動,若是將 applyRootMotion 設置爲 False,那麼咱們就只能看到動畫在原地起跳而後再落地,動畫中本來應有的在水平方向的位移就沒有了;
- Root Motion 與導入動畫時設置 Root Transform Position(XZ) 是直接相關的,若是咱們選擇了將 X 和 Z 軸方向上根節點的位移烘焙到動畫骨骼運動中的話,那麼動畫播放過程當中不論咱們是否將 Animator 的 applyRootMotion 設置爲 True 仍是 False,動畫播放過程當中物體在 X 和 Z 上的移動是必定的,由於這個已經被烘焙到骨骼動畫中,只要動畫播放,物體就會移動,可是在動畫播放的過程當中 GameObject 的 Position 值不會改變,在動畫結束後咱們切換到其餘動畫的時候,其餘動畫開始播放時的 GameObject 的位置會回到這個動畫播放前的位置,因此若是咱們須要對某個動畫應用 Root Motion 的話,那麼這個動畫在導入的時候就不要烘焙其在 X 和 Z 軸方向上的 Root Transform Position,讓 Unity 自行根據動畫中根節點的位移進行位移計算 GameObject 的位置信息;
- 注意 Root Motion 與 Rigidbody.Velocity 屬性的關係,若是有兩個動畫 A 和 B,播放 A 動畫的時候,但願 A 動畫應用 Root Motion,而在播放 B 動畫的時候不想應用 Root Motion,那麼就直接在切換到動畫 B 的時候,將 Animator 的 applyRootMotion 設置爲 False 就 OK 了。可是若是播放動畫的 GameObject 帶有 Rigidbody 組件,那麼須要注意一點,在播放 A 動畫時 Rigidbody 的 Velocity 並不會在切換到 B 動畫時清零,也就是說若是 A 動畫的運動速度較快,那麼切換到 B 動畫的時候,若是但願 B 動畫播放的時候 GameObject 按照本身的設定軌跡運動,就須要自行手動在切換到 B 動畫以前將 Rigidbody 的 Velocity 屬性清零,防止 GameObject 按照 A 動畫的運動慣性繼續運動。這個問題在沒有 Rigidbody 組件的 GameObject 上不會存在;
這邊再岔開一下,說說這個動畫跟 Rigidbody 之間的關係:
- 若是咱們沒有將 Root Transform Position 的 Y 和 XZ 軸進行烘焙的話,那麼在動畫播放的過程當中,Rigidbody 將會自動得到動畫中物體運動的速度信息,直接經過 Rigidbody.Velocity 屬性就能夠得到;
- 若是咱們將 Y 軸進行烘焙,那麼 Rigidbody.Velocity 在 Y 軸上的值將會一直爲 0,對於 XZ 軸也是同樣的,若是烘焙了 XZ 軸的位移,那麼整個動畫播放過程當中,Rigidbody.Velocity 在 X 和 Z 軸上的值都會爲 0;
- 若是播放動畫的物體沒有 Rigidbody 組件,那麼動畫的運動都會僅僅按照動畫實際的位移來進行逐幀播放,不會出現上文中提到的動畫播放切換以後還存在的運動慣性問題,由於物理引擎依賴於 Rigidbody 組件,若是沒有該組件,全部動畫的播放都只是逐幀播放動畫,不會存在速度的概念只有移動位移。
- Rigidbody 使用使用重力對於動畫在 Y 軸上的位移沒有任何影響,不管是否對 Root Transform Position 的 Y 軸進行了烘焙。
轉自:http://7dot9.com/?p=528