アニメーションビューワーの用なものを作ろうと思った時に、実行時にlayerやstate名が取得できると便利だなと思って調べてみると、UnityEditor.Animations.AnimatorControllerというものがあったので使ってみました!
環境
- Unity2018.3.7f1
- MacBookPro Mojave v10.14.3
実装
AnimatorのruntimeAnimatorControllerをUnityEditor.Animations.AnimatorControllerでキャストしてやると、情報が取れるようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AnimatorTest : MonoBehaviour { [SerializeField] private Animator m_animator = null; private void Start () { var runtimeController = m_animator.runtimeAnimatorController; // UnityEditorのAnimatorControllerでキャストする . var controller = runtimeController as UnityEditor.Animations.AnimatorController; foreach ( var layer in controller.layers ) { UnityEditor.Animations.AnimatorStateMachine stateMachine = layer.stateMachine; Debug.Log( "[" + layer.name + "]" ); foreach ( var state in stateMachine.states ) { Debug.Log( " " + state.state.name ); } } } } |
デバッグ出力した内容を確認してみると、意図した情報が取れていました。この処理とUnityちゃんを使ってUIからlayerとstateを選択できるものを作ってみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEditor; public class AnimatorUI : MonoBehaviour { [SerializeField] private Animator m_animator = null; [SerializeField] private Dropdown m_ddLayer = null; [SerializeField] private Dropdown m_ddState = null; private Dictionary<string,List<string>> m_dicState = new Dictionary<string,List<string>>(); private void Start () { m_ddLayer.ClearOptions(); m_ddState.ClearOptions(); var runtimeController = m_animator.runtimeAnimatorController; var layerList = new List<string>(); var controller = runtimeController as UnityEditor.Animations.AnimatorController; foreach ( var layer in controller.layers ) { UnityEditor.Animations.AnimatorStateMachine stateMachine = layer.stateMachine; layerList.Add( layer.name ); List<string> stateList = new List<string>(); foreach ( var state in stateMachine.states ) { stateList.Add( state.state.name ); } m_dicState[layer.name] = stateList; } if ( layerList.Count > 0 ) { m_ddLayer.AddOptions( layerList ); ChangeLayer( layerList[0] ); } } private void ChangeLayer ( string layer ) { m_ddState.value = 0; m_ddState.ClearOptions(); m_ddState.AddOptions( m_dicState[layer] ); } public void OnChangeDropdownLayer () { if ( m_ddLayer.options.Count > 0 ) { ChangeLayer( m_ddLayer.options[m_ddLayer.value].text ); } } public void OnClickPlay () { if ( m_ddState.options.Count <= 0 || m_ddLayer.options.Count <= 0 ) { return; } var stateNmae = m_ddState.options[m_ddState.value].text; var layer = m_animator.GetLayerIndex( m_ddLayer.options[m_ddLayer.value].text ); m_animator.Play( stateNmae, layer ); } } |
実行したものがこちらです。
まとめ
今回使った、UnityEditor.Animations.AnimatorControllerはエディタでしか使えませんが、layer、state名を調べたり手動で書いてアニメーション切り替えをしたりしなくてもいいのはとても便利でした。他にも機能があるようなので別の機会に試してみたいと思います!