ゴマちゃんフロンティア

アザラシが大好きなエンジニアの開発日記です

【Unity】AnimatorControllerのステート遷移時に音を再生する方法

time 2017/05/13

というわけで、今回はUnityに関するちょっとしたお話です。
タイトル通り、「AnimatorControllerのステート遷移時に音を再生する方法」を考えてみます。「ジャンプ時」や「大技を放つ前」に効果音を出したいときに使います。
プレイヤーのスクリプトでステートを判定することでも出来ますが、AnimatorController上で設定できた方がスッキリしてよさそうです。

Unityで「音を出す」となると、AudioSourceコンポーネントを使うのがメジャーでしょうか。
しかしAnimatorController上ではStateMachineBehaviourを継承したクラスしか設定できません。AudioClip型のフィールドを定義してインスペクター上から音を設定し、スクリプト上で再生できるように処理してあげます。

AudioSource.PlayClipAtPoint()を使う

単に音を出したいのであれば、AudioSource.PlayClipAtPoint()を使うのが手っ取り早いです。

using UnityEngine;

public class Attack : StateMachineBehaviour {
    public AudioClip se_clip;

    public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
        AudioSource.PlayClipAtPoint(se_clip, animator.gameObject.transform.position);
    }
}

AudioClipと再生する位置を渡すことで、AudioSourceが設定されたGameObjectが生成されます。

生成されたGameObjectは再生後、自動的に削除されます。

再生用のGameObjectを動的に生成する

「再生用のGameObjectをモーションに合わせて移動させたい!」なんて場合、上のPlayClipAtPoint()では厳しいです。再生用のGameObjectを操作するには自分で生成するしかなさそうです。
ただしAudioSourceだけでは再生後に削除されないため、簡単な削除用スクリプトを作っておきます。

using UnityEngine;

public class AutoDestroy : MonoBehaviour {
    public float time;

    void Start () {
        Destroy(gameObject, time);
    }
}

新規でGameObjectを生成し、必要なコンポーネントを設定します。
GameObject自体の生成はnew演算子で、設定するコンポーネントはAddComponent()で追加します。

using UnityEngine;

public class Attack : StateMachineBehaviour {
    public se_clip se_clip;

    public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
        GameObject soundObject = new GameObject();
        soundObject.name = se_clip.name;

        AudioSource audioSouce = soundObject.AddComponent<AudioSource>();
        audioSouce.clip = se_clip;
        AutoDestroy autoDestroy = soundObject.AddComponent<AutoDestroy>();
        autoDestroy.time = se_clip.length;

        soundObject.transform.position = animator.gameObject.transform.position;
        se_clip.Play();
    }
}

あとはsoundObjectをTransform.setParent()等で子オブジェクトにしましょう。animator.gameObjectでそのAnimatorControllerを実行しているオブジェクトが参照できるので、transformgetComponent()であれこれできます。
頻繁に使用する場合は専用に静的関数を作り、ユーティリティ化してしまうと便利です。

あとがき

そんなわけで、AnimatorController上で音を出す方法に関するお話でした。
やや強引な気もしますが、「気まぐれと勢い」なブログなのでこんなものでいいでしょう。「もっと効率よく音出したい!」な方はより深く突っ込んでいるサイトを探してみてください。

down

コメントする