おもちゃラボ

Unityで遊びを作ってます

【Unity】Animatorでステートが遷移するタイミングを検知する

Animatorを使っていると、あるステートから別のステートへ遷移したタイミングを検知して、アクションを起こしたいことがあります。

例えばジャンプアニメーションが終了して着地したタイミングで効果音を鳴らしたいとか、カメラを振動させたい、といった場合です。

このような場合はStateMachineBehaviourというコールバック用のスクリプトを使うと便利です。

f:id:nn_hokuson:20170407193927p:plain

StateMachineBehaviourの使い方

StateMachineBehaviourはAnimatorにアタッチして使う専用のスクリプトです。ここでは2Dユニティちゃんのサンプルを使って、ジャンプ終了のタイミングを検知してみます。まずはAnimatorを開くと次のような構成になっています。

f:id:nn_hokuson:20170407194657p:plain

Animatorにスクリプトをアタッチするため、ウインドウ右側のインスペクタに表示されている「Add Behaviour」をクリックして、スクリプトをアタッチしてください。

f:id:nn_hokuson:20170407194625p:plain

作成したスクリプトをプロジェクトビューから開くと、次のコールバック関数がコメントアウトされています。

  • OnStateEnter
  • OnStateExit
  • OnStateMachineEnter
  • OnStateMachineExit
  • OnStateMove
  • OnStateUpdate
  • OnStateIK

よく使うのは、OnStateEnterとOnStateExitです。これらはそれぞれ、ステートに入ったときとステートから出たときに呼び出されるコールバック関数です。

OnStateMachineEnter/Exitはそれぞれスクリプトをアタッチしたアニメーションレイヤに入ったときと出たときに呼び出されます。

StateMachineBehaviourから別のメソッドを呼び出す

ジャンプが終了したタイミングでカメラを振動させたいので、ステートが終了したときに呼び出されるOnStateExitメソッドを使います。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StateController : StateMachineBehaviour {
    // OnStateExit is called before OnStateExit is called on any state inside this state machine
    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
        if (stateInfo.IsName ("JumpDown"))
        {
            Camera.main.GetComponent<CameraShaker> ().Shake ();
        }
    }
}

ここでは、ジャンプが終了したタイミング(JumpDownステートを抜けるタイミング)を検知するため、AnimatorStateInfoのIsNameメソッドを使って、現在のステートがJumpDownステートかどうかを調べています。

JumpDownであれば、カメラオブジェクトにアタッチしたCameraShakerスクリプトのShakeメソッドを呼び出しています。

カメラを振動させるスクリプトをアタッチする

ユニティちゃんがジャンプし終わったときに呼び出すスクリプトを作ります。
カメラを振動させるスクリプトは次のようになります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraShaker : MonoBehaviour {
    IEnumerator _Shake() {
        for (int i = 0; i <= 360 * 1; i += 60) {
            float y = 0.2f*Mathf.Sin (i * Mathf.Deg2Rad);
            transform.position = new Vector3 (0, y, -10);
            yield return null;
        }
    }
    public void Shake() {
        StartCoroutine (_Shake ());
    }
}

これをヒエラルキービューのMainCameraにアタッチしておきましょう。

f:id:nn_hokuson:20170407194844j:plain

実行結果

実行結果は次のようになります。ジャンプの終了のタイミングでちゃんと画面が振動していますね。

f:id:nn_hokuson:20170407194853g:plain
© Unity Technologies Japan/UCL