开发中经常需要,对美术模型进行一些处理。(以fbx为例)
例如,需要把动作的名字、start和end加入animations的clips。
如果手动操作,就是在模型的Inspector窗口,一个动作点一次加号,然后编辑start和end。一个模型往往十几个动作,这样做很明显浪费人力。
因此需要一个可以自动导入帧数表的工具,工具应该具备一下功能。
1、根据配置(txt或者json)自动设置模型参数
配置的格式根据使用习惯,txt、json都可以,这里使用txt。用File.ReadAllLines(“路径”),可以获取配置的每一行信息,只要按照规定方式填写,就可以解析出我们想要的参数。
例如 动作名+制表符+start+制表符+end。
2、每次导入模型时,自动生效
继承了AssetPostprocessor,并且放到Editor目录下,每次资源发生改变时会自动调用里面的方法。
3、批量处理每一个动作。
如下,将第一步取出来的参数,用下面方法填入clip列表中,然后复制给模型的ModelImporter的clipAnimations。
public class clipArrayListCreater { private List<ModelImporterClipAnimation> clipList = new List<ModelImporterClipAnimation>(); public void addClip(string name, int firstFrame, int lastFrame, bool loop, WrapMode wrapMode) { ModelImporterClipAnimation tempClip = new ModelImporterClipAnimation(); tempClip.name = name; tempClip.firstFrame = firstFrame; tempClip.lastFrame = lastFrame; tempClip.loop = loop; tempClip.wrapMode = wrapMode; clipList.Add(tempClip); } public ModelImporterClipAnimation[] getArray() { return clipList.ToArray(); } }
5、设置模型类型和动作误差
ModelImporter中几个参数一般都在导入时需要处理,animationType ,animationCompression,animationPositionError ,animationRotationError,animationScaleError 。
一般根据需要设置即可。
有几点需要说明
1、帧数表的命名需要一定规范,如,模型名+“帧数表”,
2、模型应该都放到指定目录,方便管理和工具集中处理。
把代码放到工程里,路径按照自己的来,等待转菊完成,就duang的一下帧数表自动导入了。
using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; public class AssetsImportTools : AssetPostprocessor { void OnPreprocessModel() { ModelImporter modelImporter = (ModelImporter)assetImporter; string lode = modelImporter.assetPath; if (lode.Contains("Assets/Avatars/FBX"))//模型目录 {
//模型类型和动作误差 modelImporter.animationType = ModelImporterAnimationType.Legacy; modelImporter.animationCompression = ModelImporterAnimationCompression.KeyframeReduction; modelImporter.animationPositionError = 0.5f; modelImporter.animationRotationError = 0.5f; modelImporter.animationScaleError = 0.5f; lode = lode.Replace(".FBX", "帧数表.txt"); if (!File.Exists(lode)) { Debug.Log(lode + "不存在"); return; } string[] modellist = File.ReadAllLines(lode); editorImporterUtil.clipArrayListCreater creater = new editorImporterUtil.clipArrayListCreater(); for (int i = 0; i < modellist.Length; i++) { if (modellist[i].Contains("//") || string.IsNullOrEmpty(modellist[i]))//注释和空字符串跳过 continue; string[] s = modellist[i].Split(' ');//按照制表符切割为,名称 start end 是否循环(可选参数,非必填) if (s.Length < 3) { if (EditorUtility.DisplayDialog("错误", "{0} 文件的第".EFormat(lode) + (i + 1) + "行出错", "确定")) { return; } } bool isLoop = false; if (s[0] == "idle" )//循环的动作可以在这里设置,也可以在配置中设置 isLoop = true; else isLoop = false; if (s.Length==4) { if (!string.IsNullOrEmpty(s[3])) { isLoop = s[3] == "1"; } } if (isLoop) creater.addClip(s[0], int.Parse(s[1]), int.Parse(s[2]), false, WrapMode.Loop); else creater.addClip(s[0], int.Parse(s[1]), int.Parse(s[2]), false, WrapMode.Default); modelImporter.clipAnimations = creater.getArray(); } } } } namespace editorImporterUtil { public class clipArrayListCreater { private List<ModelImporterClipAnimation> clipList = new List<ModelImporterClipAnimation>(); public void addClip(string name, int firstFrame, int lastFrame, bool loop, WrapMode wrapMode) { ModelImporterClipAnimation tempClip = new ModelImporterClipAnimation(); tempClip.name = name; tempClip.firstFrame = firstFrame; tempClip.lastFrame = lastFrame; tempClip.loop = loop; tempClip.wrapMode = wrapMode; clipList.Add(tempClip); } public ModelImporterClipAnimation[] getArray() { return clipList.ToArray(); } } }