このブログで使用しているUnityのVer
・Unity 2021.3.9f1

どうもふる!個人でゲーム制作をしています、えきふるです
ゲーム制作をしていると遊びの要素として、
勝利エモートを複数用意したり、装備を変更した時にアニメーションしてポーズが変わったりしたいとかありますよね。…ありますよね?
でもそんな時、待機モーションから選択で1のエモートか2のエモート…と複数に遷移して、さらに1のエモートから2のエモート、3のエモート…に遷移して、2のエモートからは…なんてやっているととんでもない形のアニメーションの遷移図ができあがります。私もです。
そんな悩みを解決できそうな方法として、今回はAnyStateを紹介します。
今回の記事で学べる事
- Anyステートの概要、具体的な使い方の手順
AnyStateを使うと下記のような、あっち行ったりこっち行ったりなこんな遷移が

↓こんな感じでスッキリ解決します!


それでは見ていきましょー!
Any Stateとは:概要
AnyStateとは、AnimatorControllerを作成した時に最初から自動で入っているステートです。
このステートはデフォルトで常に存在しているのですが、正直最初は何なのか良くわからないですよね。

そこで公式のAnyStateの説明を見てみましょう。
Any State は常に存在する特殊なステートです。現在どのステートにいるかに影響を受けることなく、特定のステートに遷移したい場合のために存在しています。これは、全ステートに同じ遷移先を追加するのに手早い方法です。Any State は、その特殊な機能によって、ステートの遷移先とすることはできません (つまり、次の遷移先にランダムなステートを選択するための手段としては Any State は使用できませんので注意してください)。
https://docs.unity3d.com/ja/2020.3/Manual/class-State.html
これはどういう事かというと、Anyステートを使用した場合(=Anyステートから遷移を繋いだ場合)に、
現在の再生されているアニメーションがどのステートの場所にいるかに関わらず、条件を満たせば「Anyステート」に飛ばされるという事を意味しています。
例えば下記のようにAnyStateが離れ小島のようにあったとして、

こんな感じで条件を満たせばAnyStateの場所に飛ぶことができます!


それでは、AnyStateの特徴を更に見ていきましょう!
Anyステートの特徴1:EntryとExitからは遷移しない
EntryとExitは特殊なステートです。
Entryステートはここから始まりますよ、と説明するためのステートですのでEntryからAnyステートには遷移せず、Entryの遷移先のステートから遷移します。
Exitステートも同様で、このマシンステートは終了ですよと説明するためのステートになりますので、このステートからAnyステートには遷移しません(終わってないことになっちゃうし)
Exitから遷移する場合は一度アニメーションが終了し、Entryの最初から遷移する事になります。

ステートの説明は下記でも少し触れています。興味のある方はぜひ!
Anyステートの特徴2:Anyステートの遷移先からも遷移する
Anyステートはそのどのステートからでも遷移するという特性上、
AnyStateの遷移先のステートからも遷移します。
これはどういう事かというと、
下図のようにAnyステートから伸びている1番のステートから遷移条件を満たしていれば再度Anyステートに遷移する、その結果再び1番のステートに遷移する、と言う風に自分自身も遷移先に含まれるという現象が起きます。

条件によっては上図の赤い経路をグルグルしてずっと自分自身に遷移し続けることになります。
(なんかちょっと怖い…)
後述しますが、Anyステートの機能でこの自分自身への遷移を防ぐ機能もあります。
Anyステートの特徴3:ステートの遷移先とすることは出来ない
公式の説明にもありましたが、Anyステートをステートの遷移先には出来ません。
(そもそも線を引っ張れません)

これは、Any Stateはどのステートからでも遷移されるという特性なので、任意のステートからの遷移先として与えることは出来ないからですね。
Any Stateの使い方
それでは、Anyステートの概要が確認できた所で使用手順を見ていきましょう。
冒頭でも見せたこの遷移図、
これは待機モーション(オレンジ色のIdleステート)から始まり、その後どのアニメーションからでも条件によって遷移する事ができる(Move01〜Move03からIdleへも遷移可)という構造になっています。

イメージ的には装備画面で待機モーション(Idle)をしていて、武器を変えたら武器毎の決めアニメーションが再生されて、途中で装備変更時のアニメーションも受け取りつつ、待機モーションに戻る。そんなイメージ。
見てわかる通りたった4つのステートでもゴチャゴチャした遷移図になってしまっています。
今回はこれをAnyステートで整理していきながら、機能を見ていきましょう!

