Unity制作2D产品的时候,我们在制作动画的时候,要不断的生成Animation,Animator等等资源,如果动画一多的话,就变得麻烦。由于Unity是支持插件开发的,我们可以添加一个Editor,然后把美术的动画图片放在指定的位置。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.Animations; public class BuildAnimation : Editor
{ //生成出的Prefab的路径
private static string PrefabPath = "Assets/Resources/Prefabs";
//生成出的AnimationController的路径
private static string AnimationControllerPath = "Assets/AnimationController";
//生成出的Animation的路径
private static string AnimationPath = "Assets/Animation";
//美术给的原始图片路径
private static string ImagePath = Application.dataPath +"/Raw"; [MenuItem("Build/BuildAnimaiton")]
static void BuildAniamtion()
{
DirectoryInfo raw = new DirectoryInfo (ImagePath);
foreach (DirectoryInfo dictorys in raw.GetDirectories())
{
List<AnimationClip> clips = new List<AnimationClip>();
foreach (DirectoryInfo dictoryAnimations in dictorys.GetDirectories())
{
//每个文件夹就是一组帧动画,这里把每个文件夹下的所有图片生成出一个动画文件
clips.Add(BuildAnimationClip(dictoryAnimations));
}
//把所有的动画文件生成在一个AnimationController里
AnimatorController controller = BuildAnimationController(clips,dictorys.Name);
//最后生成程序用的Prefab文件
BuildPrefab(dictorys,controller);
}
} static AnimationClip BuildAnimationClip(DirectoryInfo dictorys)
{
string animationName = dictorys.Name;
//查找所有图片,因为我找的测试动画是.jpg
FileInfo []images = dictorys.GetFiles("*.png");
AnimationClip clip = new AnimationClip();
//AnimationUtility.SetAnimationType(clip,ModelImporterAnimationType.Generic);
EditorCurveBinding curveBinding = new EditorCurveBinding();
curveBinding.type = typeof(SpriteRenderer);
curveBinding.path="";
curveBinding.propertyName = "m_Sprite";
ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[images.Length];
//动画长度是按秒为单位,1/10就表示1秒切10张图片,根据项目的情况可以自己调节
float frameTime = 1/10f;
for(int i =0; i< images.Length; i++){
Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(DataPathToAssetPath(images[i].FullName));
keyFrames[i] = new ObjectReferenceKeyframe ();
keyFrames[i].time = frameTime *i;
keyFrames[i].value = sprite;
}
//动画帧率,30比较合适
clip.frameRate = 30; //有些动画我希望天生它就动画循环
if(animationName.IndexOf("idle") >=0 )
{
//设置idle文件为循环动画
SerializedObject serializedClip = new SerializedObject(clip);
AnimationClipSettings clipSettings = new AnimationClipSettings(serializedClip.FindProperty("m_AnimationClipSettings"));
clipSettings.loopTime = true;
serializedClip.ApplyModifiedProperties();
}
string parentName = System.IO.Directory.GetParent(dictorys.FullName).Name;
System.IO.Directory.CreateDirectory(AnimationPath +"/"+parentName);
AnimationUtility.SetObjectReferenceCurve(clip,curveBinding,keyFrames);
AssetDatabase.CreateAsset(clip,AnimationPath +"/"+parentName +"/" +animationName+".anim");
AssetDatabase.SaveAssets();
return clip;
} static AnimatorController BuildAnimationController(List<AnimationClip> clips ,string name)
{
AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPath(AnimationControllerPath +"/"+name+".controller");
AnimatorControllerLayer layer = animatorController.layers[0];
AnimatorStateMachine sm = layer.stateMachine;
foreach(AnimationClip newClip in clips)
{
//AnimatorStateMachine machine = sm.AddStateMachine(newClip.name);
AnimatorState state = sm.AddState(newClip.name);
state.motion = newClip;
//AnimatorStateTransition trans = sm.AddAnyStateTransition(state);
if(newClip.name == "idle"){
sm.defaultState = state;
}
//sm.AddEntryTransition(machine);
//sm.AddStateMachineExitTransition(machine);
//trans.RemoveCondition(0);
}
AssetDatabase.SaveAssets();
return animatorController;
} static void BuildPrefab(DirectoryInfo dictorys,AnimatorController animatorCountorller)
{
//生成Prefab 添加一张预览用的Sprite
FileInfo images = dictorys.GetDirectories()[0].GetFiles("*.png")[0];
GameObject go = new GameObject();
go.name = dictorys.Name;
SpriteRenderer spriteRender =go.AddComponent<SpriteRenderer>();
spriteRender.sprite = AssetDatabase.LoadAssetAtPath<Sprite>(DataPathToAssetPath(images.FullName));
Animator animator = go.AddComponent<Animator>();
animator.runtimeAnimatorController = animatorCountorller;
PrefabUtility.CreatePrefab(PrefabPath+"/"+go.name+".prefab",go);
DestroyImmediate(go);
} public static string DataPathToAssetPath(string path)
{
if (Application.platform == RuntimePlatform.WindowsEditor)
return path.Substring(path.IndexOf("Assets\\"));
else
return path.Substring(path.IndexOf("Assets/"));
} class AnimationClipSettings
{
SerializedProperty m_Property; private SerializedProperty Get (string property) { return m_Property.FindPropertyRelative(property); } public AnimationClipSettings(SerializedProperty prop) { m_Property = prop; } public float startTime { get { return Get("m_StartTime").floatValue; } set { Get("m_StartTime").floatValue = value; } }
public float stopTime { get { return Get("m_StopTime").floatValue; } set { Get("m_StopTime").floatValue = value; } }
public float orientationOffsetY { get { return Get("m_OrientationOffsetY").floatValue; } set { Get("m_OrientationOffsetY").floatValue = value; } }
public float level { get { return Get("m_Level").floatValue; } set { Get("m_Level").floatValue = value; } }
public float cycleOffset { get { return Get("m_CycleOffset").floatValue; } set { Get("m_CycleOffset").floatValue = value; } } public bool loopTime { get { return Get("m_LoopTime").boolValue; } set { Get("m_LoopTime").boolValue = value; } }
public bool loopBlend { get { return Get("m_LoopBlend").boolValue; } set { Get("m_LoopBlend").boolValue = value; } }
public bool loopBlendOrientation { get { return Get("m_LoopBlendOrientation").boolValue; } set { Get("m_LoopBlendOrientation").boolValue = value; } }
public bool loopBlendPositionY { get { return Get("m_LoopBlendPositionY").boolValue; } set { Get("m_LoopBlendPositionY").boolValue = value; } }
public bool loopBlendPositionXZ { get { return Get("m_LoopBlendPositionXZ").boolValue; } set { Get("m_LoopBlendPositionXZ").boolValue = value; } }
public bool keepOriginalOrientation { get { return Get("m_KeepOriginalOrientation").boolValue; } set { Get("m_KeepOriginalOrientation").boolValue = value; } }
public bool keepOriginalPositionY { get { return Get("m_KeepOriginalPositionY").boolValue; } set { Get("m_KeepOriginalPositionY").boolValue = value; } }
public bool keepOriginalPositionXZ { get { return Get("m_KeepOriginalPositionXZ").boolValue; } set { Get("m_KeepOriginalPositionXZ").boolValue = value; } }
public bool heightFromFeet { get { return Get("m_HeightFromFeet").boolValue; } set { Get("m_HeightFromFeet").boolValue = value; } }
public bool mirror { get { return Get("m_Mirror").boolValue; } set { Get("m_Mirror").boolValue = value; } }
} }

