FiveHeartsの技術記事

音をまとめて管理しよう

ゲーム開発において、BGMやSEは不可欠です。
基本的にはどのシーンにおいても必要なものなので
一元管理できるといいですよね。
その方法を今回はご紹介したいと思います。
今回は管理方法についての話なので音の鳴らし方については
『・初歩的な音の鳴らし方』をご参照ください。

まずSoundManagerというクラスのC#ファイルを作ります。
そしてStart関数の上にAwake関数を作ります。
このAwake関数はStart関数よりも先に呼ばれるという性質の
特殊な関数です。

				  
//=====================
//シングルトンの定義(Awake使用)
//=====================
public static SoundManager instance;

private void Awake()
{
	if (instance == null)
	{
		instance = this;
		DontDestroyOnLoad(this.gameObject);
	}
	else
	{
		Destroy(this.gameObject);
	}
}
				
				

このAwake関数で何をしているのかというと、
『シーンをまたいでもこのスクリプトをアタッチしたオブジェクトを破壊するな』
ということを記述しています。
つまりシーンをまたいでもこのスクリプトがアタッチされた
オブジェクトは存続し続けます。
そして『もし同じ名前のオブジェクトが既に存在していたら
オブジェクトを破壊しろ』とも書かれています。
これにより重複を防いでいます。

				
public AudioSource audioSourceSE; // SEのスピーカー
public AudioClip[] audioClipSE_System; // ならす素材
public AudioClip[] audioClipSE_Story; // ならす素材

public void PlaySE(string type,int index)
    {
        switch (type)
        {
            default: return;
            case "System":
                audioSourceSE.PlayOneShot(audioClipSE_System[index]); // SEを一度だけならす
                break;
            case "Story":
                audioSourceSE.PlayOneShot(audioClipSE_Story[index]); // SEを一度だけならす
                break;
        }
    }
				
				

次は実際にSEを鳴らす処理ですね。SEの場合はPlayOneShot()を使います。
BGMの場合はPlay()ですね。
引数にはAudioClip[]の配列とそのインデックスを指定しています。
バトルやシステム音、ストーリーパート専用SEなどをごちゃませで
管理しているとややこしくなるので、
この実例では配列を分けて管理しています。
この実例を呼び出すときは下記のようになります。

				
SoundManager.instance.PlaySE("Story", 6);
				
				

これでAudioClip[] audioClipSE_Storyの6番目のSEが鳴ります。
BGMも基本は同様です。
短いSEはともかく、BGMやキャラボイスというのはゲームにとっては
かなり重たいアセットとなります。
実際のゲーム開発では『Addressable Asset System』を
使用しながらのほうが良いでしょう。
またバトルSEのようにSEが重なる可能性がある場面では
SEの重複による音割れを防ぐための対応も求められます。
これらより実践的な内容については上級編である
『・実用的な音源管理の実装方法』にて紹介しています。

今回の記事はここまでです。
それではまた別の記事でお会いしましょう。