【Unity】サウンド管理システムの作り方!BGMや効果音を楽に鳴らせるようにしよう

サウンド管理クラスの作り方 ゲーム開発

今回はUnityのサウンドに関する話題で、

簡単なサウンド管理システム(SoundManager)の作り方

をご紹介するという内容になっています。

Unityで一定以上の規模のゲームを作っていると、BGMや効果音など様々なサウンドをどうやって管理するか?という問題が出てきます。これはどういうことかというと、例えば各サウンドを管理せずにバラバラに鳴らした場合

  • 音量をまとめて調整できない
  • BGMなど同時に一曲しか流れないはずの曲が複数流れてしまう
  • シーンを切り替えたときにBGMが途切れてしまう

といった問題が発生することがあるのです。したがってサウンド管理は地味ですが大切な機能だと言えるでしょう。

ただそうは言っても「サウンド管理なんてどうやってやればいいんだろう?」と悩んでしまう初心者の方は多いのではないでしょうか。そこでここでは、シンプルながら十分実用的なサウンド管理システムの作り方をご紹介しますね。

今回作るサウンド管理システムの仕様・構造

まずはじめに、今回作るサウンド管理システムの仕様や構造についてご説明します。要点は次のとおりです。

  • SoundManagerオブジェクトにAudioSourceコンポーネントを2つアタッチし、それぞれBGM用と効果音用とする。
  • SoundManagerオブジェクトはシーンに一つだけ存在するものとし、シーンを切り替えても削除されないように設定する。
  • BGMは同時に1曲だけ、効果音は同時に複数鳴らすことができる。
  • BGM・効果音ともに2Dサウンド専用とする。
  • BGMのクロスフェード(=曲を滑らかに切り替える手法)はここでは実装しない。

今回は初心者の方でも理解しやすい2Dゲーム向けのサウンド管理システムとします。3Dゲームに使うためには少し拡張が必要となるでしょう。

サウンド管理システムの作り方

ではここからが本題ですが、サウンド管理システムの作り方を具体的に説明していきます。

SoundManagerオブジェクトの作成

まずはSoundManagerのゲームオブジェクトを作成します。次の作業を行ってください。

  1. AudioSourceを2つアタッチして設定を行う
  2. タグを「SoundManager」にする

AudioSourceを2つアタッチして設定を行う

はじめに「SoundManager」という名前の空のゲームオブジェクトを作成し、AudioSourceコンポーネントを2つアタッチして次の画像のように設定を行ってください。

SoundManager用のAudioSourceコンポーネント

上がBGM用、下が効果音用です。BGM用のほうは繰り返し再生させたいので「ループ」をONにしておきましょう。

タグを「SoundManager」にする

次に「SoundManager」という新しいタグを作成し、先ほどのSoundManagerオブジェクトのタグとして設定しておいてください。

SoundManagerのC#スクリプト

そうしたらSoundManager用のC#スクリプトを書きます。新しいC#スクリプトを作成し、ファイル名をSoundManagerに変更したら次のスクリプトを書いてください。

using UnityEngine;

public class SoundManager : MonoBehaviour
{

    [SerializeField]
    AudioSource bgmAudioSource;
    [SerializeField]
    AudioSource seAudioSource;

    public float BgmVolume
    {
        get
        {
            return bgmAudioSource.volume;
        }
        set
        {
            bgmAudioSource.volume = Mathf.Clamp01(value);
        }
    }

    public float SeVolume
    {
        get
        {
            return seAudioSource.volume;
        }
        set
        {
            seAudioSource.volume = Mathf.Clamp01(value);
        }
    }

    void Start()
    {
        GameObject soundManager = CheckOtherSoundManager();
        bool checkResult = soundManager != null && soundManager != gameObject;

        if (checkResult)
        {
            Destroy(gameObject);
        }

        DontDestroyOnLoad(gameObject);
    }

    GameObject CheckOtherSoundManager()
    {
        return GameObject.FindGameObjectWithTag("SoundManager");
    }

    public void PlayBgm(AudioClip clip)
    {
        bgmAudioSource.clip = clip;

        if(clip == null)
        {
            return;
        }

        bgmAudioSource.Play();
    }

    public void PlaySe(AudioClip clip)
    {
        if(clip == null)
        {
            return;
        }

        seAudioSource.PlayOneShot(clip);
    }

}

難しい処理は特にないのでソースコードを読んでいただければ処理内容が分かると思います。書けたらこれをSoundManagerオブジェクトにアタッチし、AudioSourceをそれぞれの欄に登録しましょう。

サウンド管理システムの使い方

さて、それでは次に先ほど作ったサウンド管理システムの使い方をご説明します。大雑把に言うと

  1. SoundManagerを検索して取得するか、予めインスペクターで登録しておく
  2. 必要なタイミングでPlayBgm関数またはPlaySe関数を呼び出す

という感じに使えばOKなのですが、一応サンプルを掲載しておきますね。

BGMを再生する場合のサンプル

まずはBGMを再生する場合のサンプルです。

using UnityEngine;

public class BgmSample : MonoBehaviour
{

    [SerializeField]
    SoundManager soundManager;
    [SerializeField]
    AudioClip clip;

    void Start()
    {
        soundManager.PlayBgm(clip);
    }

}

上記のようにSoundManagerへの参照を格納する変数を作るか、もしくはGameObject.FindGameObjectWithTag関数を使ってタグでSoundManagerを検索して取得するかしてからPlayBgm関数を呼び出せばOKです。

効果音を再生する場合のサンプル

次は効果音を再生する場合のサンプルです。

using System.Collections;
using UnityEngine;

public class SeSample : MonoBehaviour
{

    [SerializeField]
    SoundManager soundManager;
    [SerializeField]
    AudioClip clip;
    [SerializeField, Min(0)]
    float waitTime = 0.5f;

    bool isPlaying = false;
    WaitForSeconds wait;

    void Start()
    {
        wait = new WaitForSeconds(waitTime);
    }

    void Update()
    {
        if (isPlaying)
        {
            return;
        }

        StartCoroutine(nameof(SeTimer));
    }

    IEnumerator SeTimer()
    {
        isPlaying = true;

        yield return wait;

        soundManager.PlaySe(clip);

        isPlaying = false;
    }

}

やり方自体はBGMの場合とほぼ同じです。ただしこちらのサンプルではチェックのために指定した効果音を一定間隔で鳴らすようにしています。

おわりに

以上、Unityでのサウンド管理システムの作り方をご説明しました。サウンド管理は地味ですがとても重要な仕組みになりますので、ぜひ上記の内容を参考にしていただきご自身のゲームに導入していただけたらと思います。

この記事がUnityでのゲーム開発のお役に立てば幸いです。