簡易アニメーションビューワを作成してみたのでサンプルコードとその解説を残す。
やること
- 新しいシーンを作成
- モーション付きのモデルをインスタンシング
- CharacterControllerコンポーネントを追加
- スクリプト追加
新しいシーンを作成
Command + Shift + N で新しいシーンを作成する。
シーンビューにはカメラしか写ってない。
モーション付きのモデルをインスタンシング
アセットストア等からデータを入手できるので入手しておく。
これをプロジェクトビューからシーンビューかHierarchyにD&Dでインスタンシングする。
インスタンシングされたオブジェクトを選択し、Inspectorに表示されたTransformの座標を全てゼロにしておく。
この時点でモノによってはカメラに納まっている。
CharacterControllerコンポーネントを追加
Component->Physics->Character Controllerを選択し、先にインスタンシングしたオブジェクトにコンポーネントを追加する。
Inspector の AnimationsにあるElementを見てアニメーションがちゃんと存在するを確認しておく。
スクリプトの追加
下記のスクリプトをコピペして追加する。
#pragma strict var roteSpeed:float = 3.5; private var side : float = 1.0; private var animationSpeed:float; private var animationCount:uint; private var animationList:Array; function Start () { print("animationGetCount:" + animation.GetClipCount()); print(animation.clip.name); animationCount = animation.GetClipCount(); print(gameObject.animation); animationList = GetAnimationList(); } function Update () { if( -0.9 < transform.rotation.y && transform.rotation.y < 0.9 ){ }else{ side *= -1; } transform.rotation.y += roteSpeed/180 * side; } function OnGUI (){ var sw : int = Screen.width; var sh : int = Screen.height; var margin : int = 10; //ghool position var ghoolRoteYLabel:Rect = Rect(0,margin + 0,sw,sh/10); GUI.Label(ghoolRoteYLabel,"Rote Y:"+ transform.rotation.y); margin += 10; //slider var playSpeedRect:Rect = Rect(0,margin + 30,sw,sh/10); animationSpeed = GUI.HorizontalSlider(playSpeedRect,animationSpeed,0.0,5.0); for (var state : AnimationState in animation) { state.speed = animationSpeed; } GUI.Label(playSpeedRect,"playSpeed :"+ animationSpeed); margin += 100; //Buttons var buttonSpace:int = 40; var rectWidth:int = 100; var rectHeight:int = 40; var max:int = 10; var rects:Array = new Array(); var i:int = 0; for (var name : String in animationList) { var rect:Rect = Rect(15,margin + 20*i + buttonSpace*i, rectWidth,rectHeight); if(GUI.Button(rect,animationList[i].ToString())){ animation.CrossFade(animationList[i],0.01); } i++; } } private function GetAnimationList():Array { var tmpArray = new Array(); for (var state : AnimationState in gameObject.animation) { tmpArray.Add(state.name); } return tmpArray; }
これを先のインスタンスしたオブジェクトにD&Dするとコンポーネントとして追加される。
再生ボタンで実行を行うと保持しているモーション一覧がボタン化されて列記される。
それらをクリックするとモーションが変更される。
ループ指定がOffだとモーションは一度再生された後に最終フレームで停止する。
スライダは再生速度を変動させる。ループ再生しているモーションを確認する際は便利。
スクリプトの解説
Startメソッドで各種初期化。
var roteSpeed:float = 3.5; private var side : float = 1.0; private var animationSpeed:float; private var animationCount:uint; private var animationList:Array; function Start () { print("animationGetCount:" + animation.GetClipCount()); print(animation.clip.name); animationCount = animation.GetClipCount(); print(gameObject.animation); animationList = GetAnimationList(); }
自身の保持するClip(アニメーション1個の単位)の数を取得。
同時に自作の関数でClipの名前を配列で取得。
UpdateメソッドではキャラのY軸上の回転を行わせている。
function Update () { if( -0.9 < transform.rotation.y && transform.rotation.y < 0.9 ){ }else{ side *= -1; } transform.rotation.y += roteSpeed/180 * side; }
OnGUIメソッドではUI表示。
function OnGUI (){ var sw : int = Screen.width; var sh : int = Screen.height; var margin : int = 10; //ghool position var ghoolRoteYLabel:Rect = Rect(0,margin + 0,sw,sh/10); GUI.Label(ghoolRoteYLabel,"Rote Y:"+ transform.rotation.y); margin += 10; //slider var playSpeedRect:Rect = Rect(0,margin + 30,sw,sh/10); animationSpeed = GUI.HorizontalSlider(playSpeedRect,animationSpeed,0.0,5.0); for (var state : AnimationState in animation) { state.speed = animationSpeed; } GUI.Label(playSpeedRect,"playSpeed :"+ animationSpeed); margin += 100; //Buttons var buttonSpace:int = 40; var rectWidth:int = 100; var rectHeight:int = 40; var max:int = 10; var rects:Array = new Array(); var i:int = 0; for (var name : String in animationList) { var rect:Rect = Rect(15,margin + 20*i + buttonSpace*i, rectWidth,rectHeight); if(GUI.Button(rect,animationList[i].ToString())){ animation.CrossFade(animationList[i],0.01); } i++; } }
スライダはアニメーションの再生速度の変更を担う。
変更時に保持するアニメーション全ての再生速度を同時に変更する。
その後、自動でアニメーション数に応じてボタンを生成。
ボタン押下時の効果はクロスフェードさせてアニメーションをスイッチする、という内容。
アニメーションの名前が分からなくてもElement#で拾えてたと思ってサンプル探したけど出て来ず。
仕方なくAnswersで検索したら発見。コピペ。
GetAnimationListメソッド
private function GetAnimationList():Array { var tmpArray = new Array(); for (var state : AnimationState in gameObject.animation) { tmpArray.Add(state.name); } return tmpArray; }
for inで、gameObjectが保持するAnimationState形式のデータを全て取得する。
取得したAnimationState各種のClipのnameプロパティ(任意で指定可能な文字列)を取得して配列に格納している。
ループが完了したら配列は返される。