バッチリマスターするふる!
最初に:アニメーションステートの状況
最初に、この後の説明をわかりやすくする為に現状どういう仕組みでアニメーション遷移させているかをサッと説明します。
アニメーションは4つ用意してあります。
それぞれの遷移条件として使う為にAnimatorのパラメーターでInt型の「TransitionNo」と言う変数を用意してあります。

この「TransitionNo」の特定の値を遷移の条件として入れています。

それぞれのモーションへの遷移はどのステートからでも下記のような条件になっています。
・待機モーション(idle)
遷移条件:TransitionNo=0、もしくはEntryから無条件に遷移

・モーション01(Move01)
遷移条件:TransitionNo=1

・モーション02(Move02)
遷移条件:TransitionNo=2

・モーション03(Move03)
遷移条件:TransitionNo=3

また、UI上のボタンでそれぞれのアニメーションの名前をクリックすると上記の「TransitionNo」のパラメーターが代入されて条件を満たすようにスクリプトを仕込んであります。
ゲームオブジェクトにスクリプトをアタッチして、

ボタンを押すとCubeにアタッチした任意のメソッドが呼び出されるように設定。

ゲームオブジェクト(Cube)にアタッチしてあるスクリプトは下記のようなシンプルなものです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeMove : MonoBehaviour
{
//最初にアニメータークラスの変数を作成
Animator animator;
void Start()
{
//animatorにゲームオブジェクトのAnimatorを取得させる
animator = GetComponent<Animator>();
}
//あとは各ボタンが押された時に下の該当メソッドを呼び出して整数を代入する
public void Idle()
{
animator.SetInteger("TransitionNo", 0);
}
public void Move01()
{
animator.SetInteger("TransitionNo", 1);
}
public void Move02()
{
animator.SetInteger("TransitionNo", 2);
}
public void Move03()
{
animator.SetInteger("TransitionNo", 3);
}
}
再生するとこんな感じです。

UIボタンを押すと下の「TransitionNo」のパラメータが変化してアニメーションが遷移しているのがわかるかと思います。

それではこれをAnyステートに置き換えてみよう!
手順1:Anyステートに遷移させたいアニメーションを繋ぐ
アニメーションの最初は待機モーションになっていて欲しいのでEntryからIdleステートに繋ぎます。

その後条件によってAnyステート経由で各ステートに遷移して欲しいのでAnyステートから各ステートに繋いでいきます。

この時、各モーション(Move01〜03)からIdleへも遷移したいのでIdleにも繋いでいる事に注意して下さい。

Anyステートの特徴で、Anyステートの遷移先からも遷移すると言うのがあったふるね!
手順2:遷移する条件を作成する
どういった条件でAnyステートから出ているそれぞれのステートに遷移するか、条件を作ります。
これは「最初に:アニメーションステートの状況」と同じようにConditionsのパラメーターで条件付けします。

Idleへの遷移条件はTransitionNo=0、Move01〜03までの遷移条件はそれぞれTransitionNo=1〜3で設定。
この段階で遷移の数が半分になっているのでAnyステートのスッキリ効果テキメンですね!
なお、遷移条件を入れないとそもそもAnyステートに遷移されず、下記のような注意書きが出ます。

この段階で再生して見るとこんな感じになっています。

なんか思っていたのと違う…!!連続再生されている…!
そう、これは「Anyステートの特徴2:Anyステートの遷移先からも遷移する」のせいで条件を満たしている時(TransitionNo=○)にアニメーションの再生中に自分自身へ無限に遷移し続けているからですね。
下側のAnimatorウインドウで見てみても、遷移が連続しているのがわかるかと思います。

そ、そんな…もう終わりふる…
手順3:自分自身への遷移を制限する
AnyStateを使った遷移自体は上手くいきましたが、その後が意図した通りになっていません。
でも大丈夫です!
これを回避する為の方法が既に実装されています。
トランジションを選択してSettingsの中から「Can Transition To Self」のチェックボタンをオフにしてください。

この項目の意味は「自分自身へ遷移できる」という項目になりますのでオフにすることで同じステートへの遷移を制限することができます。
なお、この項目はAny Stateから出ているトランジションのみ設定出来ます。
これをAny Stateから出ているすべてのトランジションに行えばOKです!
では、結果を見てみましょう。

大丈夫そうですね!

