【Unity】ランダムにアニメーションを再生する
Mecanim(Animator)を出来る限り活用してランダムにアニメーションを再生する方法についてです。
FacebookのUnityユーザー助け合い所で面白い話題が上がっていたので、試しに作ってみました。
何時もと違うアニメーションの再生
主に待機モーション等、常に同じモーションではなく稀に違うモーションを仕込んでおくと、「凄い作り込みだ」みたいな反応になる事があります。
実際、多くのゲームでは稀に違うモーションを行ったり、コントローラーを投げ捨てて放置すると少し違った動きが仕込まれている事が多いです。
ランダムなアニメーションの再生
ランダムなアニメーションの再生を考えてみます。
一番手っ取り早いのは、スクリプトでランダムにアニメーションをPlayで再生してしまう事でしょう。ただ、今回はMecanimの機能を出来る限り使ってやってみます。
この使い方を少し応用すると、シーケンスを持ったBlendTreeを実現出来る気がしますが、それはそれ、これはこれ。
数値を指定して再生するアニメーションを決める
まずは、数値で再生するアニメーションを決める動きを実現してみます。
Animatorの再生アニメーション指定にはParameterを使用するわけですが、Parameterにintを使用するとequal(=)が使用出来ます。
これを使用して、アニメーション開始時に再生するアニメーションが選別出来るようになります。
サブステートマシンで擬似的なBlendTreeに
また構造を単純にするため、複数のアニメーションはサブステートにまとめておきます。これで、WAITのサブステートマシンにアニメーションを遷移すれば、Randomの値に従ってアニメーションを再生してくれるようになります。
アニメーションを繰り返す
次に問題になるのが、アイドルモーションを「繰り返す」ようにする事です。今回の動作で期待するのは、延々と同じアニメーションをループするのではなく、アニメーションを繰り返しつつ、稀に違うアニメーションを行う事です。
この点でもSubStateMachineが有効に働きます。
やっているのは、SubStateMachineの遷移先を「自分」に指定している事です。これでExitでステートマシンから抜けた際に他のTransitionが無ければ再度Entryから入るようになります。
ちなみに、ココで全てのコンディションがFalseになると、謎の動作になります。大抵の場合、一番親のEntryから再開しますが、稀に現在のStateに残ったりと色々とアレなので、そこんとこ注意です。
ランダムにParameterを切り替える
最後にParameterの値をランダムに切り替えてみます。
切り替える方法はMonobehaviour経由でやっても良いのですが、どうせSubStateMachineに入る瞬間に1回やれば良いので、StateMachineBehaviourでやってしまいます。
ここで面白いのは、「ステートに入った」時のコールバックとしてOnStateMachineEnterとOnStateEnterがある事です。
どちらもステートに入った時に呼ばれるコールバックですが、SubStateMachineにセットした場合少し異なります。
OnStateMachineEnterの場合はサブステートに入った時に1回、OnStateEnterはサブステート内でステートが変わる度に呼ばれます。
これの応用で、OnStateUpdateを親ステートにセットすれば、特定のSubStateに居る限り毎フレーム処理を呼び出したり出来ます。
ちなみに「OnStateMachineEnter」はあくまでEntry時なのでなのか、最初に再生するアニメーションがSubState内にあると動作しませんでした。
要するに、Animatorの起動時モーションはSubState以外である必要があります。
完成
ということで、Animatorの機能を出来る限り活用して、ランダムにアニメーションを再生するアプローチでした。
そういえばUnity 2017.3からAnimatorがズーム出来るようになりました。個人的にはソレより検索と一覧表示が欲しい。切実に