ホーム < ゲームつくろー! < Unity/サウンド編

サウンド編
その2 トリガー駆動のタイミングでSEを鳴らす


 前章でUnityでのサウンド再生の根っこを見てきました。Audio ClipがくっついたAudio Soundを世界にポイっと投げれば勝手に音が鳴るんですから簡単です。でも、ゲームで実際に使うにはもう少し考える事があります。

 SEは何らかのきっかけで初めて音が鳴ります。例えばマリオがジャンプしたら「ぴゅい〜ん」とジャンプ音がしますよね。「ジャンプをしたら」というのが「きっかけ」で、そういうきっかけの事を「トリガー」と言います。お手元のゲームを観察すると分かると思いますが、SEはトリガー駆動が殆どです。

 ではUnityでトリガー駆動なSEを再生するにはどうしたら良いか?試行錯誤してみます。



@ まずはトリガーを作ろう

 まずはトリガーそのものを作ってみましょう。実際はあらゆるトリガーが考えられますが、今はテストなので「キーを押したら」にしておきます。

 Unityでキー入力を取るには「Input」というグローバルなクラスをスクリプト上で使用します。スクリプトを動かすにはヒエラルキにGameObjectが必要なので、メニューの[GameObject]→[Empty Object]で空のオブジェクトを一つ追加して「Player」という名前に変更しておきましょう。

 PlayerゲームオブジェクトにくっつけるPlayerスクリプトをProject内に追加します。このUpdateメソッド内でInputを使ってキーの押し下げを検出します:

Player.cs
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
    void Update () {
        if ( Input.GetKeyDown(KeyCode.A) == true ) {
            // Torigger
            Debug.Log( "A!" );
        }
    }
}

このスクリプトをPlayerゲームオブジェクトにくっつけてゲームを再生すると、Aキーを押すたびにConsoleウィンドウに「A!」と表示されます。これでトリガーが出来ました。



A 「A」を押すたびにSEを鳴らす

 音を鳴らすにはどうしたら良いかおさらいします。音を鳴らす人は「AudioSource」さんです。この人に音の素であるAudioClipをくっつけるとその音が鳴ります。AudioSourceさんはComponentなので、GameObjectにくっつけないと存在出来ません。一方AudioClipはリソースなので、スクリプト内に保持する事が出来ます。

 そこで、PlayerさんにAudioSourceコンポーネントをくっつけて、AuidoClipを一つ保持させる事にしましょう。AudioSourceコンポーネントは、前章でも行ったヒエラルキ上でメニューの[Component]→[Audio]→[Audio Source]でくっつきます。

 一方で上のPlayerスクリプト内にAudioClipを一つ設けます。publicで公開するとInspector上にAudioClipの設定欄が一つできますので、そこにProject内のAudioClip(kaifuku)をドラッグしてあげます。PlayerゲームオブジェクトのInspectorはこんな感じになります:

Player.cs
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

    public AudioClip audioClip;

    void Update () {
        if ( Input.GetKeyDown(KeyCode.A) == true ) {
            // Torigger
            Debug.Log( "A!" );
        }
    }
}

Audio SourceのAudio Clipは空のままにするのが大切です。ここに入れるとトリガー関係無くいきなり音が鳴ってしまいます。

 音を実際に鳴らすのは、大切なので何度でも言いますが、Audio Sourceさんです。今、PlayerスクリプトがくっついているPlayerゲームオブジェクトにはAudio Sourceがあるんだろうなぁ〜という前提になっていますので、Player.StartメソッドでAudio Sourceコンポーネントを取得する事ができるはずです:

Player.cs
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

    public AudioClip audioClip;
    AudioSource audioSource;

    void Start() {
        audioSource = gameObject.GetComponent<AudioSource>();
    }

    void Update () {
        if ( Input.GetKeyDown(KeyCode.A) == true ) {
            // Torigger
            Debug.Log( "A!" );
        }
    }
}

実際これでAudioSourceコンポーネントを取得できます。出来ちゃえばこっちのもんで、鳴らしたいauidoClipをAudioSourceにスクリプト上からくっつけてしまえます。これはAudioSource.clipというメンバに代入するだけです:

Player.cs
void Start() {
    audioSource = gameObject.GetComponent<AudioSource>();
    audioSource.clip = audioClip;
}

さらにスクリプト上からaudioSourceに「再生せよ!」っと命令するにはAudioSource.Playメソッドを呼び出します:

Player.cs
void Update () {
    if ( Input.GetKeyDown(KeyCode.A) == true ) {
        // Torigger
        Debug.Log( "A!" );
        audioSource.Play();
    }
}

これで「A」を押すと音が鳴ります(^-^)。まとめると、スクリプト上からSEを鳴らすには、

・ AudioClipをスクリプト内に用意
・ AudioSourceをスクリプト内に用意
・ AudioSource.clipにAudioClipを代入
・ AudioSource.Playメソッド呼び出し

でOKです。



B SEが重ならない!

 さて、上の実装で実際に「A」を押す度にSEが鳴るのですが、「A」をダダダダダダ!っと連打すると、SEがその度に最初から再生されるのがわかります。長いSEを使うと顕著にわかるはずです。状況にもよりますが、SEは重なって鳴って欲しい事が殆どです。

 「A」を押す度にSEを重ねるには、AudioSource.PlayメソッドではなくてAudioSource.PlayOneShotメソッドで音を鳴らします。PlayOneShotメソッドはAudioClipを直接引数に取り、呼ばれる度にそのSEをどんどん重ねてくれます:

Player.cs
void Update () {
    if ( Input.GetKeyDown(KeyCode.A) == true ) {
        // Torigger
        Debug.Log( "A!" );
        audioSource.PlayOneShot( audioClip );
    }
}

これで「A」を連打すると、音が途切れずに重なる事がわかります。

 PlayメソッドとPlayOneShotメソッドは、多分前者がBGM、後者がSEで使うように出来ているのかなと思います。


 このように、AudioClipとAudioSourceがスクリプト上でわかっていれば、任意のタイミングでSEを鳴らす事は簡単です。ただ、これで使い勝手が良いかというと「ん〜〜…」となってしまいます。SEって何かする度に色々な所から鳴ります。それを逐一GUIで追加していくのは正直しんどいのです。どうせならばスクリプトの中だけで完結してくれると気楽です。次の章ではその辺りを考えて行く事にしましょう。