以上代码支持Unity5.0以上。

代码拷贝进去自己试试就知道了,非常方便

[Unity2d系列教程] 006.Unity如何根据图片自动生成Animator的更多相关文章

  1. [Unity2d系列教程] 003.Unity如何调用android的方法

    Unity开发的时候很多时候我们需要用到底层的一些功能,比如摄像,录音,震动等等,我们在Unity的层面是无法完成的.那么我们考虑到Unity是否可以直接调用到android方面的方法,替我们去完成我 ...

  2. [Unity2d系列教程] 005.Unity如何使用外部触控插件FingerGuesture

    用过Unity的都知道自带的Input.touches并不支持鼠标输入,给我们的调试带来很大的不方便.那么我们会发现其实有很多触控方面的插件,如inputtouches,easy touch,fing ...

  3. [Unity2d系列教程] 004.Unity如何调用ios的方法(SDK集成相关)

    和上一篇类似,我们同样希望Unity能够直接调用IOS底层的代码,那么我们就需要研究怎么去实现它.下面让我来带大家看一个简单的例子 1.创建.h和.m文件如下 .h // // myTest.m // ...

  4. 黄聪:Microsoft Enterprise Library 5.0 系列教程(八) Unity Dependency Injection and Interception

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(八) Unity Dependency Injection and Interception 依赖注入容器Uni ...

  5. Springboot 系列(十一)使用 Mybatis(自动生成插件) 访问数据库

    1. Springboot mybatis 介绍 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数获取 ...

  6. [Unity2d系列教程] 002.引用外部DLL - C

    上一篇我们学习了Unity调用C#生成的外部DLL,但是有时候我们需要访问底层,不能不适用C生成的DLL.下面就让我们一起学习下,C如何生成. 1.创建一个C的控制台程序 2.点击确定->点击下 ...

  7. [Unity2d系列教程] 001.引用外部DLL - C#

    众所周知,Unity可以支持多种语言开发, C#, JS, Boo三种方式的开发, 能够很方便的集成一些外部插件,以便调用现有的动态链接库.学过C#的都知道C#可以生成一个dll供给其他的程序调用.那 ...

  8. 【前端】CentOS 7 系列教程之四: 配置 git 服务器自动部署

    转载请注明出处:http://www.cnblogs.com/shamoyuu/p/linux_4.html 安装pm2守护进程,备用 npm install -g pm2 创建/srv/www文件夹 ...

  9. TensorFlow从1到2(十二)生成对抗网络GAN和图片自动生成

    生成对抗网络的概念 上一篇中介绍的VAE自动编码器具备了一定程度的创造特征,能够"无中生有"的由一组随机数向量生成手写字符的图片. 这个"创造能力"我们在模型中 ...

