【Unity】簡易AnimationViewer

簡易アニメーションビューワを作成してみたのでサンプルコードとその解説を残す。

MotionVIewer Screen Shot 0024-03-26 at 17.20.10

やること

  • 新しいシーンを作成
  • モーション付きのモデルをインスタンシング
  • CharacterControllerコンポーネントを追加
  • スクリプト追加

新しいシーンを作成

Command + Shift + N で新しいシーンを作成する。

シーンビューにはカメラしか写ってない。

MotionVIewer Screen Shot 0024-03-26 at 15.29.16

モーション付きのモデルをインスタンシング

アセットストア等からデータを入手できるので入手しておく。

これをプロジェクトビューからシーンビューかHierarchyにD&Dでインスタンシングする。

MotionVIewer Screen Shot 0024-03-26 at 17.33.01

インスタンシングされたオブジェクトを選択し、Inspectorに表示されたTransformの座標を全てゼロにしておく。

この時点でモノによってはカメラに納まっている。

CharacterControllerコンポーネントを追加

Component->Physics->Character Controllerを選択し、先にインスタンシングしたオブジェクトにコンポーネントを追加する。

Inspector の AnimationsにあるElementを見てアニメーションがちゃんと存在するを確認しておく。

MotionVIewer Screen Shot 0024-03-26 at 15.42.29

スクリプトの追加

下記のスクリプトをコピペして追加する。

#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だとモーションは一度再生された後に最終フレームで停止する。
スライダは再生速度を変動させる。ループ再生しているモーションを確認する際は便利。

MotionVIewer Screen Shot 0024-03-26 at 17.54.11

スクリプトの解説

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プロパティ(任意で指定可能な文字列)を取得して配列に格納している。
ループが完了したら配列は返される。

参考

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です