UnityでAnimator Controllerを使っているとありがちなこととして
- ステートが多すぎて遷移が異様に複雑になりわけがわからなくなる。
- Triggerで制御しようとしてるが、時々特定のステートで意図せず制御が引っかかってしまうことがある。
があると思います。前者はサブステートやOverride Controllerを駆使してなんとか整理していくしかないのですが(慣れが必要かも)、後者の事態を招く一因として「モーションのステートと、スクリプト側でのステートの同期が取れなくなる問題」があります。
この問題はAnimator.Play()とTriggerでの制御が混在していると起きます。つまり、スクリプト側に遷移を書くのか? モーション側に遷移を書くのか? が中途半端になっていると、
- Play()でステートがワープしたためにTriggerがリセットされずに残ってしまい、その後遷移が変になる
- スクリプト側で、AnimatorStateInfo.IsName("damage")などとして待っているが、そのステートにならない
となり、ステート数が多くなるほど再現するのが面倒なバグになったりします。解決法として、
- Controllerに遷移を書かずに(ステートだけ並べて線で結ばずに)、スクリプトで Animator.CrossFadeなどを使って制御する。
- 原則としてControllerにすべての遷移を書くことにして、スクリプトではAnimator.SetTriggerなどパラメータで制御する。
のように、Controller かスクリプトのどっちが主なのかはっきりさせるのをおすすめしたいです(というか、そうするべき)。前者は、スクリプトがすべてなので、あらゆる状況で技がキャンセルできるようなゲームで有効です(ただしデザイナーやプランナーとの連携が取りづらくなるので、なにか工夫が必要)。後者は、それ以外の大体のゲームで有効です。
具体的な実装については次の投稿で。