スプライトアニメーションは連続画像を複数選択してScene上にドラッグドロップするだけでAnimationファイルとAnimatorContollerファイルを作成してくれ、簡単に扱えると思うのですが、要件的に少し特殊なことをしようとしてハマったので備忘録として残します。
間違っていたり動かないことがあればご指摘いただけますと幸いです。
ケーススタディ
1. スクリプトの値を動的に使う
UnityのAnimatorでparametersのfloat値とか使って動的にAnimationを変化させたさある
— Nakaji Kohki (@kohki_nakaji) 2017年9月9日
結論としては無理なので、スクリプトで制御しました(今回は角度)。
public void SetShot(float angle, bool isGround)
{
Debug.Log("shot");
bodyAnimator.SetTrigger(SRAnimators.player.Parameters.shot);
var _angle = ((angle + 45f) % 90) - 45f;
transform.rotation = Quaternion.Euler(0, 0, _angle);
// do something
}
2. 動的に変化させた値をAnimatorでデフォルト値に戻す
上記でスクリプトから設定した値を、Animationの設定で上書きして値を戻すというアプローチです。
結論これも無理でした。
UnityのAnimatorで角度はスクリプトからいじってるんだけど、Animationに一つでも角度のパラメータが入るとAnimatior側で管理されるようになってスクリプトからいじれなくなる、クソい
— Nakaji Kohki (@kohki_nakaji) 2017年9月9日
Write Defaultについては今回は用途が違いましたが、うまく使うと便利そう。
Write Defaultはそのあたりを制御できるのかと思ってたけど、管理されているけどそのAnimationで指定されていないパラメータに関して、前Animationの値を使う(false)場合と初期値を使う場合(true)の制御だった
— Nakaji Kohki (@kohki_nakaji) 2017年9月9日
3. Animationの開始時に処理を挟む
- の手法が使えなかったので、スクリプトから開始時を判定して処理を挟み込みます。
方法はいくつかあります。
AnimationState.normalizedTimeを監視する
StateMachineBehaviourを使用する
これはAnimationのイベントを拾うことができるBehaviorです。StateMachineBehaviourを継承して使うことができます。 Componentと少し扱いが違うので注意です(ちょっとハマりました)。 Animatorウィンドウ上でステートを選択し、Inspectorウィンドウで「Add Behavior」をすることでアタッチできます。
こちらの記事が参考になると思います。
【Unity5】StateMachineBehaviourでAnimatorを監視する - Qiita
また、上記記事の後半に書かれているUniRx版ですが、 UniRx.Triggers
にまさしく同じような機能が ObservableStateMachineTrigger
として実装されています。使い方は「Add Behavior」しておいた上で Animator.GetBehavior
もしくは Animator.GetBehaviors
で取得し、あとは hogehogeAsObservable()
に対して Subscribe
することができると思います。
その他: Exit TimeとTransition Duration
Transition Durationは3Dの場合はいい感じにブレンドして自然に遷移してくれる機能ですが、2Dでは特にクロスフェード等してくれる訳ではないので、基本的には0にしておくといいと思います。
(これが0でない値になっているのに気がつかず、うまく意図しない挙動になっていてハマりました。。)
また、同様Exit Timeを使い場合も開始位置は終端の1に合わせておきましょう。
さいごに
当たり前の話ではあるんだけど、アニメーションの制御はAnimatorに任せるパラメータとスクリプトで管理するパラメータの住み分けしっかり考えた方がよさそう
— Nakaji Kohki (@kohki_nakaji) 2017年9月9日