Unity非運行模式下實現動畫播放/回退工具

實現效果

核心功能

  1. 支持選定模型(帶Animator)在非運行模式下,播放/暫停/中止動做。
  2. 支持動做單幀前進,單幀回退(幀時間默認0.05f,能夠代碼設置)。
  3. 支持滾動條拖拽,將動做調整到指定時間。
  4. 支持調整播放速度。

其餘功能

  1. 支持循環播放。
  2. 支持選中Animator下的任一動做。
  3. 編輯器關閉時,會刪除中間產生的臨時GameObject
  4. 選中Project中的Prefab,若是符合條件,將會本身建立一份Clone到Hierarchy中。

效果圖

實現原理

總體思路

  1. 獲取指定GameObject上的Animator,並記錄其全部的AniamtionClip。
  2. 模擬播放時間,經過AnimationMode.SampleAnimationClip方法設置播放位置。
  3. 添加進度條,單幀執行等方式修改播放時間。

注意細節

  1. 若是模型勾選了OptimizeGameObject選項,優化骨骼,那麼動做可能會由於找不到骨骼而沒法播放。須要使用AnimatorUtility.DeoptimizeTransformHierarchy方法,暫時屏蔽骨骼優化。
  2. 在使用AnimationMode.SampleAnimationClip方法時,參數的GameObject應該設置爲Animator所對應的GameObject而不是根節點。
  3. 由於不是運行狀態,因此Update須要由EditorApplication.update提供。(工具關閉時,須要反註冊)
  4. OnGUI方法不是每幀都執行,當使用滾動條( Slider )和進度條(ProgressBar)時,顯示不會及時更新,因此當數據更新時,須要調用Repaint方法,強制刷新UI。
  5. EditorWindow下,OnSelectionChange方法能夠用來監聽選擇變化。可是在這個方法內部,修改當前選中的對象(Selection的屬性)無效。
  6. ProgressBar不能使用Layout,須要本身設置Position。在Layout中獲取上一個Rect的位置,而後計算ProcessBar的位置,實現方式:
if(Event.current.type == EventType.Repaint)
        {
            var lastRect = GUILayoutUtility.GetLastRect();
            EditorGUI.ProgressBar(new Rect(lastRect.x, lastRect.y + lastRect.height, lastRect.width, 20), animationCtrl.escapeTime / animationCtrl.length, "");
        }

存在疑問

  1. AnimationMode文檔中說在使用 SampleAnimationClip時須要 StartAnimationMode,但沒有調用,也是能夠正常運行。BeginSampling,EndSampling做用什麼?不加也能夠正常運行。
  2. 在使用AnimatorUtility.OptimizeTransformHierarchy去還原模型時,須要知道exposedTransforms即須要保留的骨骼。可是沒有找到獲取exposedTransforms的方法,因此GameObject在被DeoptimizeTransformHierarchy以後沒法還原。一種的思路是在調用DeoptimizeTransformHierarchy以前記錄子Transform,而且去掉包含SkinnedMeshRender的Transform,使用這些Transform來當作exposedTransforms。可是這種方式不精確,對模型有限制。

ToDo

  1. 倒播。修改時間變化方式,添加符號判斷。
  2. ParticleSystem.Simulate能夠在非運行模式下制定特效播放到制定時間,能夠用這個方法實現一套特效的播放回退機制。(特效比較複雜可能包含多個ParticleSystem,也可能包含動畫)
  3. 結合動做和特效,實現特效與模型動做的匹配,指定特效延時時間,而且能夠同時處理多個特效。(相似技能編輯器的表現)

源碼下載html

轉載請註明出處:http://www.cnblogs.com/chiguozi/p/6862571.html編輯器

相關文章
相關標籤/搜索