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 按钮吧,然后你会发现预制体以及动画状态机都帮你制作好了,嘿嘿!

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

  • 相关阅读:
    1024X768大图 (Wallpaper)
    (Mike Lynch)Application of linear weight neural networks to recognition of hand print characters
    瞬间模糊搜索1000万基本句型的语言算法
    单核与双核的竞争 INTEL P4 670对抗820
    FlashFTP工具的自动缓存服务器目录的功能
    LDAP over SSL (LDAPS) Certificate
    Restart the domain controller in Directory Services Restore Mode Remotely
    How do I install Active Directory on my Windows Server 2003 server?
    指针与指针变量(转)
    How to enable LDAP over SSL with a thirdparty certification authority
  • 原文地址:https://www.cnblogs.com/xiaoyulong/p/9848474.html
Copyright © 2011-2022 走看看