State の多い Animator を自由に動かすために編集するのが面倒。
そこでポーズ用の Animation を用意して、プログラムで設定したい。
アニメは初めてなのでユニティちゃんを例にいろいろと試してみる。
通常はAnimatorを使って状態遷移をする必要がある。
デフォルトのAnimatorはこんな感じ。
これだと好きに遷移させることができない。
これをいじってスクリプトで特定のStateになるまで飛ばすという方法が考えられる。
飛ばすのも負荷的によくなさそうだし、以下のようにどの状態にも遷移できるようなほうが見た目的にわかりやすい。
ただこれも多数の状態がある場合にめんどくさい。
そこで Animator を使わず Animation を使ってスクリプト操作する。
しかしこの辺はUI前提だからか非常に分かりにくかった。
多分こんな感じの関係だと思うけどAnimationがよくわからない。
コンポーネントとスクリプトでなんか違うものに思える。
今回やりたいのはUnityちゃんのポーズをとってきて適応することです。
ポーズは UnityChan/Animations/unitychan_ARpose1 を使用します。
まずデフォルトだとエラーが出るのでアニメーションの設定をいじります。
アニメーションタイプを Legacy にする必要がありました。
アニメーションからクリップを名前で取り出します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public Animation anim1; //unitychan_ARpose1 public Animation targetAnime; //UnityちゃんにつけたAnimation public void PlayAnim(string newpose){ foreach (AnimationState s in anim1) { if(s.name==newpose){ targetAnime.clip = s.clip; //不要? targetAnime.AddClip(s.clip,newpose); if(oldpose != newpose && oldpose != ""){ targetAnime.RemoveClip(oldpose); //しなくてもいい } } } targetAnime.Play(newpose); oldpose = newpose; } |
これでユニティちゃんは機敏にポーズを変えます。
追記
ポーズ用途ならクリップは1つしか必要がない。
一々RemoveするよりもAddの時に名前を統一すれば上書きされる。
1 2 3 4 5 6 7 8 9 10 11 |
public Animation anim1; //unitychan_ARpose1 public Animation targetAnime; //UnityちゃんにつけたAnimation public void PlayAnim(string newpose){ foreach (AnimationState s in anim1) { if(s.name==newpose){ targetAnime.AddClip(s.clip,"pose"); } } targetAnime.Play("pose"); } |
もっと簡単に Animation > Animations に必要なクリップを全てアタッチして、
クリップ名を指定して Play() する方法もある。
さらに追記
そもそもAnimatorを使ってもやりたいことができた。
1 2 3 4 5 6 |
public Animator anim; // 対象のAnimatorコンポーネント ... void ChangePose (string pose) { int hash = Animator.StringToHash(pose);//ポーズ名 anim.Play(hash, -1, 0);//ハッシュ、レイヤー、正規化された時間(0-1) } |
複数レイヤーの場合、レイヤーインデックスを指定する必要があるように見えるけど指定しなくても問題なかった。
またハッシュ値にせずにポーズ名を指定しても問題ない。
勘違いしてたけどAnimatorコントローラはステートマシンの機能も持っているだけで、Animationを使うよりも便利に使えるみたい。
何よりも Legacy Type にする必要がないのでアニメーションの使いまわしができる。