Unity自动切割动画
最近在开发项目时,需要处理大量的动画,于是就网上查找资料,然后写了这么编辑器工具:
就是在模型导入时,根据配置文件自动切割动画。
首先我们需要封装两个类:一个模型类和一个动画类
- public class ModelFbx
- {
- #region -- 变量定义
- public string modelName; //模型名称
- public Clip[] clips; //模型所包含的动画
- #endregion
- }
- public class Clip
- {
- #region -- 变量定义
- public string clipName; //动画名称
- public int firstFrame; //动画第一帧
- public int lastFrame; //动画最后一帧
- public bool isLoop; //是否循环
- #endregion
- #region -- 自定义函数
- /// <summary>
- /// 构造动画信息
- /// </summary>
- /// <param name="_clipName">动画名称</param>
- /// <param name="_firstFrame">动画第一帧</param>
- /// <param name="_lastFrame">动画最后一帧</param>
- /// <param name="_isLoop">动画是否循环</param>
- public Clip(string _clipName, int _firstFrame, int _lastFrame, bool _isLoop)
- {
- clipName = _clipName;
- firstFrame = _firstFrame;
- lastFrame = _lastFrame;
- isLoop = _isLoop;
- }
- #endregion
- }
然后我们封装一个类,来读取配置文件并初始化切割信息的类
- using UnityEngine;
- using System.Collections.Generic;
- using System.Xml;
- using System.IO;
- public static class AnimationClipConfig
- {
- #region -- 变量定义
- public static string ConfigPath = "/_Scripts/Editor/CutAnimation/Config.xml";
- private static bool mIsInit = false;//配置信息是否初始化
- public static List<ModelFbx> modelList = new List<ModelFbx>();
- #endregion
- #region -- 自定义函数
- public static bool Enable
- {
- get
- {
- string _enable = Read(Application.dataPath + ConfigPath, new string[] { "Root", "Enable" });
- return bool.Parse(_enable);
- }
- }
- /// <summary>
- /// 初始化配置信息
- /// </summary>
- /// <returns>返回初始化是否成功</returns>
- public static bool Init()
- {
- if (mIsInit)
- {
- return true;
- }
- mIsInit = true;
- return InitModeList();
- }
- private static bool InitModeList()
- {
- string _path = Application.dataPath + ConfigPath;
- if (File.Exists(_path))
- {
- XmlDocument _xmlDoc = new XmlDocument();
- XmlReaderSettings _set = new XmlReaderSettings();
- _set.IgnoreComments = true;
- XmlReader _reader = XmlReader.Create(_path, _set);
- _xmlDoc.Load(_reader);
- _reader.Close();
- XmlNodeList _nodeList = _xmlDoc.SelectSingleNode("Root").ChildNodes;
- foreach (XmlElement _xe in _nodeList)
- {
- if (_xe.Name == "ModelFbx")
- {
- ModelFbx _modelFbx = new ModelFbx();
- foreach (XmlElement _x1 in _xe.ChildNodes)
- {
- if (_x1.Name == "ModelName")
- {
- _modelFbx.modelName = _x1.InnerText;
- }
- if (_x1.Name == "Clips")
- {
- _modelFbx.clips = new Clip[_x1.ChildNodes.Count];
- int _index = ;
- foreach (XmlElement _x2 in _x1.ChildNodes)
- {
- string _clipName = "";
- int _firstFrame = ;
- int _lastFrame = ;
- bool _isLoop = false;
- foreach (XmlElement _x3 in _x2.ChildNodes)
- {
- if (_x3.Name == "ClipName")
- {
- _clipName = _x3.InnerText;
- }
- if (_x3.Name == "FirstFrame")
- {
- _firstFrame = int.Parse(_x3.InnerText);
- }
- if (_x3.Name == "LastFrame")
- {
- _lastFrame = int.Parse(_x3.InnerText);
- }
- if (_x3.Name == "IsLoop")
- {
- _isLoop = bool.Parse(_x3.InnerText);
- }
- }
- _modelFbx.clips[_index] = new Clip(_clipName, _firstFrame, _lastFrame, _isLoop);
- _index++;
- }
- }
- }
- modelList.Add(_modelFbx);
- }
- }
- return true;
- }
- else
- {
- Debug.LogError("无法找打" + _path + "文件,请检查配置文件路径(ConfigPath)是否正确");
- return false;
- }
- }
- /// <summary>
- /// 读取 XML 文件指定子节点数据
- /// </summary>
- /// <param name="_path">文件读取路径</param>
- /// <param name="_xmlNodes">节点数组</param>
- /// <returns></returns>
- private static string Read(string _path, string[] _xmlNodes)
- {
- string _innerstr = "";//返回值
- XmlDocument _xmlDoc = new XmlDocument();
- XmlReaderSettings _set = new XmlReaderSettings();
- _set.IgnoreComments = true;
- //判断文件是否存在
- if (File.Exists(_path))
- {
- _xmlDoc.Load(XmlReader.Create(_path, _set));
- }
- else
- {
- Debug.LogError("目标文件不存在,请检查路径是否有误");
- return null;
- }
- int _nodeNum = _xmlNodes.Length;
- int _counter = ;
- XmlNodeList _nodelist = _xmlDoc.SelectSingleNode(_xmlNodes[]).ChildNodes;
- if (_nodelist == null)
- {
- return _innerstr;
- }
- while (_counter < _nodeNum)
- {
- bool _checkok = false;
- foreach (XmlNode _element in _nodelist)
- {
- if (_element.Name == _xmlNodes[_counter])
- {
- _checkok = true;
- _counter++;
- if (_counter >= _nodeNum)
- {
- _innerstr = _element.InnerText;
- _nodelist = null;
- break;
- }
- _nodelist = _element.ChildNodes;
- break;
- }
- }
- if (!_checkok)
- {
- break;
- }
- }
- return _innerstr;
- }
- #endregion
- }
接下来就是切割动画了
- using UnityEngine;
- using UnityEditor;
- public class CutAnimation : AssetPostprocessor
- {
- #region -- 系统函数
- /// <summary>
- /// 模型导入之前调用
- /// </summary>
- public void OnPreprocessModel()
- {
- //是否启用动画切割
- if (!AnimationClipConfig.Enable)
- {
- return;
- }
- //当前正在导入的模型
- ModelImporter _modelImporter = (ModelImporter)assetImporter;
- if (AnimationClipConfig.Init())
- {
- foreach (ModelFbx item in AnimationClipConfig.modelList)
- {
- //当前导入模型的路径包含AnimationClipConfig.modelList数据表中的模型名字,那就要对这个模型的动画进行切割
- if (assetPath.Contains(item.modelName))
- {
- _modelImporter.animationType = ModelImporterAnimationType.Generic;
- _modelImporter.generateAnimations = ModelImporterGenerateAnimations.GenerateAnimations;
- ModelImporterClipAnimation[] _animations = new ModelImporterClipAnimation[item.clips.Length];
- for (int i = ; i < item.clips.Length; i++)
- {
- _animations[i] = SetClipAnimation(item.clips[i].clipName, item.clips[i].firstFrame, item.clips[i].lastFrame, item.clips[i].isLoop);
- }
- _modelImporter.clipAnimations = _animations;
- }
- }
- }
- else
- {
- Debug.LogError("无法找打" + Application.dataPath+AnimationClipConfig.ConfigPath + "文件,请检查配置文件路径(mCofigPath)是否正确");
- }
- }
- #endregion
- #region -- 自定义函数
- private ModelImporterClipAnimation SetClipAnimation(string _clipName, int _firstFrame, int _lastFrame, bool _isLoop)
- {
- ModelImporterClipAnimation _clip = new ModelImporterClipAnimation();
- _clip.name = _clipName;
- _clip.firstFrame =_firstFrame;
- _clip.lastFrame = _lastFrame;
- _clip.loop = _isLoop;
- if (_isLoop)
- {
- _clip.wrapMode = WrapMode.Loop;
- }
- else
- {
- _clip.wrapMode = WrapMode.Default;
- }
- return _clip;
- }
- #endregion
- }
感觉也没啥好说的,就直接分享代码了。而且我觉得这个功能比较鸡肋,适用性不是很广,只能在一些特定情况下用到。
下面是我的配置文件和文件结构:
- <?xml version="1.0" encoding="utf-8"?>
- <Root>
- <Enable>True</Enable><!--是否启用。启用:True;禁用:False-->
- <ModelFbx><!--模型-->
- <ModelName></ModelName><!--模型名称(string)-->
- <Clips><!--动画集-->
- <Clip><!--动画-->
- <ClipName>Start</ClipName><!--动画名称(string)-->
- <FirstFrame></FirstFrame><!--动画第一帧(int)-->
- <LastFrame></LastFrame><!--动画最后一帧(int)-->
- <IsLoop>False</IsLoop><!--是否循环(bool)-->
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- <ModelFbx>
- <ModelName></ModelName>
- <Clips>
- <Clip>
- <ClipName>Start</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>Take</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- <Clip>
- <ClipName>End</ClipName>
- <FirstFrame></FirstFrame>
- <LastFrame></LastFrame>
- <IsLoop>False</IsLoop>
- </Clip>
- </Clips>
- </ModelFbx>
- </Root>
Unity自动切割动画的更多相关文章
- Unity自动生成AnimatorController
上一篇写了如何自动切割动画,这一篇写如何自动生成AnimatorController. 之前网上查了很多资料,看的一直很蒙,看不懂是怎么回事的,这里我先给大家明确几个概念: 画的不好,大家将就着看,写 ...
- 关于Unity中Mecanim动画的动画状态代码控制与代码生成动画控制器
对于多量的.复杂的.有规律的控制器使用代码生成 动画状态代码控制 1:每个动画状态,比如进入状态,离开状态, 等都有可能需要代码来参与和处理,比如,进入这个动画单元后做哪些事情,来开这个动画单元后做哪 ...
- Unity 2D骨骼动画2:创建真实动画
http://bbs.9ria.com/thread-401781-1-1.html 在这个系列,我们将关注Unity引擎提供的基于骨骼动画工具.它的主要思想是为了把它应用到你自己的游戏来介绍和教基本 ...
- Unity2D研究院之自动生成动画、AnimationController、Prefab(一)
http://www.xuanyusong.com/archives/3243 国庆了,回家了.时刻还是要吃一颗学习的心,在家了也要抽出时间好好学习一下.之前MOMO一直没研究过Unity2D,今天研 ...
- unity 对Animator动画系统的研究
unity的新动画系统叫Mecanim,使用Animator来取代旧系统Animation,按Unity文档的惯例:知识点主要分2部分:unity manual和unity script,读者可以边看 ...
- Unity MegaFiers 顶点动画
使用 MegaFiers 插件,能够使得Unity支持顶点动画的播放. 官方视频教程例如以下: 在这里简单測试使用下,环境例如以下: Blender 2.72 Unity 4.5.4 Mega ...
- Linux下nginx生成日志自动切割
1.编辑切割日志的 shell 程序,目录自定 #vi /data/nginx/cut_nginx_log.sh 输入代码: #!/bin/bash # This script run at 00:0 ...
- 【shell脚本】nginx每天自动切割日志脚本
nginx每天日志量比较大的时候,最好每天自动切割,存储,这样可以方面以后的查询和分析 #!/bin/sh ################### #filename: nginx_log_rotat ...
- linux系统日志自动切割工具----logrotate
参考资料 :https://www.cnblogs.com/kevingrace/p/6307298.html 对于Linux系统安全来说,日志文件是极其重要的工具.不知为何,我发现很多运维同学的服务 ...
随机推荐
- 其它 nginx
原地址忘了 常用命令: 在CMD下输入如下命令,可以强行关闭所有Nginx进程 taskkill /f /im nginx.exe start nginx nginx -s stop nginx -s ...
- 2016word多级列表 一级标题居中后偏左
一.如下图所示,定义好多级列表之后设置标题,但是发现标题居中后偏左. 二.选择多级列表,设置居左对齐
- Tomcat的三种安装方式:解压版、安装版、配置成Windows服务版
https://blog.csdn.net/Jessica_XLF/article/details/81711429
- 认识border
标签(空格分隔): border border的认识: border:边框的意思,描述盒子的边框,边框有三个要素: 粗细, 线性样式 ,颜色: <!DOCTYPE html> <ht ...
- windows下git 同步数据到github的常见问题
常用排错方法: 1,查看连接是否正常. 2,push数据有时会报错,这是由于远程repository和我本地的repository冲突造成. 解决方法: 1.使用强制push的方法: git push ...
- spring cloud Ribbon
参考:https://www.jianshu.com/p/1bd66db5dc46 Ribbon 是什么 spring cloud ribbon 是一个基于HTTP 和 TCP 的客户端负载均衡工具, ...
- oracle数据库查询语句case的用法
实现功能: 1.先查询status=2的记录,如果查询到记录则返回第一条记录的Product_Name:2.如果查询不到status=2的记录,则判断status=1的记录是否存在,不存在则返回“请耐 ...
- ISE初始化
step1:输入setup进行初始化,如下图: step2:输入setup进行初始化,如下图:
- hosts更改域名之后怎么生效
原先配置好的ip + 域名,现在更改了域名,可是保存了hosts之后,访问到的还是原先的域名. 现将方法记录如下,亲测有效: 新建(在桌面新建即可)一个txt文件,将hosts文件里所有的配置复制过来 ...
- 分布式之redis
正文 1.为什么使用redis 分析:博主觉得在项目中使用redis,主要是从两个角度去考虑:性能和并发.当然,redis还具备可以做分布式锁等其他功能,但是如果只是为了分布式锁这些其他功能,完全还有 ...