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系统安全来说,日志文件是极其重要的工具.不知为何,我发现很多运维同学的服务 ...
随机推荐
- docker镜像无法下载或者下载缓慢
解决docker镜像无法下载的问题 2015年10月02日 16:01:05 阅读数:20776 克服跨洋网络延迟,使用Docker Hub Mirror加速Docker官方镜像下载 http://c ...
- dubbo常见面试问题(二)
1.什么是Dubbo? Duubbo是一个RPC远程调用框架, 分布式服务治理框架 2.什么是Dubbo服务治理? 服务与服务之间会有很多个Url.依赖关系.负载均衡.容错.自动注册服务 3.Dubb ...
- Oracle获取一周前,一个月前,一年前, 本周,本月,当年的日期
1.获取当前时间一周前的日期 ' day from dual 类似的 --当前时间减去7分钟的时间 ' MINUTE from dual --当前时间减去7小时的时间 ' hour from dual ...
- LVS(一):基本概念和三种模式
网站架构中,负载均衡技术是实现网站架构伸缩性的主要手段之一.所谓"伸缩性",是指可以不断向集群中添加新的服务器来提升性能.缓解不断增加的并发用户访问压力. 负载均衡有好几种方式:h ...
- Android 保存图片到相册
/** * 保存图片到相册 */ public void saveImageToGallery(Bitmap mBitmap) { if (!Environment.getExternalStorag ...
- “菜”鸟理解.NET Framework(CLI,CLS,CTS,CLR,FCL,BCL)
既然要学.NET,就要先认识认识她,我不喜欢大段大段文字的东西,自己通过理解,画个图,来看看.NET的沉鱼落雁,闭月羞花之容. 最下层蓝色部分是.NET Framework的基础,也是所有应用软件的基 ...
- Python开发【初始篇】:Linux下安装Python3
Linux系统默认自带python2.6的版本,这个版本被系统很多程序所依赖,所以建议不要轻易删除,除非你能解决其他程序的依赖问题.如果使用最新的Python3需要进行编译安装源码包,这样就对系统默认 ...
- 第一个spring简单的helloworld
spring 是一个开源的框架 也是轻量级框架 1.导入jar包 spring的版本 4.0 目录: spring-framework-4.0.0.RELEASE-libs 下的jar spring ...
- 部署代码review和CI
公司原先搭了一个代码Review的服务器,由于历史原因,装的是一个32bit的Ubuntu系统,后来由于需要,需要安装gitlab,由于gitlab需要64位系统,所以临时凑合了个vagrant,本质 ...
- Maven Nexus仓库地址
收集的仓库地址如下: http://maven.wso2.org/nexus/content/groups/public/ http://jcenter.bintray.com/ http://mav ...