最近在开发项目时,需要处理大量的动画,于是就网上查找资料,然后写了这么编辑器工具:

就是在模型导入时,根据配置文件自动切割动画。

首先我们需要封装两个类:一个模型类和一个动画类

  1. public class ModelFbx
  2. {
  3. #region -- 变量定义
  4. public string modelName; //模型名称
  5. public Clip[] clips; //模型所包含的动画
  6. #endregion
  7. }
  8.  
  9. public class Clip
  10. {
  11. #region -- 变量定义
  12. public string clipName; //动画名称
  13. public int firstFrame; //动画第一帧
  14. public int lastFrame; //动画最后一帧
  15. public bool isLoop; //是否循环
  16. #endregion
  17.  
  18. #region -- 自定义函数
  19. /// <summary>
  20. /// 构造动画信息
  21. /// </summary>
  22. /// <param name="_clipName">动画名称</param>
  23. /// <param name="_firstFrame">动画第一帧</param>
  24. /// <param name="_lastFrame">动画最后一帧</param>
  25. /// <param name="_isLoop">动画是否循环</param>
  26. public Clip(string _clipName, int _firstFrame, int _lastFrame, bool _isLoop)
  27. {
  28. clipName = _clipName;
  29. firstFrame = _firstFrame;
  30. lastFrame = _lastFrame;
  31. isLoop = _isLoop;
  32. }
  33. #endregion
  34.  
  35. }

