最近有個新需求,要用代碼添加動畫的事件,但是Unity不能直接修改FBX中的AnimationClip
在Animation窗口中可以看到,AnimationClip是Read-Only狀態,用代碼修改這個AnimationClip也是不會生效的,包括用代碼添加事件
解決方法就是將這個AnimationClip從FBX中復制一份,如果不用代碼的話,就是選中這個AnimationClip然后按Ctrl+D
AnimationClip已經被復制出來了
但是大量的動畫文件,肯定不能用這種方法解決,還是要用代碼批量處理
1 static void AnimCopy(string fbxPath, string parentPath, string name) 2 { 3 Object[] objs = AssetDatabase.LoadAllAssetsAtPath(fbxPath); 4 5 string animationPath = ""; 6 7 AnimationClipSettings setting; 8 9 AnimationClip srcClip;//源AnimationClip 10 11 AnimationClip newClip;//新AnimationClip 12 13 foreach (Object o in objs) 14 { 15 if (o.GetType() == typeof(AnimationClip) && o.name == name) 16 { 17 srcClip = o as AnimationClip; 18 19 newClip = new AnimationClip(); 20 21 newClip.name = srcClip.name;//設置新clip的名字 22 23 if (!Directory.Exists(parentPath + @"/copy/")) 24 25 Directory.CreateDirectory(parentPath + @"/copy/"); 26 27 animationPath = parentPath + @"/copy/" + newClip.name + ".anim"; 28 29 setting = AnimationUtility.GetAnimationClipSettings(srcClip);//獲取AnimationClipSettings 30 31 AnimationUtility.SetAnimationClipSettings(newClip, setting);//設置新clip的AnimationClipSettings 32 33 newClip.frameRate = srcClip.frameRate;//設置新clip的幀率 34 35 EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(srcClip);//獲取clip的curveBinds 36 37 for (int i = 0; i < curveBindings.Length; i++) 38 { 39 AnimationUtility.SetEditorCurve(newClip, curveBindings[i], AnimationUtility.GetEditorCurve(srcClip, curveBindings[i]));//設置新clip的curve 40 } 41 42 AssetDatabase.CreateAsset(newClip, animationPath); //AssetDatabase中的路徑都是相對Asset的 如果指定路徑已存在asset則會被刪除,然后創建新的asset 43 44 AssetDatabase.SaveAssets();//保存修改 45 46 AssetDatabase.Refresh(); 47 48 } 49 } 50 }
上面的代碼就是將FBX中的動畫文件的數據設置到一個新的AnimationClip上
需要注意的是,Unity中有兩種AnimationClip
第一種是直接右鍵Create-Animation直接創建
創建后選擇Debug
可以看到Legacy選項沒有選上
第二種是選擇場景中的一個物體,然后打開Animtion窗口,可以看到出現了Create按鈕
同樣創建后選擇Debug可以看到
這種動畫的Legacy選項是被勾選的
具體的區別就不說了,不過在上面的代碼中有這樣一段
1 EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(srcClip);//獲取clip的curveBinds 2 3 for (int i = 0; i < curveBindings.Length; i++) 4 { 5 AnimationUtility.SetEditorCurve(newClip, curveBindings[i], AnimationUtility.GetEditorCurve(srcClip, curveBindings[i]));//設置新clip的curve 6 }
非Legacy動畫使用GetCurveBindings、GetEditorCurve和SetEditorCurve方法
Legacy要使用GetObjectReferenceCurveBindings、GetObjectReferenceCurve和SetObjectReferenceCurve方法
那么單個AnimationClip復制已經完成了,接下來就是批量的復制
1 [MenuItem("CYL/CopyAnimationClip")] 2 public static void AnimationClipsCopy() 3 { 4 Object[] go = Selection.objects; 5 6 string Path = AssetDatabase.GetAssetPath(go[0]); 7 8 string parentPath = Editor_Ani.getParentPathForAsset(Path); 9 10 for (int i = 0; i < go.Length; i++) 11 { 12 string fbxPath = AssetDatabase.GetAssetPath(go[i]); 13 14 AnimCopy(fbxPath, parentPath, go[i].name.Split('@')[1]); 15 } 16 } 17 18 19 20 /// <summary> 21 /// 返回傳入目錄的父目錄(相對於asset) 22 /// </summary> 23 /// <param name="assetPath"></param> 24 /// <returns></returns> 25 public static string getParentPathForAsset(string assetPath) 26 { 27 string[] pathName = assetPath.Split('/'); 28 string parentPath = ""; 29 30 if (pathName.Length < 2 || pathName[pathName.Length - 1] == "") 31 { 32 Debug.Log(assetPath + @"沒有父目錄!"); 33 return parentPath; 34 } 35 36 for (int i = 0; i < pathName.Length - 1; i++) 37 { 38 39 if (i != pathName.Length - 2) 40 parentPath += pathName[i] + @"/"; 41 else 42 parentPath += pathName[i]; 43 } 44 45 return parentPath; 46 }
選中所有的FBX再點擊擴展的菜單欄按鈕就可以了