株式会社グレンジでUnityエンジニアをしている @s_ebata と申します。
この記事はグレンジ Advent Calendar 2020の12/17の記事です。
はじめに
タイトルの通りですが非エンジニア向けに超絶簡易的なアニメーションビューア機能を作ってみました。
本来ならUnityのAnimatorウィンドウとAnimationウィンドウを使えば事足りる機能ですが、本機能は以下の点を重視して手早く作ったものになります。ご留意ください。
- 非エンジニア向け
- インスペクタで完結する
- アニメーションの指定と再生・停止ができる
環境
Unity 2018.4.27f1
demo
こんな感じでLayersとStateをプルダウンから選択して再生・一時停止・再開・停止が可能です
Unityちゃんのアニメーションチェックシーン使っているため若干ややこしい見た目になってますが、インスペクタ内からアニメーションの指定と再生・停止・一時停止・再開ができているのが確認出来るかと思います。
解像度が低くて分かりづらいかもですが、ボタンは左からPlay、Pause、Resume、Stopとなっています。
動画には入っていませんが、AnimationEventsの設定有無も確認できます。
実装
難しいことは一切やっていません。ただただAnimator側の情報を取って表示しているだけです。
細かい制御などは端折って記載しています。
// ...省略...
/// <summary>
/// CustomAnimator参照
/// </summary>
private CustomAnimator _customAnimator;
/// <summary>
/// レイヤー名を格納する配列
/// </summary>
private string[] _layerNames = new string[] { };
/// <summary>
/// ステート名を格納するディクショナリ
/// </summary>
private Dictionary<int, string[]> _stateNamesDict = new Dictionary<int, string[]>();
private int _layerIndex;
private CustomAnimator CustomAnimator
{
get
{
if (_customAnimator == null)
_customAnimator = target as CustomAnimator;
return _customAnimator;
}
}
public override void OnInspectorGUI()
{
// ...省略...
EditorGUILayout.LabelField("デバッグ再生");
_layerIndex = EditorGUILayout.Popup("Layers", _layerIndex, _layerNames);
var stateNames = _stateNamesDict.ContainsKey(_layerIndex) ? _stateNamesDict[_layerIndex] : new string[] { };
_stateIndex = EditorGUILayout.Popup("States", _stateIndex, stateNames);
_stateName = stateNames.Length > 0 ? stateNames[_stateIndex] : string.Empty;
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Play"))
{
var fullPathHash = Animator.StringToHash(string.Join(".", _animator.GetLayerName(_layerIndex), _stateName));
CustomAnimator.Play(fullPathHash, _layerIndex, _normalizedTime, () =>
{
Debug.Log("Complete");
});
}
if (GUILayout.Button("Pause"))
{
CustomAnimator.Pause();
}
if (GUILayout.Button("Resume"))
{
CustomAnimator.Resume();
}
if (GUILayout.Button("Stop"))
{
CustomAnimator.Stop();
}
}
// ...省略...
}
// ...省略...
実行時にAnimatorControllerのLayersとStatesの拾い方がわからなくてググりました。
以下方法で拾えることがわかって勉強になりました。
// UnityEditorのAnimatorControllerでキャスト
var controller = _animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
for (var i = 0; i < controller.layers.Length; i++)
{
var layer = controller.layers[i];
Debug.Log(layer.name); // レイヤー名
var states = layer.stateMachine.states;
foreach (var state in states)
{
Debug.Log(state.state.name); // ステート名
}
}
以上になります。