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来写相关的逻辑,经 ...
随机推荐
- IDEA中显示RunDashboard
在打开.idea/workspace.xml,找到RunDashboard的配置,添加红色字体内容 <component name="RunDashboard"> &l ...
- 20175213《Java程序设计》实验二Java面向对象程序设计实验报告
实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装,继承,多态 3.初步掌握UML建模 4.熟悉S.O.L.I.D原则 5.了解设计模式 知识总结 1.伪代码 2.产品代码: ...
- echarts饼图去除鼠标移入高亮
1:如果echarts的js文件为压缩版本,在编辑器打开去掉t.on("mouseover",c).on("mouseout",d)这一行,如果js文件为非压缩 ...
- Mysql 视图,触发器,存储过程,函数,事务
视图 视图虚拟表,是一个我们真实查询结果表,我们希望将某次查询出来的结果作为单独的一个表,就叫视图,无法对图字段内容进行增删改. --格式: CREATE VIEW 视图名字 AS 操作; --比如: ...
- Eclipse设置所有新创建文件默认格式为UTF-8
一.为什么需要设置所有新创建文件默认格式为UTF-8 Eclipse编码默认是ISO-8859-1,不支持中文.而很多时候,我们的文件中含有中文,或者需要在创建文件时就需要是UTF-8编码格式的.在创 ...
- docker学习-lnmp+redis之搭建redis容器服务
1. 目录映射:/lnmp/data/redis:/data/lnmp/conf/redis/redis.conf:/etc/redis/redis.conf/lnmp/logs/redis:/var ...
- python之元组及其方法---整理集
元组: 区别:与列表类似,是对列表的二次加工:用小括号包括起来:元素不可修改:不可增加.删除 技巧:创建元组的时候,一般在最后一个元素后面加一个逗号:为了与方法区分:并且这个逗号不算元素例如: tu= ...
- 探究编译后,try-with-resources括号中的object是否关闭,以及两种写法编译后的对比
源码(@TargetApi(Build.VERSION_CODES.KITKAT)) public List<T> test1() { String sql = "selxe x ...
- workerman与thinkphp结合
运行workerman需要安装pcntl和event或者libevent pcntl安装方法: 以php-5.5.20为例,实际情况按自己安装的PHP目录 一. 找到PHP源码,进入 php-5.5. ...
- Educational Codeforces Round 43 (Rated for Div. 2)
Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...