Unity游戲開發——自動為動畫剪輯添加事件 之 最后幾幀的事件不能被調用的問題


 

最近在做一個根據配置表自動生成動畫剪輯clip以及controller的功能.做法是根據配置表配置的動作以及每個動作的關鍵幀,自動為每個clip添加事件.這樣做可以把動畫的事件處理在游戲運行之前就計算好然后存到動畫文件.anim中,可以提高游戲的運行效率,如果做的再細點,還可以自定義動畫事件的傳入的參數.比如act游戲中的多段攻擊,這些數據一定是配到表中的,我們可以把表中的數據導入成Unity的ScriptableObject類型,然后打成.asset文件,在把他指定給AnimationEvent的objectReferenceParam參數,這樣當動畫播放的攻擊幀並檢測到攻擊事件后直接把本段攻擊的配置數據傳入游戲運行時,可以減少不少的數據查找操作.

 
     private static void AddClipEvent(AnimationClip clip, ActionData data)
     {
         List atvts = new List();
         float maxFrame = data.frameCount;
         if (!string.IsNullOrEmpty(data.detFrames))
         {
             string[] dets = data.detFrames.Split(',');
 
             for (int i = 0; i < dets.Length; i++)
             {
                 int frame;
                 if (int.TryParse(dets[i], out frame))
                 {
                     if (frame > 0 && frame <= maxFrame) 
                     {
                         AnimationEvent detEvt = new AnimationEvent();
                         detEvt.functionName = GCharacter.FRAME_EVENT_NAME;
                         detEvt.stringParameter = GCharacter.FrameType.Detec.ToString() + "_" + data.id + "_" + i;
                         detEvt.time = frame / clip.frameRate;
                         atvts.Add(detEvt);
                     }
                 }
             }
         }
 
         AnimationEvent endEvt = new AnimationEvent();
         endEvt.functionName = GCharacter.FRAME_EVENT_NAME;
         endEvt.stringParameter = GCharacter.FrameType.End.ToString() + "_" + data.id;
         endEvt.time = data.frameCount / clip.frameRate;
         atvts.Add(endEvt);
 
         AnimationUtility.SetAnimationEvents(clip, atvts.ToArray());
     }

不過在做到這的時候你會發現一個問題,那就是GCharacter.FrameType.End是最后一幀的幀事件,每當一個state切換到另一個state的時候這個幀尾的事件是不會被調用的!盯着Unity的狀態機視圖看了很久,終於找到了問題的所在!

Unity之所以收到很多人的青睞就是因為他給開發者實現了很多比較復雜的功能,這里就是因為兩個動畫過度時候的融合導致的,添加Transition的時候會默認指定一個過度時間,也就是上圖中的Transition Duration,這里是0.1.

所以其實就相當於上個動畫播放到距離最后一幀還有0.1秒的時候開始播放下一個動畫,也就是此時Unity的"當前狀態"已經是下一個state,而上一個state的后幾幀的事件也不會觸發.

有兩種方法,一種是Transition Duration設為0,還有一種是讓動畫在離最后一幀還有0.1秒的時候就認為動畫已經播放到最后一幀.我是用的后者,畢竟Unity"動畫過度的融合"咱不能自己寫吧,可是差0.1秒,到是可以在程序中自己控制.

把這句改成這樣:endEvt.time = (data.frameCount / clip.frameRate) - 0.12f;

OK,完事!

本文固定連接:http://www.cnblogs.com/fly-100/p/5008961.html


免責聲明!

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



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