然后我们封装一个类,来读取配置文件并初始化切割信息的类

  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using System.Xml;
  4. using System.IO;
  5.  
  6. public static class AnimationClipConfig
  7. {
  8. #region -- 变量定义
  9. public static string ConfigPath = "/_Scripts/Editor/CutAnimation/Config.xml";
  10. private static bool mIsInit = false;//配置信息是否初始化
  11. public static List<ModelFbx> modelList = new List<ModelFbx>();
  12. #endregion
  13.  
  14. #region -- 自定义函数
  15. public static bool Enable
  16. {
  17. get
  18. {
  19. string _enable = Read(Application.dataPath + ConfigPath, new string[] { "Root", "Enable" });
  20. return bool.Parse(_enable);
  21. }
  22. }
  23. /// <summary>
  24. /// 初始化配置信息
  25. /// </summary>
  26. /// <returns>返回初始化是否成功</returns>
  27. public static bool Init()
  28. {
  29. if (mIsInit)
  30. {
  31. return true;
  32. }
  33. mIsInit = true;
  34.  
  35. return InitModeList();
  36. }
  37. private static bool InitModeList()
  38. {
  39. string _path = Application.dataPath + ConfigPath;
  40. if (File.Exists(_path))
  41. {
  42. XmlDocument _xmlDoc = new XmlDocument();
  43. XmlReaderSettings _set = new XmlReaderSettings();
  44. _set.IgnoreComments = true;
  45. XmlReader _reader = XmlReader.Create(_path, _set);
  46. _xmlDoc.Load(_reader);
  47. _reader.Close();
  48. XmlNodeList _nodeList = _xmlDoc.SelectSingleNode("Root").ChildNodes;
  49. foreach (XmlElement _xe in _nodeList)
  50. {
  51. if (_xe.Name == "ModelFbx")
  52. {
  53. ModelFbx _modelFbx = new ModelFbx();
  54. foreach (XmlElement _x1 in _xe.ChildNodes)
  55. {
  56. if (_x1.Name == "ModelName")
  57. {
  58. _modelFbx.modelName = _x1.InnerText;
  59. }
  60. if (_x1.Name == "Clips")
  61. {
  62. _modelFbx.clips = new Clip[_x1.ChildNodes.Count];
  63. int _index = ;
  64. foreach (XmlElement _x2 in _x1.ChildNodes)
  65. {
  66. string _clipName = "";
  67. int _firstFrame = ;
  68. int _lastFrame = ;
  69. bool _isLoop = false;
  70. foreach (XmlElement _x3 in _x2.ChildNodes)
  71. {
  72. if (_x3.Name == "ClipName")
  73. {
  74. _clipName = _x3.InnerText;
  75. }
  76. if (_x3.Name == "FirstFrame")
  77. {
  78. _firstFrame = int.Parse(_x3.InnerText);
  79. }
  80. if (_x3.Name == "LastFrame")
  81. {
  82. _lastFrame = int.Parse(_x3.InnerText);
  83. }
  84. if (_x3.Name == "IsLoop")
  85. {
  86. _isLoop = bool.Parse(_x3.InnerText);
  87. }
  88. }
  89. _modelFbx.clips[_index] = new Clip(_clipName, _firstFrame, _lastFrame, _isLoop);
  90. _index++;
  91. }
  92. }
  93. }
  94. modelList.Add(_modelFbx);
  95. }
  96. }
  97. return true;
  98. }
  99. else
  100. {
  101. Debug.LogError("无法找打" + _path + "文件,请检查配置文件路径(ConfigPath)是否正确");
  102. return false;
  103. }
  104. }
  105.  
  106. /// <summary>
  107. /// 读取 XML 文件指定子节点数据
  108. /// </summary>
  109. /// <param name="_path">文件读取路径</param>
  110. /// <param name="_xmlNodes">节点数组</param>
  111. /// <returns></returns>
  112. private static string Read(string _path, string[] _xmlNodes)
  113. {
  114. string _innerstr = "";//返回值
  115. XmlDocument _xmlDoc = new XmlDocument();
  116. XmlReaderSettings _set = new XmlReaderSettings();
  117. _set.IgnoreComments = true;
  118. //判断文件是否存在
  119. if (File.Exists(_path))
  120. {
  121. _xmlDoc.Load(XmlReader.Create(_path, _set));
  122. }
  123. else
  124. {
  125. Debug.LogError("目标文件不存在,请检查路径是否有误");
  126. return null;
  127. }
  128. int _nodeNum = _xmlNodes.Length;
  129. int _counter = ;
  130. XmlNodeList _nodelist = _xmlDoc.SelectSingleNode(_xmlNodes[]).ChildNodes;
  131. if (_nodelist == null)
  132. {
  133. return _innerstr;
  134. }
  135. while (_counter < _nodeNum)
  136. {
  137. bool _checkok = false;
  138. foreach (XmlNode _element in _nodelist)
  139. {
  140. if (_element.Name == _xmlNodes[_counter])
  141. {
  142. _checkok = true;
  143. _counter++;
  144. if (_counter >= _nodeNum)
  145. {
  146. _innerstr = _element.InnerText;
  147. _nodelist = null;
  148. break;
  149. }
  150. _nodelist = _element.ChildNodes;
  151. break;
  152. }
  153. }
  154. if (!_checkok)
  155. {
  156. break;
  157. }
  158. }
  159. return _innerstr;
  160. }
  161. #endregion
  162.  
  163. }

