WaitForAnimationを自分用にカスタマイズしてみました。
スクリプトでAnimationの待機を検知したい場合、
コルーチンを使うのが良さげみたいです。
ただ、UnityのデフォルトにはAnimatorで設定したアニメーションが終わるまで待機する
というのが無いっぽいんです。*1
そこで検索してみた所、
テラシュールブログさんの方で、カスタムコルーチンを使ったAnimationの検知方法が記載されていました。
これは便利そうだと、cacaponも使ってみたのですが、思ったように動かない…
そもそも、AnimationとかAnimatorの仕組みがよくわかってない部分もあるので、
今回はAnimatorで設定したアニメーションがどう変化しているのか?
それを調べたうえで、cacaponなりに自分で使える形にカスタマイズしましたので、
それを紹介しようかなと思います。
- 確認したUnityのバージョン
- 準備編 Animationを準備する
- 調査① 元々の作りはどんなもの?
- 調査② cacapon環境で使ってみたけどうまく行かない…
- 調査③ ステートのハッシュ値を調べてみる。
- 調査結果
- 実装してみる。
- 注意点
- 終わりに
- 参考リンク
確認したUnityのバージョン
2020.3.3f1
準備編 Animationを準備する
こんな感じのものを準備しました。
イメージの色を変えるだけの簡単なアニメーションです。
60フレームかけて変化するアニメーションと、
90フレームかけて変化するアニメーションを
ボタンを押すと再生されるようにしています。
アニメーションの詳しい設定方法については先週私がまとめたものもありますし、
他のブログさんでも分かりやすくまとめている方がいるのでここでは割愛しますね。
調査① 元々の作りはどんなもの?
テラシュールブログさんが作成したWaitForAnimation
は以下のようにして検知しているようです。
- newしたタイミングのステート*2のハッシュ値を取得する
- keepWaiting中は常に現在のステートのハッシュ値を取得する。
- newしたタイミングのステートと現在のステートが同じであり、かつ 再生時間中なら待機する。*3
アニメ再生後に、yield return null;
で1フレーム進めることで、
newしたタイミングが待機したいステートになるように調整し、
狙いのステートが終わるまで待機するコルーチンを実現しているようです。
調査② cacapon環境で使ってみたけどうまく行かない…
使い方も分かったので、先ほどのアニメーションで試してみたのですが、うまく行きませんでした。
私が今回作ったアニメーターは以下の形式なのですが、
どうも、1フレーム進めても待機状態に当たるNew State
を取得しているようなのです。
どうすれば、Wait60,Wait90の部分だけ検知することができるのでしょう…
調査③ ステートのハッシュ値を調べてみる。
Animatorの現在のステートのハッシュ値は
Animatorのインスタンス.GetCurrentAnimatorStateInfo(レイヤー番号).fullPathHash;
で取得することができます。
ならば、カスタムコルーチン内部でfullPathHashをログで出すようにしたら分かりそうです。
そこで、本来の使い方ではないでしょうが、カスタムコルーチンを常にTrueを返すようにし、
ボタンを押されてからのハッシュ値の変化を調べてみることにしました。
結果的には下記のようになりました。
- Newされたタイミングから暫くHash値Aが続いている
- 途中でHash値が変化する。
- 再生されたアニメーションによってハッシュ値が変わっている。(60Fアニメをハッシュ値B、90Fアニメをハッシュ値Cとしました)
- しばらくするとHash値Aに戻った。
- ハッシュ値Bとハッシュ値Cにて明らかに時間差を感じた。
図にするとこのような形でしょうか?
調査結果
私の環境で1Fずらしても上手くアニメーションが行かなかったのは、
最初の部分のHashAから抜け出せなかったがゆえにのようです。
そして、今回のアニメーションのようにExitで抜ける形であるならば、
HashAからHashXに変わったタイミングから、
HashXからHASHAに変わるタイミングを検知さえできれば
コルーチンによるAnimationの待機処理は実現できそうなのが分かりました。
ですので、この結果をもとに自分用にカスタマイズしたカスタムコルーチンを作成したいと思います。
実装してみる。
作ったものはこうなりました。
大きな変更点としては、normalizedTimeをオミットしたこと、
bool値 isPlayで再生開始と終了を検知できるようにしたことでしょうか。
newしたタイミングが恐らくIDLE中のハッシュ値というのを利用して、
変わったら再生開始、戻ったら再生終了、という判定を、
keepWaitingの中で行っています。
自分で使った範囲だと、正しく待機しているようです。*5
注意点
私がテラシュールブログさんの記事内に掲載されていたスクリプトを参考にしたように、
今回作成したアニメーションの待機処理を自己責任の上で参考に頂いて構いませんが、注意点があります。
それは、今回作成したアニメーション待機処理があくまで
Entry → 待機 → 再生 → Exit
という構成を取っているアニメーターを想定しているものということです。
他の構成が未確認ではありますが、
Entry → 待機 → 再生1 → 再生2 → Exit
のような構成なら、再生1、再生2の分だけ待機するでしょうし、
Entry → 再生1 → Exit
のような構成ならWaitForAnimationは永遠にTrueを返しますので
その点をご注意の上、参考頂ければと思います。
終わりに
限定的ではありますが、自分に合ったアニメーションの待機スクリプトを作成することが出来ました。
分からないことでも、調査することで理解が深まった良い機会になりました。
当面はUnityのゲーム作成を続けていると思いますので、
実装に当たって得た知見を引き続き公開できればなと思います。
それではまた。
参考リンク
大元のスクリプトを作成した方です。ありがとうございました。 tsubakit1.hateblo.jp