シンプルなアクションゲームを作ってみようの第8回です。
今回はキャラクターのアニメーションの状態と遷移を作成していきたいと思います。
前回はキャラクターの移動スクリプトを作成しました。
シンプルなアクションゲームを作ってみようの他の記事は
シンプルなアクションゲームを作るのを通してUnityの使い方を学ぶカテゴリです。
から参照出来ます。
アニメーションの管理
前回の記事で、キャラクターを移動させるスクリプトを作り、キーボードの矢印キーで床の上を移動出来るようにしました。
ただ、移動している時にキャラクターはずっとTポーズ(完全なTではないですが・・・)のままで移動しています。
Tポーズと言ってもチョコプラとは関係なく、人型キャラクターモデルはTポーズにしておくとボーンを付ける時にやりやすくなるからだと思います(違う理由かもしれませんが)。
Tポーズのまま動くのは、キャラクターにアニメーションをさせていない為です。
なので、今回はキャラクターにアニメーションを管理するAnimatorControllerを取り付け、どういう状態の時はこのアニメーション、何らかの条件が成立したら別のアニメーションを再生するということをしてみたいと思います。
今回の場合、動いていない時は「立っているアニメーション」、移動している時は「歩いているアニメーション」の二つの状態を作り、移動しているかどうかで、その状態を互いに遷移出来るようにします。
AnimatorControllerを作成する
文章だけを見てもわからないと思いますので、実際にキャラクターのアニメーションを管理するAnimatorControllerを作成し、キャラクターに設定していきます。
まずはAnimatorControllerを入れておくフォルダをAssetsフォルダ内に作成し、名前をAnimatorsとします。
Assets/Animatorsフォルダ内で右クリックからCreate→Animator Controllerを選択します。
出来たら名前をPlayerとします。
Playerアニメーターコントローラーを、Stage1シーンのEthanのインスペクタのAnimatorコンポーネントのControllerにドラッグ&ドロップして設定します。
これで、EthanはPlayerアニメーターコントローラーでアニメーションの状態と遷移を管理されます。
Playerアニメーターコントローラーの状態と遷移を作成する
Ethan用のアニメーターコントローラーの作成と設定が出来たので、次は状態と遷移を作成していきます。
Playerアニメーターコントローラーを選択した状態でAnimatorウインドウを開きます。
Animatorウインドウが開いていない場合は、UnityメニューのWindowからAnimation→Animatorを選択する事でウインドウが開きます。
状態の作成
まずは、アニメーターコントローラーに「何もしていない状態」と「歩いている状態」を作成します。
Animatorウインドウ内で右クリックからCreate→Emptyを選択します。
以下のようにNew Stateという状態ができるので、選択します。
Animatorウインドウでは、マウスの中ボタンを押しながらドラッグすると状態表示画面をスクロールすることが出来、状態をマウスの左ボタンを押しながらドラッグすると位置を変えることが出来ます。
New State状態はEntryから矢印が繋がっているので、New Stateが最初に再生されるアニメーション状態になります。
New State状態を選択して、インスペクタで名前をIdleに変更します。
さらに、Motionの右のアイコンを押し、スタンダードアセットのHumanoidIdleアニメーションを設定します。
これでIdle状態の時はHumanoidIdleアニメーションが再生されます。
さらに、Foot IKにチェックを入れ、アニメーション時に足が接地した時は地面に足を付けるようにします。
Idle状態を作った時と同じようにWalk状態を作成し、MotionにHumanoidWalkアニメーションを設定します。
これでIdle状態とWalk状態が出来ました。
アニメーションパラメータの作成
次はアニメーションの状態を遷移する条件であるアニメーションパラメーターを作成していきます。
アニメーションパラメータ―の型はFloat、Int、Bool、Triggerになります。
Floatは小数点、Intは整数、Boolはtrueとfalse、Triggerはトリガーを引きます。
BoolとTriggerは似ていますが、Boolはtrueとfalseの切り替えが出来ますが、Triggerはトリガーした時の一度だけ条件を成立します。
今回はキャラクターが移動しているかどうかでアニメーションを切り替えるので、Float型のSpeedというアニメーションパラメータ―を作成し、その値によってIdleとWalkの状態を切り替えるようにします。
AnimatorウインドウのParametersタブの+を押し、Floatを選択します。
名前をSpeedとします。
これでアニメーションパラメータ―が出来ました。
遷移条件の設定
次に、アニメーションパラメータ―Speedの値によって、IdleとWalkの状態を行き来する条件を設定していきます。
Idle状態を選択し、右クリックからMake Transitionを選択します。
矢印が出てくるのでWalk状態を押します。
すると以下のようにIdleからWalkへの遷移矢印が出来ます。
次はIdleからWalkへと繋がった矢印を選択し、インスペクタで遷移条件を設定します。
インスペクタでは以下のように表示されます。
まずはアニメーションの遷移条件を設定します。
Has Exit Timeのチェックを外します。
Has Exit Timeはアニメーションの再生が終わったら次の状態へと遷移するという条件で、ここでチェックをしていると現在のアニメーションの再生が終わるまで次の状態へと遷移しません。
次にConditionsの+を押し先ほど作ったアニメーションパラメータ―のSpeedを設定し、Greaterの0.1を設定します。
Greaterは右の数値以上の時でLessの場合は以下の時に条件が成立します。
今回の場合はアニメーションパラメータ―の数値が0.1以上になったらIdleからWalkへと遷移する条件にしています。
次にIdleアニメーションとWalkアニメーションのブレンドを操作します。
IdleからWalk状態へと遷移する時にIdleから少しずつWalkアニメーションへと変わっていきますが、そのブレンドの設定をすることが出来ます。
グラフの左上の目のアイコンをドラッグして一番左にドラッグし、その右の矢印アイコンを左にドラッグしてIdleからWalkへのアニメーションのブレンド時間を短くします。
さらにSettingsの横の矢印を押し、Interruption SourceをNext Stateにし、次の遷移条件が成立した時にすぐさま遷移出来るようにします。
これはWalk→Idle→Walkという遷移条件が成立した時にWalk→Idle→Walkと通常通りアニメーションをブレンドすると一瞬アニメーションが止まっているように見えてしまう為、次の遷移条件が成立したらすぐさま次の状態へと遷移させる為にNext Stateを設定します。
これでIdle→Walkの遷移条件が出来たので、次はWalk→Idleの遷移条件を作ります。
やる事は同じなので割愛しますが、以下のようになります。
Walk→Idleへの遷移条件はほとんどが同じですが、ConditionsでSpeedがLessで0.1という条件になります。
これはアニメーションパラメータのSpeedが0.1以下になった時にIdleへと遷移させる為です。
これで機能が出来ました。
スクリプトからAnimatorControllerのアニメーションパラメーターを操作する
AnimatorControllerの状態を遷移を作成し、アニメーションパラメーターのSpeedによって状態を遷移出来るようになりました。
次はスクリプトからアニメーションパラメーターのSpeedの値を変更します。
まずはフィールドにAnimator型のanimatorを用意し、Startメソッドで自身のゲームオブジェクトからAnimatorコンポーネントを取得し参照を入れる処理を追加します。
1 2 3 4 5 6 7 | private Animator animator; void Start() { animator = GetComponent<Animator>(); } |
Moveメソッドでvelocity.magnitudeで速度ベクトルの大きさを求め、それが0より大きい場合は
animator.SetFloatを使って第1引数で指定したアニメーションパラメーター名にvelocity.magnitudeの値を入れます。
それ以外(速度ベクトルの大きさが0以下)の時はアニメーションパラメーターのSpeedに0fを入れます。
0の後のfという文字はfloatであることを明示しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // 移動値と向きの計算 private void Move() { // 接地している場合 if (isGrounded) { // 移動速度の長さが0より大きければ歩くアニメーション if (velocity.magnitude > 0f) { animator.SetFloat("Speed", velocity.magnitude); } else { animator.SetFloat("Speed", 0f); } // 移動速度を初期化 velocity = Vector3.zero; } // 移動入力値 input = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical")); // 速度の計算 velocity = new Vector3(input.normalized.x * moveSpeed, 0f, input.normalized.z * moveSpeed); } |
これでアニメーションが切り替わるようになりました。
実行してキャラクターを動かしてみる
機能が出来たのでUnityエディターで実行して確認してみましょう。
キャラクターを動かすと歩くアニメーションが再生され、止まると立っているアニメーションが再生されるようになりました。
しかし、ここでひとつ問題があります。
それはキャラクターの移動する速さは1秒間で2mに設定しているのに、明らかにそれ以上の速さで動いている事です。
これはEthanのAnimatorのApply Root Motionにチェックが入っている為です。
Apply Root Motionにチェックが入っていると、キャラクターの位置や回転をアニメーション自体の位置や回転を使って行うようになります。
つまり、アニメーションで移動や回転を行うように作っている場合は、その変更値がキャラクターのTransformに影響を与えてしまいます。
今回のゲームではスクリプトでキャラクターの移動や回転を行っていますので、AnimatorのApply Root Motionのチェックを外し、アニメーションのデータをTransformに反映しないようにします。
これで完成です。
実行してみると以下のようになりました。
終わりに
今回はキャラクターのアニメーションを管理するアニメーターコントローラーを作成しました。
キャラクターが移動が出来るようになったり、アニメーションが再生されたのでなんだかうれしくなりますね。(^_^)v
キャラクターをカメラの範囲外に移動させると見えなくなってしまいます。
そこで、次回はキャラクターの移動に合わせてカメラを移動させるようにしていきたいと思います。