よかったふる〜
手順3:Exitに繋いで一手間いれる
手順2までで概ね元の遷移と同じことは出来るようになっています。
…が!せっかくなので最初のイメージである
「待機モーションから武器を選ぶと武器モーションを行い、また待機モーションに戻る」
を更にしっかり作り込んで見たいと思います。
この状態にする為に以下のように考えました。
1.各武器モーションが再生されたら待機モーションに戻る。
2.待機モーションが再生されたら遷移条件(TransitionNo)の値を0に戻す。
1番に関して
各MoveモーションをExitステートに繋ぐことで解決します。
これによって各武器モーションが再生されたら一度アニメーションステートを終了とし、最初から再生が始まるため、武器モーションが再生された後は自動的に待機モーションに戻ります。

この際、Exitに繋いだトランジションの設定をそれぞれExitTimeを1にしてあげてください。
こうすることでアニメーションが再生しきってからExitへ遷移するようになります。

もしトラジションの設定項目に関しては不明点がある場合、下記を参考にしてみてください。
ここで一度再生してみましょう!

違う、そうじゃない…!待機モーションに戻ったらそのまま待機モーションでいてくれ…!
このままではExitから戻って最初から再生が始まったさい、TransitionNoの値に0以外が入ったままになっているのでUIボタンを押していないのに遷移が勝手に始まってしまいます。
そこで2番の処理を入れます。
2番の処理に関しては待機アニメーション(Idle)のアニメーションクリップ中に「アニメーションイベント」を仕込むことで解決する事にしました。
待機アニメーションの0F目にアニメーションイベントを仕込みます。
このアニメーションイベントでは
Cubeにアタッチしてあるスクリプトの下記メソッドが呼び出されるようにしました。
(TransitionNoが0になるメソッド)
public void Idle()
{
animator.SetInteger("TransitionNo", 0);
}
Animationウインドウの0F目にアニメーションイベントを作成。

作成したアニメーションイベントを選択して、
Inspectorで下記のようにスクリプトからIdle()メソッドを呼び出します。

こうすることで待機アニメーションが再生された時にTransitionNoが0に戻るので、待機に戻った時に勝手に遷移するのを防ぐことができます。
※ついでにAnyStateからIdleへの遷移はExitから自動で戻るパターンの時は必要ない事に気づき、削除しました。

大丈夫そうですね!
Moveモーションの再生中に他のMoveを選んだ場合もちゃんと割り込んで遷移しています。


これにて完成ふる!
※ここでは詳しく解説しませんが、もしアニメーションイベントやアニメーションウインドウでの操作など不明でしたら下記記事の「アニメーションウインドウの見方」を参考にしてみて下さい。
TIPS:Entryの遷移先からすぐに遷移させなくても大丈夫
例ではEntryから待機モーションを再生させてそこからAnyステートに遷移するような作りになっていました。
しかし、必ずしもこの形が良いとは限りません。
例えば、アクションゲーム等で待機中でも歩き中でも攻撃モーションに遷移できる、という使い方もありますね。
この場合は本筋のアニメーションは待機と歩行にして、操作条件によってどちらの状況からでも攻撃モーションに遷移させる、といった使い方もできそうです。


待機、歩行、どちらからでも攻撃モーションに移れる!
TIPS:Any Stateが使えそうな場面
ここまでの工程を見てみて、このAnyステートを使うことで、
・装備の着せ替えアニメーションの設定
・どんな状態からでも接触したら発生するダメージモーション
・アクションのキャンセルコマンド
・どの状態からでもボタン操作で特定のUIを呼び出す
など、さまざまな使い方が出来そうです。

夢が広がリングふる
終わりに
今回はAnyStateについて詳しく見ていきました。
AnyStateは複雑になってしまった遷移を整理できると共に、どこからでも遷移が出来ると言う特性を使うことで条件設定によって様々な場面に使える事ができそうです。
なんだかグチャグチャしてきたなぁ、と思ったら思い出して見てください。もしかしたら使えるかも。
◾️Unityアニメーションのマトメ記事はこちら
えきふるからのご相談!
当ブログ「えきふるゲームラボ」では出来るだけ分かり易く読みやすい記事の作成を目指しています!
もし読んでくださった方の中で
「ここが良く分からなかった」「ここをもう少し掘り下げて欲しい」等ありましたら
ぜひコメントで教えて下さい!

コメント貰えると元気も出ますので、どうぞお気軽にお願いしますふる!
※このブログは、UnityTechnologiesまたはその関連会社が後援または提携しているものではありません。「Unity」は、UnityTechnologiesまたはその関連会社の米国およびその他の国における商標または登録商標です。