最近有个新需求,要用代码添加动画的事件,但是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再点击扩展的菜单栏按钮就可以了