ikoan unity 開発メモ

Unityに関するアレコレを日々つづっていこうと思います

Animatorで同一アニメを一定回数loopしてから別のstateに遷移させる

環境

Unity2018.2.16f1

概要

Animatorのstateにセットしたアニメーションが終了する、もしくは状態が変更したのを検知したい時があると思います。
そんな時には「StateMachineBehaviour」を使って、制御しましょう。
StateMachineBehaviour - Unity スクリプトリファレンス

実装手順

まずはStateMachineBehaviourを継承したクラスを作成します。
通常通り、Scriptを作成し、通常ならMonoBehaviourを指定している箇所をStateMachineBehaviourに変更します。

StateMachineBehaviourにはいくつかのcallbackが用意されていて、自分の目的にあったcallbackをoverrideすることで、必要な処理を実装します。
例えば、stateに切り替わったタイミングを検知したい場合は下記のようになります。

作成ができたら、UnityのAnimatorビューに移動します。
Animatorビュー上の監視したいstateを選択すると、Inspector上に「Add Behaviour」というボタンがあるので、それで先ほど作成したスクリプトを追加してください。

あとは再生すれば、監視対象に設定したstateの状態に応じてcallbackが呼ばれるので、それを元に様々なことができると思います。

同一アニメを繰り返したい場合

いよいよ本題についてです。
通常なら、一つのステートに一つのアニメーションを割り当てると思います。そのアニメーションはloop設定しなければ、一度再生され、そしてそのstateのまま状態が保持されると思います。逆にloop設定すると延々と同じアニメーションを繰り返してしまいます。
同一アニメを繰り返すのは、例えば同じアニメを設定したstateを複数個用意し、アニメが終わったら次のstateで同じアニメ、それが終わったら次のstateで同じアニメ・・・、といった方法も取れなくはありませんが、美しくありませんし、数が増えるとなると現実的ではありません。
その場合、どうするかというと、先ほどのStateMachineBehaviourを使用します。
StateMachineBehaviourのcallbackに「OnStateUpdate」というのが存在します。これはAnimatorがそのstateにいる時に毎フレーム呼び出されます。
このOnStateUpdateで渡される引数の中に、AnimatorStateInfoというものがあり、これはそのstateの現在の状態を保持しています。
AnimatorStateInfoのリファレンスを見てみましょう。

AnimatorStateInfo - Unity スクリプトリファレンス

変数の中に「normalizedTime ステートの正規化された時間」というのがありました。
これはつまり一回のloopを0〜1で表した時間ということになるんですね。
つまり、この数値が3以上になった時、それは3回ループしたよ、ということになります。
この数値でループ回数を判断して、条件を満たした時にstateを変更するように命令すれば、やりたいことができると思います。

まとめ

リファレンスは神。