1. 程式人生 > >unity5之程式碼建立狀態機,玩的666

unity5之程式碼建立狀態機,玩的666

http://blog.csdn.net/litaog00/article/details/50483189

最近做專案的時候用到了狀態機,網上搜了一下帖子,大部分都是簡單介紹使用方法的,講解的詳細的很少。作者

好好研究了一番,感覺很有必要和大家分享一下。技術和靈感,來源於網路,共享於網路~

好多個human模型有好多個動作片段,這些片段又分出若干大類和若干小類,一個主角可能會應用到所有的這些片

段,當滿足一定條件時從一類動作中隨機取出一個播放,進遊戲的時候有的動作條件滿足有的不滿足隨著玩的進度

又可能會滿足#@#@#%@!!&*&,,,,略複雜,總之就是有好多動作(200個左右),有的能播,有的不能播

,作者(頭硬)一心想用一個狀態機來解決所有問題,所以就用程式碼建立吧,畢竟這麼多動作,讓策劃去擺,費時

費力還容易出錯,特別在設定transition的條件時,呵呵,那就程式碼建立吧,既能體現情懷又能提高自己。

首先網上搜了搜,只有雨鬆momo的一篇http://www.xuanyusong.com/archives/2811(冒犯引用一下),介紹了大

概思想和用法,但是比較舊,要知道作者用的可是unity3d5.2.2版的,不同及需要注意的地方依次列出:

1.AnimatorController所在的庫由UnityEditorInternal變為UnityEditor.Animations

2.AnimatorController裡可以建立layer,每個layer有個statemachine(我們通常叫‘某個角色的狀態機’好

像不合適,應該叫‘某個角色的AnimatorController’

  1. //建立controller
  2. AnimatorController controller=AnimatorController.CreateAnimatorControllerAtPath("Assets/Resources/CharacterAnim/Play2Controllor_2.controller");  
  3. AnimatorControllerLayer layer=controller.layers[0];  
  4. AnimatorStateMachine machine=layer.stateMachine;  
這樣取到了base layer的statemachine

3.建立引數,

  1. controller.AddParameter("zhan->pa",AnimatorControllerParameterType.Trigger);  

引數型別有4種:int、float、bool、trigger(作者之前用4.2版的時候還沒有trigger,只有int、float

、bool、vector)

有了引數,就有判斷條件了,判斷條件的型別有

  1. AnimatorConditionMode.If;  
  2. AnimatorConditionMode.IfNot;  
  3. AnimatorConditionMode.Equals;  
  4. AnimatorConditionMode.NotEqual;  
  5. AnimatorConditionMode.Greater;  
  6. AnimatorConditionMode.Less;  
其中if既可以來判斷bool又可以判斷trigger(其實trigger就是觸發一下就重置了,可以理解為自動重置的bool)


4.新增內容

新增oneState

  1. oneState=machine.AddState(名字,位置)  
新增anyState到oneState的transition
  1. AnimatorStateTransition defaultTransition=machine.AddAnyStateTransition(oneState);  
建立二級子狀態機
  1. AnimatorStateMachine sub2Machine=machine.AddStateMachine(名字,位置)  
作者這裡建立了三級子狀態機,子狀態機跟父狀態機一樣,都可以新增state、transition。有一點需要注意,
  1. AnimatorStateTransition transition1=machine.AddAnyStateTransition(oneState);  
  2. AnimatorStateTransition transition2=sub2Machine.AddAnyStateTransition(twoState);  

transition1和transition2不是從同一個anyState出發的,而是從各自狀態機的anyState出發的(子狀態

機也有個anyState,但是在controller編輯器裡看不出來)

5.雨鬆momo的帖子裡有網友問到:如果fbx裡有多個clip,用AssetDatabase.LoadAssetAtPath(xxx.fbx)

如何取到呢?那麼答案來了

  1. Object[] objects=AssetDatabase.LoadAllAssetsAtPath("Assets/Art/Animation/"+fbxName);  
  2. for(int m=0;m<objects.Length;m++)  
  3. {  
  4. <span style="white-space:pre">    </span>if(objects[m].GetType()==typeof(AnimationClip) && !objects[m].name.Contains("Take 001"))  
  5.     {  
  6.         AnimationClip clip=(AnimationClip)objects[m];  
  7.         if(clip.name.Equals("chushidongzuo001"))  
  8.         {  
  9.             defaultState.motion=clip;  
  10.         }  
  11.         else
  12.         {  
  13.             addAnimationClip(clip,actionDetails,machine,haveSub3);  
  14.         }  
  15.     }  
  16. }  

注意到了嗎?AssetDatabase.LoadAllAssetsAtPath可以把fbx裡的所有資訊取到,clip、骨骼節點、mesh。。。,

然後過濾一下下。而AssetDatabase.LoadAssetAtPath<AnimationClip>("xxx.FBX")只能取到此fbx下第一個clip。

好了,就寫到這裡,下面把整個程式碼貼出來,供大家參考~

  1. using UnityEngine;  
  2. using System.Collections.Generic;  
  3. using UnityEditor;  
  4. //using UnityEditorInternal;
  5. using UnityEditor.Animations;  
  6. using System.IO;  
  7. publicclass Play2ControllerGenerator : EditorWindow {  
  8.     publicenum ActionType:int
  9.     {  
  10.         undefine=0,  
  11.         zhan,  
  12.         tang,  
  13.         cewo,  
  14.         pa,  
  15.         guodu,  
  16.         kaichang,  
  17.         jieshu,  
  18.         wu  
  19.     }  
  20.     publicenum ActionStyle:int
  21.     {  
  22.         normal=0,  
  23.         qingchun,  
  24.         keai,  
  25.         gaoleng,  
  26.         yundong,  
  27.         chengshu,  
  28.         xinggan  
  29.     }  
  30.     privatestaticstring[] sub2MachineNames=newstring[]{"undefine","zhan","tang","cewo","pa","guodu","kaichang","jieshu","wu"};  
  31.     privatestaticstring[] sub3MachineNames=newstring[]{"normal","qingchun","keai","gaoleng","yundong","chengshu","xinggan"};  
  32.     privateconststring ParamNameTransitionAction="transitionAction";  
  33.     privateconststring ParamNameActionId="actionId";  
  34.     privateconstfloat TransitionDuring=0.4f;  
  35.     //
  36.     [MenuItem("LoveLive/核心玩法2/生成狀態機")]  
  37.     privatestaticvoid addWindow()  
  38.     {  
  39.         Rect rect=new Rect(0,0,600,300);  
  40.         Play2ControllerGenerator window=EditorWindow.GetWindowWithRect<Play2ControllerGenerator>(rect,true,"生成核心玩法狀態機(省得策劃自己擺了)");  
  41.         window.minSize=new Vector2(300,100);  
  42.         window.maxSize=new Vector2(600,300);  
  43.         window.Show();  
  44.     }  
  45.     void OnGUI()  
  46.     {  
  47.         EditorGUILayout.BeginVertical();  
  48.         EditorGUILayout.LabelField("需要\"Assets/Resources/Config/action.txt\"");  
  49.         EditorGUILayout.LabelField("需要\"Assets/Art/Animation\"下的動作檔案");  
  50.         EditorGUILayout.EndVertical();  
  51.         EditorGUILayout.Separator();  
  52.         EditorGUILayout.LabelField("生成的狀態機在這個位置:\"Assets/Resources/CharacterAnim/Play2Controllor_2.controller\"