上一篇写了如何自动切割动画,这一篇写如何自动生成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. java 将mysql中Blob类型转为字符串或数字

    引入Blob类型貌似不行,不知道是版本问题还是java中的Blob类型为oracle,后来使用byte[]转换成功. public float byte2float(byte[] b) { if(b! ...

  2. SpringBoot之SOAP WebService

    SpringBoot的Web Service类型常见有RESTful Web Service和SOAP Web Service两种,RESTful风格的web服务比较常用,但实际工作中仍有部分场景用到 ...

  3. ABAP 程序/接口调用其他程序的数据

    在ABAP遇到的业务场景中,可能会遇到一种情况,需要调用其他报表的数据来发送或者二次加工,这个时候又不想对源程序做大的改动.有以下几种思路解决. 1.修改源程序,将需要展示的数据存储到DB中,然后主程 ...

  4. JSONObject optString

    JSONObject optString  获取后台返回的{"state":1001,"data":"数据保存成功"} 用optString ...

  5. dotnet不是内部或外部的命令,也不是可运行的程序或批处理文件

    该问题是由于电脑环境变量配置错误所导致.最初在网上查找的方法,是在系统环境变量path中添加以下语句: %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\ ...

  6. IDEA 中tomcat日志位置

    参考 https://blog.csdn.net/dela_/article/details/78555977 /home/dela/.IntelliJIdea2017.1/system/tomcat ...

  7. FineCMS v5.4.1 后台getshell

    0x01.前言 最近在学代码审计,拿finecms学习的时候偶然发现的,应该算个1day吧 0x02.正文 FineCMS v5.4.1 后台域名配置处 域名配置文件config/domain.php ...

  8. 重启虚拟机后dhclient进程未运行解决办法

    问题分析 重启虚拟机后,dhclient进程未运行的根因通常为: 1.NetworkManager未开启自启动导致的dhclient进程未运行 2.网卡设置未纳入NetworkManager管理导致的 ...

  9. Ubuntu16.04 安装python3.7和pip3

    到官网下载源码 装个依赖包:apt-get install libffi-dev 三部曲 ./configure make make install 但此时pip3可能不行,加个local,前提是前面 ...

  10. 关于微信小程序appsecret保护的问题

    本地后端代码中通常会配置 appid 和 appsecret,直接 push 到 公有 git 库会导致所有人可见.但其他人由于不是开发者有了别的项目的 secret 用处不大.但仍建议采用某种方法加 ...