接下来就是切割动画了

  1. using UnityEngine;
  2. using UnityEditor;
  3.  
  4. public class CutAnimation : AssetPostprocessor
  5. {
  6. #region -- 系统函数
  7. /// <summary>
  8. /// 模型导入之前调用
  9. /// </summary>
  10. public void OnPreprocessModel()
  11. {
  12. //是否启用动画切割
  13. if (!AnimationClipConfig.Enable)
  14. {
  15. return;
  16. }
  17.  
  18. //当前正在导入的模型
  19. ModelImporter _modelImporter = (ModelImporter)assetImporter;
  20.  
  21. if (AnimationClipConfig.Init())
  22. {
  23. foreach (ModelFbx item in AnimationClipConfig.modelList)
  24. {
  25. //当前导入模型的路径包含AnimationClipConfig.modelList数据表中的模型名字,那就要对这个模型的动画进行切割
  26. if (assetPath.Contains(item.modelName))
  27. {
  28. _modelImporter.animationType = ModelImporterAnimationType.Generic;
  29. _modelImporter.generateAnimations = ModelImporterGenerateAnimations.GenerateAnimations;
  30. ModelImporterClipAnimation[] _animations = new ModelImporterClipAnimation[item.clips.Length];
  31. for (int i = ; i < item.clips.Length; i++)
  32. {
  33. _animations[i] = SetClipAnimation(item.clips[i].clipName, item.clips[i].firstFrame, item.clips[i].lastFrame, item.clips[i].isLoop);
  34. }
  35. _modelImporter.clipAnimations = _animations;
  36. }
  37. }
  38. }
  39. else
  40. {
  41. Debug.LogError("无法找打" + Application.dataPath+AnimationClipConfig.ConfigPath + "文件,请检查配置文件路径(mCofigPath)是否正确");
  42. }
  43. }
  44. #endregion
  45.  
  46. #region -- 自定义函数
  47. private ModelImporterClipAnimation SetClipAnimation(string _clipName, int _firstFrame, int _lastFrame, bool _isLoop)
  48. {
  49. ModelImporterClipAnimation _clip = new ModelImporterClipAnimation();
  50. _clip.name = _clipName;
  51. _clip.firstFrame =_firstFrame;
  52. _clip.lastFrame = _lastFrame;
  53. _clip.loop = _isLoop;
  54. if (_isLoop)
  55. {
  56. _clip.wrapMode = WrapMode.Loop;
  57. }
  58. else
  59. {
  60. _clip.wrapMode = WrapMode.Default;
  61. }
  62. return _clip;
  63. }
  64. #endregion
  65.  
  66. }

感觉也没啥好说的,就直接分享代码了。而且我觉得这个功能比较鸡肋,适用性不是很广,只能在一些特定情况下用到。

