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 按鈕吧,然后你會發現預制體以及動畫狀態機都幫你制作好了,嘿嘿!

然后狀態之間具體怎么連,這部分是需要自己根據項目需求自己寫的,我這里只是給大家一個例子。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM