Unity自动生成AnimatorController
上一篇写了如何自动切割动画,这一篇写如何自动生成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的更多相关文章
- Unity 自动生成组件索引类工具
Unity 自动生成组件索引类工具 需求由来 我们在写UI类时 需要获取预设中的组件 joystick = transform.Find("joystick"); backgrou ...
- Unity3D研究院之Machine动画脚本自动生成AnimatorController(七十一)
以前的项目一直不敢用Machine动画,因为当时立项的时候Machine动画还不成熟,最近项目做得差不多了我能有点时间学习,我就想在研究学习学习Machine.用Machine动画的时候需要创建一个A ...
- Unity3D研究院之Machine动画脚本自动生成AnimatorController
原地址: http://www.xuanyusong.com/archives/2811 以前的项目一直不敢用Machine动画,因为当时立项的时候Machine动画还不成熟,最近项目做得差不多了我能 ...
- Unity3D读取模型文件自动生成AnimatorController简单实例
前几天接到一个任务,做一个导入.控制模型动画的工具类,没有太具体的要求,于是就自行思考实际需求,最终根据宣雨松老师的一篇博客,自己规范了一下写了一个工具类.相关工具代码及测试用例已上传至Github. ...
- unity组件路径自动生成
unity 有时候找路径太麻烦 写了一个自动生成脚本的工具 using System.Collections.Generic; using System.IO; using System.Text; ...
- Unity 导出的android项目自动生成Private Libraries
如果Unity里面Plugins/Android 添加了 jar 文件,则导出Android 项目时会自动生成 Private Libraries. 而且里面的项还删不掉 然后在网上搜了一下,找到了原 ...
- Unity2D研究院之自动生成动画、AnimationController、Prefab(一)
http://www.xuanyusong.com/archives/3243 国庆了,回家了.时刻还是要吃一颗学习的心,在家了也要抽出时间好好学习一下.之前MOMO一直没研究过Unity2D,今天研 ...
- 9.1.3 .net framework通过业务逻辑层自动生成WebApi的做法
首先需要说明的是这是.net framework的一个组件,而不是针对.net core的.目前工作比较忙,因此.net core的转换正在编写过程中,有了实现会第一时间贴出来. 接下来进入正题.对于 ...
- 自动生成查找组件的lua代码
本篇主要解决的问题是使用lua脚本编写unity业务逻辑时,自动生成一些查找组件及绑定控件事件的lua代码! 现在很多unity项目都是用ulua作为热更新解决方案,因此需要用lua来写相关的逻辑,经 ...
随机推荐
- errors collectiions
c/c++中出现“undefined reference to”的解决 如果提示未定义的函数是某个库的函数.检查库时候已经安装,并在编译命令中采用-l和-L参数导入库. 如果提示未定义的函数是程序中的 ...
- 2019/2/11 LinuxRPM包管理
一.RPM安装包管理: a.yum install …… , yum remove ……, yum update …… , b.只下载安装包而不安装:yum install -y 包名 - ...
- IDEA连接数据库自动生成实体类
1.连接数据库 (1)按下图 , 点击view-----选择tool windows----------选择database并点击 (2)弹出Database窗口,点击加号--------- ...
- IDEA 中tomcat日志位置
参考 https://blog.csdn.net/dela_/article/details/78555977 /home/dela/.IntelliJIdea2017.1/system/tomcat ...
- python--第二十一/二天总结
Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Python的标准库外,其不依赖任何其他模块. 1 2 3 ...
- SQL数据库索引理解与应用【转贴--收藏】
SQL数据库中索引分为聚集索引(CLUSTERED)和非聚集索引(NONCLUSTERED)两种. 聚集索引确定表中数据的物理顺序,它就类似与电话簿,按照姓氏排列数据.由于聚集索引规定数据表中的物理顺 ...
- 变邻域搜索(Variable neighborhood search)
变邻域搜索(Variable neighborhood search)VNS是Hansen等提出的一种元启发近似算法,它通过在不同的邻域结构内跳转搜索, 能够避免陷入局部最优解. 算法主要分为两部分: ...
- poj 1141 Brackets Sequence 区间dp,分块记录
Brackets Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 35049 Accepted: 101 ...
- VSCode的使用
前后端分离的,先打开vs,打开你的项目,在项目根目录中找到.vs文件加,找到.vs\config\applicationhost.config,然后打开找到你项目的IIS Express配置,例如:& ...
- 处理ajax数据;数据渲染
当我们用ajax把数据拿到前台,该如何渲染到页面,有以下几种方式: 一:使用字符串拼接的方法 声明一个空变量,然后拼接 var st=""; st+="<div&g ...