下面是我的配置文件和文件结构:

  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3. <Root>
  4. <Enable>True</Enable><!--是否启用。启用:True;禁用:False-->
  5.  
  6. <ModelFbx><!--模型-->
  7. <ModelName></ModelName><!--模型名称(string)-->
  8. <Clips><!--动画集-->
  9. <Clip><!--动画-->
  10. <ClipName>Start</ClipName><!--动画名称(string)-->
  11. <FirstFrame></FirstFrame><!--动画第一帧(int)-->
  12. <LastFrame></LastFrame><!--动画最后一帧(int)-->
  13. <IsLoop>False</IsLoop><!--是否循环(bool)-->
  14. </Clip>
  15.  
  16. <Clip>
  17. <ClipName>Take</ClipName>
  18. <FirstFrame></FirstFrame>
  19. <LastFrame></LastFrame>
  20. <IsLoop>False</IsLoop>
  21. </Clip>
  22.  
  23. <Clip>
  24. <ClipName>End</ClipName>
  25. <FirstFrame></FirstFrame>
  26. <LastFrame></LastFrame>
  27. <IsLoop>False</IsLoop>
  28. </Clip>
  29. </Clips>
  30. </ModelFbx>
  31.  
  32. <ModelFbx>
  33. <ModelName></ModelName>
  34. <Clips>
  35. <Clip>
  36. <ClipName>Start</ClipName>
  37. <FirstFrame></FirstFrame>
  38. <LastFrame></LastFrame>
  39. <IsLoop>False</IsLoop>
  40. </Clip>
  41.  
  42. <Clip>
  43. <ClipName>Take</ClipName>
  44. <FirstFrame></FirstFrame>
  45. <LastFrame></LastFrame>
  46. <IsLoop>False</IsLoop>
  47. </Clip>
  48.  
  49. <Clip>
  50. <ClipName>End</ClipName>
  51. <FirstFrame></FirstFrame>
  52. <LastFrame></LastFrame>
  53. <IsLoop>False</IsLoop>
  54. </Clip>
  55. </Clips>
  56. </ModelFbx>
  57.  
  58. <ModelFbx>
  59. <ModelName></ModelName>
  60. <Clips>
  61. <Clip>
  62. <ClipName>Start</ClipName>
  63. <FirstFrame></FirstFrame>
  64. <LastFrame></LastFrame>
  65. <IsLoop>False</IsLoop>
  66. </Clip>
  67.  
  68. <Clip>
  69. <ClipName>Take</ClipName>
  70. <FirstFrame></FirstFrame>
  71. <LastFrame></LastFrame>
  72. <IsLoop>False</IsLoop>
  73. </Clip>
  74.  
  75. <Clip>
  76. <ClipName>End</ClipName>
  77. <FirstFrame></FirstFrame>
  78. <LastFrame></LastFrame>
  79. <IsLoop>False</IsLoop>
  80. </Clip>
  81. </Clips>
  82. </ModelFbx>
  83.  
  84. <ModelFbx>
  85. <ModelName></ModelName>
  86. <Clips>
  87. <Clip>
  88. <ClipName>Start</ClipName>
  89. <FirstFrame></FirstFrame>
  90. <LastFrame></LastFrame>
  91. <IsLoop>False</IsLoop>
  92. </Clip>
  93.  
  94. <Clip>
  95. <ClipName>Take</ClipName>
  96. <FirstFrame></FirstFrame>
  97. <LastFrame></LastFrame>
  98. <IsLoop>False</IsLoop>
  99. </Clip>
  100.  
  101. <Clip>
  102. <ClipName>End</ClipName>
  103. <FirstFrame></FirstFrame>
  104. <LastFrame></LastFrame>
  105. <IsLoop>False</IsLoop>
  106. </Clip>
  107. </Clips>
  108. </ModelFbx>
  109.  
  110. <ModelFbx>
  111. <ModelName></ModelName>
  112. <Clips>
  113. <Clip>
  114. <ClipName>Start</ClipName>
  115. <FirstFrame></FirstFrame>
  116. <LastFrame></LastFrame>
  117. <IsLoop>False</IsLoop>
  118. </Clip>
  119.  
  120. <Clip>
  121. <ClipName>Take</ClipName>
  122. <FirstFrame></FirstFrame>
  123. <LastFrame></LastFrame>
  124. <IsLoop>False</IsLoop>
  125. </Clip>
  126.  
  127. <Clip>
  128. <ClipName>End</ClipName>
  129. <FirstFrame></FirstFrame>
  130. <LastFrame></LastFrame>
  131. <IsLoop>False</IsLoop>
  132. </Clip>
  133. </Clips>
  134. </ModelFbx>
  135.  
  136. <ModelFbx>
  137. <ModelName></ModelName>
  138. <Clips>
  139. <Clip>
  140. <ClipName>Start</ClipName>
  141. <FirstFrame></FirstFrame>
  142. <LastFrame></LastFrame>
  143. <IsLoop>False</IsLoop>
  144. </Clip>
  145.  
  146. <Clip>
  147. <ClipName>Take</ClipName>
  148. <FirstFrame></FirstFrame>
  149. <LastFrame></LastFrame>
  150. <IsLoop>False</IsLoop>
  151. </Clip>
  152.  
  153. <Clip>
  154. <ClipName>End</ClipName>
  155. <FirstFrame></FirstFrame>
  156. <LastFrame></LastFrame>
  157. <IsLoop>False</IsLoop>
  158. </Clip>
  159. </Clips>
  160. </ModelFbx>
  161.  
  162. <ModelFbx>
  163. <ModelName></ModelName>
  164. <Clips>
  165. <Clip>
  166. <ClipName>Start</ClipName>
  167. <FirstFrame></FirstFrame>
  168. <LastFrame></LastFrame>
  169. <IsLoop>False</IsLoop>
  170. </Clip>
  171.  
  172. <Clip>
  173. <ClipName>Take</ClipName>
  174. <FirstFrame></FirstFrame>
  175. <LastFrame></LastFrame>
  176. <IsLoop>False</IsLoop>
  177. </Clip>
  178.  
  179. <Clip>
  180. <ClipName>End</ClipName>
  181. <FirstFrame></FirstFrame>
  182. <LastFrame></LastFrame>
  183. <IsLoop>False</IsLoop>
  184. </Clip>
  185. </Clips>
  186. </ModelFbx>
  187.  
  188. <ModelFbx>
  189. <ModelName></ModelName>
  190. <Clips>
  191. <Clip>
  192. <ClipName>Start</ClipName>
  193. <FirstFrame></FirstFrame>
  194. <LastFrame></LastFrame>
  195. <IsLoop>False</IsLoop>
  196. </Clip>
  197.  
  198. <Clip>
  199. <ClipName>Take</ClipName>
  200. <FirstFrame></FirstFrame>
  201. <LastFrame></LastFrame>
  202. <IsLoop>False</IsLoop>
  203. </Clip>
  204.  
  205. <Clip>
  206. <ClipName>End</ClipName>
  207. <FirstFrame></FirstFrame>
  208. <LastFrame></LastFrame>
  209. <IsLoop>False</IsLoop>
  210. </Clip>
  211. </Clips>
  212. </ModelFbx>
  213.  
  214. <ModelFbx>
  215. <ModelName></ModelName>
  216. <Clips>
  217. <Clip>
  218. <ClipName>Start</ClipName>
  219. <FirstFrame></FirstFrame>
  220. <LastFrame></LastFrame>
  221. <IsLoop>False</IsLoop>
  222. </Clip>
  223.  
  224. <Clip>
  225. <ClipName>Take</ClipName>
  226. <FirstFrame></FirstFrame>
  227. <LastFrame></LastFrame>
  228. <IsLoop>False</IsLoop>
  229. </Clip>
  230.  
  231. <Clip>
  232. <ClipName>End</ClipName>
  233. <FirstFrame></FirstFrame>
  234. <LastFrame></LastFrame>
  235. <IsLoop>False</IsLoop>
  236. </Clip>
  237. </Clips>
  238. </ModelFbx>
  239.  
  240. <ModelFbx>
  241. <ModelName></ModelName>
  242. <Clips>
  243. <Clip>
  244. <ClipName>Start</ClipName>
  245. <FirstFrame></FirstFrame>
  246. <LastFrame></LastFrame>
  247. <IsLoop>False</IsLoop>
  248. </Clip>
  249.  
  250. <Clip>
  251. <ClipName>Take</ClipName>
  252. <FirstFrame></FirstFrame>
  253. <LastFrame></LastFrame>
  254. <IsLoop>False</IsLoop>
  255. </Clip>
  256.  
  257. <Clip>
  258. <ClipName>End</ClipName>
  259. <FirstFrame></FirstFrame>
  260. <LastFrame></LastFrame>
  261. <IsLoop>False</IsLoop>
  262. </Clip>
  263. </Clips>
  264. </ModelFbx>
  265.  
  266. <ModelFbx>
  267. <ModelName></ModelName>
  268. <Clips>
  269. <Clip>
  270. <ClipName>Start</ClipName>
  271. <FirstFrame></FirstFrame>
  272. <LastFrame></LastFrame>
  273. <IsLoop>False</IsLoop>
  274. </Clip>
  275.  
  276. <Clip>
  277. <ClipName>Take</ClipName>
  278. <FirstFrame></FirstFrame>
  279. <LastFrame></LastFrame>
  280. <IsLoop>False</IsLoop>
  281. </Clip>
  282.  
  283. <Clip>
  284. <ClipName>End</ClipName>
  285. <FirstFrame></FirstFrame>
  286. <LastFrame></LastFrame>
  287. <IsLoop>False</IsLoop>
  288. </Clip>
  289. </Clips>
  290. </ModelFbx>
  291.  
  292. </Root>

