zoukankan      html  css  js  c++  java
  • Unity自动生成AnimatorController

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

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

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

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

      1 using UnityEngine;
      2 using UnityEditor;
      3 using System.IO;
      4 using UnityEditor.Animations;
      5 
      6 public class CreatePrefab : EditorWindow
      7 {
      8     #region -- 变量定义
      9     private static string mOutputPath = "";
     10     private static bool mIsCreateAnimatorController = true;
     11 
     12     private static AnimationClip mStart;
     13     private static AnimationClip mTake;
     14     private static AnimationClip mEnd;
     15     #endregion
     16 
     17     #region -- 系统函数
     18     private void OnGUI()
     19     {
     20         GUILayout.BeginVertical();
     21 
     22         //绘制标题
     23         GUILayout.Space(10);
     24         GUI.skin.label.fontSize = 24;
     25         GUI.skin.label.alignment = TextAnchor.MiddleCenter;
     26         GUILayout.Label("Create Prefabs");
     27 
     28         //绘制文本
     29         GUILayout.Space(10);
     30         mOutputPath = EditorGUILayout.TextField("Output Path:", mOutputPath);
     31 
     32         GUILayout.Space(10);
     33         mIsCreateAnimatorController = EditorGUILayout.Toggle("Create AnimaControl:", mIsCreateAnimatorController);
     34 
     35         if (GUILayout.Button("Create"))
     36         {
     37             CreatePrefabs();
     38         }
     39 
     40         GUILayout.EndVertical();
     41     }
     42     #endregion
     43 
     44     #region -- 自定义函数
     45     public static void CreateWindow()
     46     {
     47         //绘制窗口
     48         EditorWindow.GetWindow(typeof(CreatePrefab), true, "Create Prefabs");
     49     }
     50     private static void CreatePrefabs()
     51     {
     52         Object[] _objs = Selection.GetFiltered(typeof(GameObject), SelectionMode.Unfiltered);
     53         if (_objs.Length == 0)
     54         {
     55             Debug.Log("你没有选择任何物体!");
     56             return;
     57         }
     58         for (int i = 0; i < _objs.Length; i++)
     59         {
     60             if (!Directory.Exists(Application.dataPath + "/" + mOutputPath))
     61             {
     62                 Directory.CreateDirectory(Application.dataPath + "/" + mOutputPath);
     63             }
     64             GameObject _temObJ = _objs[i] as GameObject;
     65             string _outputPath = "";
     66             if (mOutputPath == "")
     67             {
     68                 _outputPath = "Assets/";
     69             }
     70             else
     71             {
     72                 _outputPath = "Assets/" + mOutputPath + "/";
     73             }
     74             GameObject _prefab = PrefabUtility.CreatePrefab(_outputPath + _temObJ.name + ".prefab", _temObJ);
     75             if (mIsCreateAnimatorController)
     76             {
     77                 AnimatorController _animatorController = CreateAnimatorController(AssetDatabase.GetAssetPath(_objs[i]), _temObJ.name + ".controller", _outputPath + "AnimatorControllers");
     78                 Animator _animator = _prefab.GetComponent<Animator>();
     79                 if (_animator != null)
     80                 {
     81                     _animator.runtimeAnimatorController = _animatorController;
     82                 }
     83             }
     84         }
     85         AssetDatabase.Refresh();
     86     }
     87     private static AnimatorController CreateAnimatorController(string _assetsPath, string _controllerName, string _outPutPath)
     88     {
     89         //创建AnimatorController文件,保存在_outPutPath路径下
     90         if (!Directory.Exists(_outPutPath))
     91         {
     92             Directory.CreateDirectory(_outPutPath);
     93         }
     94 
     95         //生成动画控制器(AnimatorController)
     96         AnimatorController _animatorController = AnimatorController.CreateAnimatorControllerAtPath(_outPutPath + "/" + _controllerName);
     97 
     98         //添加参数(parameters)
     99         _animatorController.AddParameter("Normal", AnimatorControllerParameterType.Float);
    100         _animatorController.AddParameter("Play", AnimatorControllerParameterType.Bool);
    101 
    102         //得到它的Layer, 默认layer为base,可以拓展
    103         AnimatorControllerLayer _layer = _animatorController.layers[0];
    104 
    105         //把动画文件保存在我们创建的AnimatorController中
    106         AddStateTransition(_assetsPath, _layer);
    107         return _animatorController;
    108     }
    109     private static void AddStateTransition(string _assetsPath, AnimatorControllerLayer _layer)
    110     {
    111         //添加动画状态机(这里只是通过层得到根状态机,并未添加)
    112         AnimatorStateMachine _stateMachine = _layer.stateMachine;
    113 
    114         // 根据动画文件读取它的AnimationClip对象
    115         var _datas = AssetDatabase.LoadAllAssetsAtPath(_assetsPath);
    116         if (_datas.Length == 0)
    117         {
    118             Debug.Log(string.Format("Can't find clip in {0}", _assetsPath));
    119             return;
    120         }
    121 
    122         // 遍历读取模型中包含的动画片段
    123         foreach (var _data in _datas)
    124         {
    125             if (!(_data is AnimationClip))
    126             {
    127                 continue;
    128             }
    129             AnimationClip _newClip = _data as AnimationClip;
    130             switch (_newClip.name)
    131             {
    132                 case "Start":
    133                     mStart = _newClip;
    134                     break;
    135                 case "End":
    136                     mEnd = _newClip;
    137                     break;
    138                 case "Take":
    139                     mTake = _newClip;
    140                     break;
    141             }
    142         }
    143 
    144         // 先添加一个默认的空状态
    145         AnimatorState _emptyState = _stateMachine.AddState("Empty", new Vector3(_stateMachine.entryPosition.x + 200, _stateMachine.entryPosition.y, 0));
    146 
    147         // 添加与动画名称对应的装态(AnimatorState)到状态机中(AnimatorStateMachine)中,并设置状态
    148         AnimatorState _startState = _stateMachine.AddState(mStart.name, new Vector3(_stateMachine.entryPosition.x + 500, _stateMachine.entryPosition.y + 100, 0));
    149         _startState.motion = mStart;
    150 
    151         AnimatorState _endState = _stateMachine.AddState(mEnd.name, new Vector3(_stateMachine.entryPosition.x + 500, _stateMachine.entryPosition.y - 100, 0));
    152         _endState.motion = mEnd;
    153 
    154         AnimatorState _take01State = _stateMachine.AddState("Take01", new Vector3(_stateMachine.entryPosition.x + 800, _stateMachine.entryPosition.y + 100, 0));
    155         _take01State.motion = mTake;
    156 
    157         AnimatorState _take02State = _stateMachine.AddState("Take02", new Vector3(_stateMachine.entryPosition.x + 800, _stateMachine.entryPosition.y - 100, 0));
    158         _take02State.motion = mTake;
    159         _take02State.speed = -1;
    160 
    161         //连接每个状态,并添加切换条件
    162         AnimatorStateTransition _animatorStateTransition = _emptyState.AddTransition(_startState);
    163         _animatorStateTransition.AddCondition(AnimatorConditionMode.Greater, 0, "Normal");
    164         _animatorStateTransition.hasExitTime = false;
    165         _animatorStateTransition.duration = 0;
    166 
    167         _animatorStateTransition = _emptyState.AddTransition(_endState);
    168         _animatorStateTransition.AddCondition(AnimatorConditionMode.Less, 0, "Normal");
    169         _animatorStateTransition.hasExitTime = false;
    170         _animatorStateTransition.duration = 0;
    171 
    172         _animatorStateTransition = _startState.AddTransition(_take01State);
    173         _animatorStateTransition.AddCondition(AnimatorConditionMode.If, 0, "Play");
    174         _animatorStateTransition.hasExitTime = false;
    175         _animatorStateTransition.duration = 0;
    176 
    177         _animatorStateTransition = _endState.AddTransition(_take02State);
    178         _animatorStateTransition.AddCondition(AnimatorConditionMode.If, 0, "Play");
    179         _animatorStateTransition.hasExitTime = false;
    180         _animatorStateTransition.duration = 0;
    181     }
    182     #endregion
    183 
    184 }

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

    有个坑和大家说一下,我们是有 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 按钮吧,然后你会发现预制体以及动画状态机都帮你制作好了,嘿嘿!

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

  • 相关阅读:
    IDE IntelliJ IDEA ToolsTable 窗口找回
    Equals方法与“==”区别
    JAVA虚拟机内存分配与回收机制(转)
    java集合框架总结三--Set接口及其子类
    2014年4月5日 java集合框架总结2--List接口及其子类
    java集合框架总结一
    sql 操作数据库
    EF框架用中使用mysql数据库需要安装mysql-for-visualstudio
    mysql 服务启动不了;无法启动MYSQL服务”1067 进程意外终止”解决办法
    mysql 修改密码
  • 原文地址:https://www.cnblogs.com/xiaoyulong/p/9848474.html
Copyright © 2011-2022 走看看