實現效果
核心功能
- 支持選定模型(帶Animator)在非運行模式下,播放/暫停/停止動作。
- 支持動作單幀前進,單幀回退(幀時間默認0.05f,可以代碼設置)。
- 支持滾動條拖拽,將動作調整到指定時間。
- 支持調整播放速度。
其他功能
- 支持循環播放。
- 支持選中Animator下的任一動作。
- 編輯器關閉時,會刪除中間產生的臨時GameObject
- 選中Project中的Prefab,如果符合條件,將會自己創建一份Clone到Hierarchy中。
效果圖

實現原理
整體思路
- 獲取指定GameObject上的Animator,並記錄其所有的AniamtionClip。
- 模擬播放時間,通過AnimationMode.SampleAnimationClip方法設置播放位置。
- 添加進度條,單幀執行等方式修改播放時間。
注意細節
- 如果模型勾選了OptimizeGameObject選項,優化骨骼,那么動作可能會因為找不到骨骼而無法播放。需要使用AnimatorUtility.DeoptimizeTransformHierarchy方法,暫時屏蔽骨骼優化。
- 在使用AnimationMode.SampleAnimationClip方法時,參數的GameObject應該設置為Animator所對應的GameObject而不是根節點。
- 因為不是運行狀態,所以Update需要由EditorApplication.update提供。(工具關閉時,需要反注冊)
- OnGUI方法不是每幀都執行,當使用滾動條( Slider )和進度條(ProgressBar)時,顯示不會及時更新,所以當數據更新時,需要調用Repaint方法,強制刷新UI。
- EditorWindow下,OnSelectionChange方法可以用來監聽選擇變化。但是在這個方法內部,修改當前選中的對象(Selection的屬性)無效。
- 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, "");
}
存在疑問
- AnimationMode文檔中說在使用 SampleAnimationClip時需要 StartAnimationMode,但沒有調用,也是可以正常運行。BeginSampling,EndSampling作用什么?不加也可以正常運行。
- 在使用AnimatorUtility.OptimizeTransformHierarchy去還原模型時,需要知道exposedTransforms即需要保留的骨骼。但是沒有找到獲取exposedTransforms的方法,所以GameObject在被DeoptimizeTransformHierarchy之后無法還原。一種的思路是在調用DeoptimizeTransformHierarchy之前記錄子Transform,並且去掉包含SkinnedMeshRender的Transform,使用這些Transform來當做exposedTransforms。但是這種方式不精確,對模型有限制。
ToDo
- 倒播。修改時間變化方式,添加符號判斷。
- ParticleSystem.Simulate可以在非運行模式下制定特效播放到制定時間,可以用這個方法實現一套特效的播放回退機制。(特效比較復雜可能包含多個ParticleSystem,也可能包含動畫)
- 結合動作和特效,實現特效與模型動作的匹配,指定特效延時時間,並且可以同時處理多個特效。(類似技能編輯器的表現)
源碼下載
轉載請注明出處:http://www.cnblogs.com/chiguozi/p/6862571.html