Unity自动切割动画的更多相关文章

  1. Unity自动生成AnimatorController

    上一篇写了如何自动切割动画,这一篇写如何自动生成AnimatorController. 之前网上查了很多资料,看的一直很蒙,看不懂是怎么回事的,这里我先给大家明确几个概念: 画的不好,大家将就着看,写 ...

  2. 关于Unity中Mecanim动画的动画状态代码控制与代码生成动画控制器

    对于多量的.复杂的.有规律的控制器使用代码生成 动画状态代码控制 1:每个动画状态,比如进入状态,离开状态, 等都有可能需要代码来参与和处理,比如,进入这个动画单元后做哪些事情,来开这个动画单元后做哪 ...

  3. Unity 2D骨骼动画2:创建真实动画

    http://bbs.9ria.com/thread-401781-1-1.html 在这个系列,我们将关注Unity引擎提供的基于骨骼动画工具.它的主要思想是为了把它应用到你自己的游戏来介绍和教基本 ...

  4. Unity2D研究院之自动生成动画、AnimationController、Prefab(一)

    http://www.xuanyusong.com/archives/3243 国庆了,回家了.时刻还是要吃一颗学习的心,在家了也要抽出时间好好学习一下.之前MOMO一直没研究过Unity2D,今天研 ...

  5. unity 对Animator动画系统的研究

    unity的新动画系统叫Mecanim,使用Animator来取代旧系统Animation,按Unity文档的惯例:知识点主要分2部分:unity manual和unity script,读者可以边看 ...

  6. Unity MegaFiers 顶点动画

        使用 MegaFiers 插件,能够使得Unity支持顶点动画的播放. 官方视频教程例如以下: 在这里简单測试使用下,环境例如以下: Blender 2.72 Unity 4.5.4 Mega ...

  7. Linux下nginx生成日志自动切割

    1.编辑切割日志的 shell 程序,目录自定 #vi /data/nginx/cut_nginx_log.sh 输入代码: #!/bin/bash # This script run at 00:0 ...

  8. 【shell脚本】nginx每天自动切割日志脚本

    nginx每天日志量比较大的时候,最好每天自动切割,存储,这样可以方面以后的查询和分析 #!/bin/sh ################### #filename: nginx_log_rotat ...

  9. linux系统日志自动切割工具----logrotate

    参考资料 :https://www.cnblogs.com/kevingrace/p/6307298.html 对于Linux系统安全来说,日志文件是极其重要的工具.不知为何,我发现很多运维同学的服务 ...

