上一篇写了如何自动切割动画,这一篇写如何自动生成AnimatorController。

之前网上查了很多资料,看的一直很蒙,看不懂是怎么回事的,这里我先给大家明确几个概念:

画的不好,大家将就着看,写这个工具我们会涉及到很多类,类名包含上图哪个关键字,这个东西就跟哪个东西有关

只要大家能明确这些概念,看懂代码就不难了,下面上代码:

 using UnityEngine;
using UnityEditor;
using System.IO;
using UnityEditor.Animations; public class CreatePrefab : EditorWindow
{
#region -- 变量定义
private static string mOutputPath = "";
private static bool mIsCreateAnimatorController = true; private static AnimationClip mStart;
private static AnimationClip mTake;
private static AnimationClip mEnd;
#endregion #region -- 系统函数
private void OnGUI()
{
GUILayout.BeginVertical(); //绘制标题
GUILayout.Space();
GUI.skin.label.fontSize = ;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("Create Prefabs"); //绘制文本
GUILayout.Space();
mOutputPath = EditorGUILayout.TextField("Output Path:", mOutputPath); GUILayout.Space();
mIsCreateAnimatorController = EditorGUILayout.Toggle("Create AnimaControl:", mIsCreateAnimatorController); if (GUILayout.Button("Create"))
{
CreatePrefabs();
} GUILayout.EndVertical();
}
#endregion #region -- 自定义函数
public static void CreateWindow()
{
//绘制窗口
EditorWindow.GetWindow(typeof(CreatePrefab), true, "Create Prefabs");
}
private static void CreatePrefabs()
{
Object[] _objs = Selection.GetFiltered(typeof(GameObject), SelectionMode.Unfiltered);
if (_objs.Length == )
{
Debug.Log("你没有选择任何物体!");
return;
}
for (int i = ; i < _objs.Length; i++)
{
if (!Directory.Exists(Application.dataPath + "/" + mOutputPath))
{
Directory.CreateDirectory(Application.dataPath + "/" + mOutputPath);
}
GameObject _temObJ = _objs[i] as GameObject;
string _outputPath = "";
if (mOutputPath == "")
{
_outputPath = "Assets/";
}
else
{
_outputPath = "Assets/" + mOutputPath + "/";
}
GameObject _prefab = PrefabUtility.CreatePrefab(_outputPath + _temObJ.name + ".prefab", _temObJ);
if (mIsCreateAnimatorController)
{
AnimatorController _animatorController = CreateAnimatorController(AssetDatabase.GetAssetPath(_objs[i]), _temObJ.name + ".controller", _outputPath + "AnimatorControllers");
Animator _animator = _prefab.GetComponent<Animator>();
if (_animator != null)
{
_animator.runtimeAnimatorController = _animatorController;
}
}
}
AssetDatabase.Refresh();
}
private static AnimatorController CreateAnimatorController(string _assetsPath, string _controllerName, string _outPutPath)
{
//创建AnimatorController文件,保存在_outPutPath路径下
if (!Directory.Exists(_outPutPath))
{
Directory.CreateDirectory(_outPutPath);
} //生成动画控制器(AnimatorController)
AnimatorController _animatorController = AnimatorController.CreateAnimatorControllerAtPath(_outPutPath + "/" + _controllerName); //添加参数(parameters)
_animatorController.AddParameter("Normal", AnimatorControllerParameterType.Float);
_animatorController.AddParameter("Play", AnimatorControllerParameterType.Bool); //得到它的Layer, 默认layer为base,可以拓展
AnimatorControllerLayer _layer = _animatorController.layers[]; //把动画文件保存在我们创建的AnimatorController中
AddStateTransition(_assetsPath, _layer);
return _animatorController;
}
private static void AddStateTransition(string _assetsPath, AnimatorControllerLayer _layer)
{
//添加动画状态机(这里只是通过层得到根状态机,并未添加)
AnimatorStateMachine _stateMachine = _layer.stateMachine; // 根据动画文件读取它的AnimationClip对象
var _datas = AssetDatabase.LoadAllAssetsAtPath(_assetsPath);
if (_datas.Length == )
{
Debug.Log(string.Format("Can't find clip in {0}", _assetsPath));
return;
} // 遍历读取模型中包含的动画片段
foreach (var _data in _datas)
{
if (!(_data is AnimationClip))
{
continue;
}
AnimationClip _newClip = _data as AnimationClip;
switch (_newClip.name)
{
case "Start":
mStart = _newClip;
break;
case "End":
mEnd = _newClip;
break;
case "Take":
mTake = _newClip;
break;
}
} // 先添加一个默认的空状态
AnimatorState _emptyState = _stateMachine.AddState("Empty", new Vector3(_stateMachine.entryPosition.x + , _stateMachine.entryPosition.y, )); // 添加与动画名称对应的装态(AnimatorState)到状态机中(AnimatorStateMachine)中,并设置状态
AnimatorState _startState = _stateMachine.AddState(mStart.name, new Vector3(_stateMachine.entryPosition.x + , _stateMachine.entryPosition.y + , ));
_startState.motion = mStart; AnimatorState _endState = _stateMachine.AddState(mEnd.name, new Vector3(_stateMachine.entryPosition.x + , _stateMachine.entryPosition.y - , ));
_endState.motion = mEnd; AnimatorState _take01State = _stateMachine.AddState("Take01", new Vector3(_stateMachine.entryPosition.x + , _stateMachine.entryPosition.y + , ));
_take01State.motion = mTake; AnimatorState _take02State = _stateMachine.AddState("Take02", new Vector3(_stateMachine.entryPosition.x + , _stateMachine.entryPosition.y - , ));
_take02State.motion = mTake;
_take02State.speed = -; //连接每个状态,并添加切换条件
AnimatorStateTransition _animatorStateTransition = _emptyState.AddTransition(_startState);
_animatorStateTransition.AddCondition(AnimatorConditionMode.Greater, , "Normal");
_animatorStateTransition.hasExitTime = false;
_animatorStateTransition.duration = ; _animatorStateTransition = _emptyState.AddTransition(_endState);
_animatorStateTransition.AddCondition(AnimatorConditionMode.Less, , "Normal");
_animatorStateTransition.hasExitTime = false;
_animatorStateTransition.duration = ; _animatorStateTransition = _startState.AddTransition(_take01State);
_animatorStateTransition.AddCondition(AnimatorConditionMode.If, , "Play");
_animatorStateTransition.hasExitTime = false;
_animatorStateTransition.duration = ; _animatorStateTransition = _endState.AddTransition(_take02State);
_animatorStateTransition.AddCondition(AnimatorConditionMode.If, , "Play");
_animatorStateTransition.hasExitTime = false;
_animatorStateTransition.duration = ;
}
#endregion }

代码很详细了,也写了很多注释,这里就不多说了,大家自己看。

有个坑和大家说一下,我们是有 bool 类型的参数,如何设置 bool 类型的参数呢?

我开始天真的以为是这样的:

_animatorStateTransition.AddCondition(AnimatorConditionMode.If, 0, "BoolParameter");
_animatorStateTransition.AddCondition(AnimatorConditionMode.If, 1, "BoolParameter");

不知道有多少同学和我一样,有这种天真的想法,然后你会发现这样设置根本没用,值全部都为True,根本设置不了false

后来查了好久资料,才发现是这样设置 bool 类型的参数的:

_animatorStateTransition.AddCondition(AnimatorConditionMode.If, 0, "BoolParameter");  为True
_animatorStateTransition.AddCondition(AnimatorConditionMode.IfNot, 0, "BoolParameter");为False

实在是坑,不想说话。。。。。。。

附上一张效果图

填写好输出路径,在 Project 视图中选中模型,点击 Create 按钮吧,然后你会发现预制体以及动画状态机都帮你制作好了,嘿嘿!

然后状态之间具体怎么连,这部分是需要自己根据项目需求自己写的,我这里只是给大家一个例子。

Unity自动生成AnimatorController的更多相关文章

  1. Unity 自动生成组件索引类工具

    Unity 自动生成组件索引类工具 需求由来 我们在写UI类时 需要获取预设中的组件 joystick = transform.Find("joystick"); backgrou ...

  2. Unity3D研究院之Machine动画脚本自动生成AnimatorController(七十一)

    以前的项目一直不敢用Machine动画,因为当时立项的时候Machine动画还不成熟,最近项目做得差不多了我能有点时间学习,我就想在研究学习学习Machine.用Machine动画的时候需要创建一个A ...

  3. Unity3D研究院之Machine动画脚本自动生成AnimatorController

    原地址: http://www.xuanyusong.com/archives/2811 以前的项目一直不敢用Machine动画,因为当时立项的时候Machine动画还不成熟,最近项目做得差不多了我能 ...

  4. Unity3D读取模型文件自动生成AnimatorController简单实例

    前几天接到一个任务,做一个导入.控制模型动画的工具类,没有太具体的要求,于是就自行思考实际需求,最终根据宣雨松老师的一篇博客,自己规范了一下写了一个工具类.相关工具代码及测试用例已上传至Github. ...

  5. unity组件路径自动生成

    unity 有时候找路径太麻烦 写了一个自动生成脚本的工具 using System.Collections.Generic; using System.IO; using System.Text; ...

  6. Unity 导出的android项目自动生成Private Libraries

    如果Unity里面Plugins/Android 添加了 jar 文件,则导出Android 项目时会自动生成 Private Libraries. 而且里面的项还删不掉 然后在网上搜了一下,找到了原 ...

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

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

  8. 9.1.3 .net framework通过业务逻辑层自动生成WebApi的做法

    首先需要说明的是这是.net framework的一个组件,而不是针对.net core的.目前工作比较忙,因此.net core的转换正在编写过程中,有了实现会第一时间贴出来. 接下来进入正题.对于 ...

  9. 自动生成查找组件的lua代码

    本篇主要解决的问题是使用lua脚本编写unity业务逻辑时,自动生成一些查找组件及绑定控件事件的lua代码! 现在很多unity项目都是用ulua作为热更新解决方案,因此需要用lua来写相关的逻辑,经 ...

随机推荐

  1. ipad忘记了锁屏密码,已经越狱了

    ipad忘记了锁屏密码,已经越狱了, 已经需要连接itunes了...要是恢复的话,好像就不能越狱了耶... 我叫什么好咧 | 浏览 3330 次  问题暂时关闭  推荐于2016-07-23 11: ...

  2. 20175213 2018-2019-2 《Java程序设计》第7周学习总结

    教材学习内容总结 (1)String (char a[])用一个字符数组a创建一个String对象. (2)String(char a[],int startIndex,int count) 提取字符 ...

  3. model 字段参数 choice

    class Banner(NewsBase): ''' 轮播图 ''' PRI_CHOICES = [ # 优先级的限制选择范围 (1,'第一级'), (2,'第二级'), (3,'第三级'), (4 ...

  4. Hackergame 2018的一道题目confused_flxg失败心得体会

    分析了这道题,发现自己有如下缺陷需要: 1.要提升:C/C++代码的分析能力2.熟悉IDA的动态调试功能3.能练习使用python编程基本的逻辑功能代码

  5. canvas 的HTML属性

    (一) width/height 默认值与单位 Canvas  标签只有两个属性—— width\height,作为一种替换元素,它默认大小为300×150像素. canvas的单位只能是是px,值只 ...

  6. Flask使用记录

    关于FLASK框架的使用 使用pycharm创建工程 在默认的templates中新增模板页面 在默认的app.py中定义路由并引用模板 @app.route("/add", me ...

  7. springmvc的面试知识点总结

    新的一年,开启新的篇章,欧气满满,迎接未来. 前几天回顾了spring相关的知识点,现在再来回顾下springmvc相关的知识点做一下总结. 问题总结 之前面试问题总结的那篇文章中,与springmv ...

  8. zabbix添加nginx监控

    nginx内置了一个status状态的功能,通过配置可以看到nginx的运行情况,status显示的内容包括当前连接数,处于活动状态的连接数,已经处理的请求数等等,可以利用这个功能编写zabbix监控 ...

  9. redis缓存雪崩,缓存穿透,缓存击穿的解决方法

    一.缓存雪崩 缓存雪崩表示在某一时间段,缓存集中失效,导致请求全部走数据库,有可能搞垮数据库,使整个服务瘫痪. 使缓存集中失效的原因: 1.redis服务器挂掉了. 2.对缓存数据设置了相同的过期时间 ...

  10. 使用JFlex生成词法分析器 1:安装配置

    环境:Windows 10 STEP 1: 下载 JFlex 文件,我选择的是 jflex-1.7.0.zip.下载完成后解压到想安装的位置. 文件结构如下(假设解压目录为 C:\): C:\jfle ...