随机推荐

  1. 题目分享M

    题意: 其实就是找到AB+min(AC,BC)的最大值 分析:刚看到这道题,很容易往AB为树的直径方向上去想,C就可以遍历每个点,最后求出对于每个点为C时的最大值 那AB到底是不是树的直径或者为什么A ...

  2. .NET Core+QQ第三方授权登录

    安装包 dotnet add package AspNet.Security.OAuth.QQ 接上文GitHub第三方授权登录 申请过程不介绍了,申请者资料,个人也是可以申请成功的. 这时候有二个参 ...

  3. js数据类型很简单,却也不简单

    最近脑子里有冒出"多看点书"的想法,但我个人不是很喜欢翻阅纸质书籍,另一方面也是因为我能抽出来看书的时间比较琐碎,所以就干脆用app看电子书了(如果有比较完整的阅读时间,还是建议看 ...

  4. STM32 ADC多通道规则采样和注入采样

    layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 什么是ADC? STM ...

  5. Dotnet core使用JWT认证授权最佳实践(二)

    最近,团队的小伙伴们在做项目时,需要用到JWT认证.遂根据自己的经验,整理成了这篇文章,用来帮助理清JWT认证的原理和代码编写操作. 第一部分:Dotnet core使用JWT认证授权最佳实践(一) ...

  6. Redux:pre

    If you aren't familiar with state management libraries like Redux or MobX, don't use context. For ma ...

  7. 13.2 Go练习题答案

    13.2 Go练习题答案 练习题1: 创建一个goroutine与主线程按顺序相互发送信息若干次 且打印 package temp import "fmt" //创建一个gorou ...

  8. mysql运维入门6:MySQL读写分离

    Amoeba 以MySQL为底层数据存储,并对应用提供MySQL协议接口的proxy 集中想用应用的请求,根据用户事先设置的规则,将SQL请求发送到特定的数据库上执行 基于此可以实现负载均衡.读写分离 ...

  9. 关于MySQL数据被删除后空间重用的问题实验

    以前知道,MySQL在通过delete语句删除数据后,空间并不会被腾出,而只是在数据文件中被标记为已删除,除非执行optimize table.前两天听说,虽然delete数据后硬盘空间不会被腾出,但 ...

  10. MySQL(6)— 事务

    六.事务 ACID: 原子性.一致性.隔离性和持久性 原子性(atomicity) :一组事务,不能再细分了,其中的sql, 要么全部提交成功,要么全部失败回滚,不能只提交其中的一部分操作. 一致性( ...