随机推荐

  1. 其它 nginx

    原地址忘了 常用命令: 在CMD下输入如下命令,可以强行关闭所有Nginx进程 taskkill /f /im nginx.exe start nginx nginx -s stop nginx -s ...

  2. 2016word多级列表 一级标题居中后偏左

    一.如下图所示,定义好多级列表之后设置标题,但是发现标题居中后偏左. 二.选择多级列表,设置居左对齐

  3. Tomcat的三种安装方式:解压版、安装版、配置成Windows服务版

    https://blog.csdn.net/Jessica_XLF/article/details/81711429

  4. 认识border

    标签(空格分隔): border border的认识: border:边框的意思,描述盒子的边框,边框有三个要素: 粗细, 线性样式 ,颜色: <!DOCTYPE html> <ht ...

  5. windows下git 同步数据到github的常见问题

    常用排错方法: 1,查看连接是否正常. 2,push数据有时会报错,这是由于远程repository和我本地的repository冲突造成. 解决方法: 1.使用强制push的方法: git push ...

  6. spring cloud Ribbon

    参考:https://www.jianshu.com/p/1bd66db5dc46 Ribbon 是什么 spring cloud ribbon 是一个基于HTTP 和 TCP 的客户端负载均衡工具, ...

  7. oracle数据库查询语句case的用法

    实现功能: 1.先查询status=2的记录,如果查询到记录则返回第一条记录的Product_Name:2.如果查询不到status=2的记录,则判断status=1的记录是否存在,不存在则返回“请耐 ...

  8. ISE初始化

    step1:输入setup进行初始化,如下图: step2:输入setup进行初始化,如下图:

  9. hosts更改域名之后怎么生效

    原先配置好的ip + 域名,现在更改了域名,可是保存了hosts之后,访问到的还是原先的域名. 现将方法记录如下,亲测有效: 新建(在桌面新建即可)一个txt文件,将hosts文件里所有的配置复制过来 ...

  10. 分布式之redis

    正文 1.为什么使用redis 分析:博主觉得在项目中使用redis,主要是从两个角度去考虑:性能和并发.当然,redis还具备可以做分布式锁等其他功能,但是如果只是为了分布式锁这些其他功能,完全还有 ...