学習記事一覧 · Unity

【学習】Unity 6:シーンが切り替わっても BGM を止めない(DontDestroyOnLoad とシングルトン)

Unity でゲーム制作をしていると、タイトル画面・ゲーム画面・リザルト画面など、複数シーンを切り替える構成が一般的になります。

そのとき多いのが次の問題です。

  • シーンが切り替わるたびに BGM が止まる

今回は、シーンをまたいでも BGM を流し続ける考え方と、Unity 6 での Inspector の違いまで、ひと通り整理します。


今日のゴール

  • なぜシーン切替で BGM が止まるか説明できる
  • DontDestroyOnLoadシングルトン(1 個だけ残す) で BGM マネージャーを実装できる
  • Unity 6 の Audio Source まわりの表示の変化を混乱なく扱える

なぜ BGM が止まるのか

Unity では、シーンをロードし直すとそのシーンに属していた GameObject は破棄されるのが基本です。

例えば次のような構成だとします。

  • TitleScene
    • BGMManagerAudioSource 付き)

ここから GameSceneSceneManager.LoadScene などで移ると、TitleScene 側の BGMManager も一緒に消えるため、AudioSource の再生も止まります。

つまり問題の本質は「音だけ」ではなく、シーンに置いたオブジェクトはシーンとセットで寿命が切れるという Unity のルールです。


解決の考え方:DontDestroyOnLoad

Unity には、ロード専用の隠しシーンへオブジェクトを退避し、次のシーン読み込み後も破棄しないための API があります。

DontDestroyOnLoad(gameObject);

これで、その GameObject(と子オブジェクト)はシーン切替後も残り、BGM の再生を継続できます。

注意点として、同じマネージャーを各シーンに置き続けると、退避したオブジェクトに加えて新しいオブジェクトも生き残り、二重再生になりがちです。そこでよく組み合わせるのが シングルトンインスタンスは常に 1 つ)です。


完成コード

同じ GameObjectAudioSource とこのスクリプトを付けます。

using UnityEngine;
public class BGMManager : MonoBehaviour
{
    private static BGMManager instance;
    [SerializeField]
    private AudioClip bgmClip;
    private AudioSource audioSource;
    private void Awake()
    {
        if (instance != null)
        {
            Destroy(gameObject);
            return;
        }
        instance = this;
        DontDestroyOnLoad(gameObject);
        audioSource = GetComponent<AudioSource>();
        audioSource.clip = bgmClip;
        audioSource.loop = true;
        audioSource.Play();
    }
}

GameObject の準備(Hierarchy)

  1. 空の GameObject を作成し、名前例:BGMManager
  2. 次のコンポーネントを追加する
    • AudioSource
    • BGMManager(上記スクリプト)

AudioSource の Inspector 設定(目安)

項目 設定
Play On Awake 状況に合わせて調整(下記参照)
Loop ON(コードでも loop = true を入れています)
Audio Resource / Clip 使う BGM ファイル

補足(上級者向けの整理)
このサンプルでは Awake()Play() しています。実行順によっては Play On Awake が ON だと二重に再生が走ることがあるため、Awake で制御するなら Play On Awake は OFF にそろえると安全、という運用もよく使われます(教材によっては ON のままにしていることもあります)。


コード解説

BGMManager を 1 つだけにする

private static BGMManager instance;

static なフィールドはシーンではなく型に紐づく共有領域のイメージです。
現在の正」として、生き残るインスタンスを 1 つだけ保持します。

重複生成を防ぐ

if (instance != null)
{
    Destroy(gameObject);
    return;
}

各シーンに BGMManager を置く運用でも、先に存在していた方を正として、後から出現した方を破棄します。
これで BGM の二重再生を防ぎます。

シーン切替でも消さない(最重要)

DontDestroyOnLoad(gameObject);

ここが今回の要です。通常ならシーンと一緒に消えるオブジェクトを、ロード後も残す側へ移します。

AudioSource を取得して設定し、再生する

audioSource = GetComponent<AudioSource>();
audioSource.clip = bgmClip;
audioSource.loop = true;
audioSource.Play();

同じ GameObjectAudioSource を使い、クリップ・ループ・再生Awake でそろえています。


Unity 6 で少し変わった点(Inspector)

Unity 6 では Inspector の表記が整理・変更されています。

  • 以前は AudioClip と表示されていた場所が、環境によって Audio ResourceClip などのラベルになっていることがあります。

コード側の型は変わらず AudioClip なので、[SerializeField] private AudioClip bgmClip;Unity 6 でもそのまま通用します(見た目の名前が違うだけ、と捉えれば足ります)。


応用:BGM 以外にも効くパターン

今回の学びは「シーンをまたいで残したい状態」全般に効きます。

  • サウンド管理
  • スコアやセッション情報
  • 設定(音量、言語、操作方式)
  • プレイヤーの一時データ

など、**寿命が「1 シーン」ではなく「アプリ実行中」**のものを載せるときの定番が、DontDestroyOnLoad とシングルトンの組み合わせです。


まとめ

シーン切替後も BGM を継続するには、次をセットで理解すると強いです。

  • シーンに置いたオブジェクトは基本、シーンと一緒に消える
  • DontDestroyOnLoad で破棄されない場所へ退避する
  • シングルトンでマネージャーの重複を潰す
  • AudioSource でクリップ・ループ・再生を管理する

この「オブジェクトの寿命」の考え方は、Unity 制作のどこにでも顔を出します。BGM だけのテクニックではなく、ゲーム全体の設計の基礎として覚えておくと後が楽になります。

続き(関連): DontDestroyOnLoad で残したオブジェクトの破棄とシングルトン運用