【Unity】シーンを跨いでも消えない!UnityのDontDestroyOnLoad徹底解説と活用術

作成: 2025-12-10最終更新: 2026-07-13

シーン切り替え時もオブジェクトを保持するDontDestroyOnLoadの使い方と、シングルトンパターンによる安全な管理方法を解説します。

「シーンを切り替えたらBGMが途切れた」「スコアがリセットされた」——シーンをロードすると、古いシーンのオブジェクトはすべて破棄される。これがUnityの標準動作です。でも、BGMプレイヤーやゲームマネージャーのように「こいつだけは生き残ってほしい」オブジェクトが必ず出てきます。

そのための仕組みが DontDestroyOnLoad() です。この記事では基本的な使い方から、初心者が必ずハマる「重複生成」の落とし穴、そして定番の解決策である シングルトンパターン との組み合わせまでを解説します。

DontDestroyOnLoadのイメージ。シーンが切り替わってもBGMプレイヤーだけが生き残る

この記事でわかること

  • シーン切り替えでオブジェクトが消える仕組みとDontDestroyOnLoadの役割
  • 基本の使い方(Awakeで呼ぶだけ)
  • 定番の落とし穴「重複生成」が起きる理由
  • シングルトンパターンによる安全な永続化の実装

Sponsored

DontDestroyOnLoadの基本概念

DontDestroyOnLoadは、Objectクラスの静的メソッドです。このメソッドにGameObjectを渡すと、そのオブジェクトは「DontDestroyOnLoadシーン」と呼ばれる特殊な内部シーンに移動し、以降のシーン切り替えの影響を受けなくなります。

DontDestroyOnLoadシーンは、通常のシーンとは異なり、ゲームが終了するまで破棄されません。これにより、BGMやゲームマネージャーといった、ゲーム全体で永続的に存在する必要があるオブジェクトを簡単に管理できるようになります。

DontDestroyOnLoadの仕組みの図。シーンAからシーンBに切り替わると通常のオブジェクトは破棄されるが、DontDestroyOnLoadシーンに移動したオブジェクトは生き残る

コード例1:基本的な使い方

最もシンプルな使い方は、永続化したいオブジェクトにアタッチされたスクリプトのAwake()メソッド内でDontDestroyOnLoad(this.gameObject)を呼び出すことです。

以下の例は、BGMを再生するオブジェクトにアタッチすることを想定したスクリプトです。

using UnityEngine;

public class BgmPlayer : MonoBehaviour
{
    void Awake()
    {
        // このGameObjectをシーン切り替え時に破棄されないように設定します
        DontDestroyOnLoad(this.gameObject);

        // BGMの再生を開始する処理などをここに追加します
        Debug.Log("BGMプレイヤーが生成され、DontDestroyOnLoadが適用されました。");
    }
}

このスクリプトをアタッチしたGameObjectがシーンに配置されていれば、シーンを何度切り替えても、そのGameObjectは破棄されずに残り続けます。

初心者が躓きやすいポイント:オブジェクトの重複生成

DontDestroyOnLoadを使う際に、初心者が最も陥りやすい間違いは「オブジェクトの重複生成」です。

例えば、上記のBgmPlayerがシーンAに配置されており、シーンBにも同じBgmPlayerが配置されているとします。シーンAからシーンBへ移動すると、以下のようになります。

  1. シーンAのBgmPlayerDontDestroyOnLoadが適用され、永続化されます。
  2. シーンBがロードされると、シーンBに配置されていた新しいBgmPlayerが生成されます。
  3. 結果として、ゲーム内にBgmPlayerが2つ存在し、BGMが二重に再生されてしまう、といった問題が発生します。
重複生成の落とし穴の図。シーンAで永続化したBGMプレイヤーが生き残っ�たまま、シーンBに配置されていた2体目が生成され、BGMが二重再生されてしまう

コード例2:シングルトンパターンを用いた安全な管理

この重複生成の問題を解決し、永続化したいオブジェクトがゲーム内にただ一つだけ存在することを保証するために、DontDestroyOnLoadシングルトンパターンと組み合わせて使用されるのが一般的です。

シングルトンパターンとは、「クラスのインスタンスが一つしか存在しないことを保証する」デザインパターン(設計の定石)です。

以下のGameManagerスクリプトは、DontDestroyOnLoadとシングルトンパターンを組み合わせた、実践的なコード例です。

using UnityEngine;

public class GameManager : MonoBehaviour
{
    // 外部からアクセスするための静的なインスタンス
    public static GameManager Instance { get; private set; }

    void Awake()
    {
        // 既にインスタンスが存在するかチェック
        if (Instance != null && Instance != this)
        {
            // 既に存在するなら、新しく生成された自分自身を破棄して重複を防ぐ
            Destroy(this.gameObject);
            return;
        }

        // インスタンスが存在しない場合、自分自身をInstanceとして設定
        Instance = this;

        // シーンを跨いでも破棄されないように設定
        DontDestroyOnLoad(this.gameObject);

        Debug.Log("GameManagerが初期化され、永続化されました。");
    }

    // 例:どこからでもアクセスできるゲーム状態管理メソッド
    public void AddScore(int amount)
    {
        // スコア加算処理など
        Debug.Log("スコアが" + amount + "点加算されました。");
    }
}

このコードのポイントは、Awake()内で既存のインスタンスの有無を確認し、もし既に存在していれば新しく生成された自分自身を即座に破棄している点です。これにより、シーンを何度ロードしてもGameManagerは一つしか存在しないことが保証されます。

イメージは「門番のチェック」です。すでに1体目が中にいるなら、後から来た2体目は門前払い(Destroy)されます。

シングルトンパターンの門番チェックの図。すでにインスタンスが存在する場合、シーンロードで新しく生成された2体目はAwakeの門番チェックで即座に破棄され、常に1体だけが保たれる

他のスクリプトからは、GameManager.Instance.AddScore(100);のように、いつでも安全にこのマネージャーにアクセスできるようになります。

Sponsored

実践:タイトル→ゲーム→リザルトでBGMを1曲だけ鳴らし続ける

仕組みが分かったら、いちばん出番の多い形で完成させましょう。RPGでもパズルでもノベルゲームでも、「タイトル→ゲーム→リザルト→タイトル」とシーンを何往復しても、 BGMが途切れず・二重にならず・1曲だけ 流れ続ける構成です。

タイトル→ゲーム→リザルトと一巡してもBgmPlayerは1つだけ生き残り、BGMが途切れない完成イメージ

先ほどのBgmPlayerに門番を組み込みます。

using UnityEngine;

[RequireComponent(typeof(AudioSource))]
public class BgmPlayer : MonoBehaviour
{
    public static BgmPlayer Instance { get; private set; }

    void Awake()
    {
        // 門番チェック:すでに1体目がいるなら、2体目は入場お断り
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this;
        DontDestroyOnLoad(gameObject); // rootのGameObjectで呼ぶこと(後述の失敗②)
    }
}

組み立て手順:

  1. タイトルシーンに空のGameObject「BgmPlayer」を、 Hierarchyの一番上の階層(root) に作ります。AudioSource(BGMを設定し、Play On AwakeLoopをオン)と上のスクリプトを付けます
  2. ゲームシーンとリザルトシーンには 置きません。タイトルから流れてきた1体に任せます(うっかり置いても、門番が2体目を破棄してくれます)
  3. タイトル→ゲーム→リザルト→タイトルと3往復して、(a) BGMが一度も途切れないこと、(b) 再生中のHierarchy最下部に現れる「DontDestroyOnLoad」シーンにBgmPlayer1つだけ いることを確認します

「永続させるもの」と「リセットするもの」を分ける

永続オブジェクトに慣れてきた頃にやりがちなのが、 1プレイ分の状態まで永続Managerに載せっぱなしにする ことです。スコアや残機がタイトルに戻っても残り続け、「New Gameなのに前回のスコアから始まる」バグになります。線引きはこうです。

  • 永続してよいもの: BGM、音量などの設定、「どこまで解放したか」のセーブ情報
  • New Gameでリセットするもの: スコア・残機・コンボなどの一時状態。ゲーム開始時に必ず初期化します
// 永続するGameManagerに「1プレイ分の状態」を持たせるなら、開始時のリセットを忘れずに
public void StartNewGame()
{
    score = 0;
    lives = 3;
    SceneManager.LoadScene("Game");
}

わざと壊して、直す

このテーマの定番事故は3つです。安全な環境で、実際に起こしてみてください。

  1. 各シーンに置いて二重再生: 門番のif文をコメントアウトして、ゲームシーンにもBgmPlayerを置いて往復すると、BGMが2本重なって音が濁ります(往復のたびに増えます)。門番を戻せば、2体目は生まれた瞬間に破棄されて1本に戻ります
  2. 子オブジェクトに付けて永続しない: BgmPlayerを何かの にして再生すると、Consoleに警告が出て永続しません。DontDestroyOnLoadrootのGameObject専用 です。どうしても子にある物を残したいなら、transform.SetParent(null)でrootへ出してから呼びます
  3. staticイベントの解除忘れで処理が増殖: シーン内のオブジェクトがSceneManager.sceneLoaded += OnSceneLoadedのような staticイベント を購読してOnDestroy-=し忘れると、シーンを再訪するたびに登録が積み上がり、同じ処理が2回・3回と走ります(しかも破棄済みオブジェクト相手でエラーに)。 staticや永続オブジェクトのイベントを購読したら、破棄時に必ず解除 が鉄則です

仕上げはPlayで3往復です。タイトル→ゲーム→リザルトを回ってもBGMは一度も途切れず、Hierarchyの「DontDestroyOnLoad」にはBgmPlayerが1体だけ。もしNew Gameで前回のスコアが顔を出したら、犯人は永続オブジェクトへの載せすぎ——StartNewGameのリセットを見直してください。

おまけ:先に知っておくと良いこと

永続オブジェクトを扱えるようになったら、次はこのあたりの知識が役立ちます。

  • シングルトンパターンをもっと深く: 便利な反面、使いすぎると依存関係が絡まる諸刃の剣でもあります。Singletonパターンの記事 で正しい実装と注意点を学べます。
  • そもそものシーン遷移の仕組み: LoadScene/LoadSceneAsyncの使い方は SceneManagerの記事 で解説しています。
  • 「データだけ」ならオブジェクトを永続化しない手も: スコアや設定のようなデータは、GameObjectごと生き残らせる代わりに ScriptableObjectセーブデータ で持つ設計もあります。ScriptableObjectの記事セーブ&ロードの記事 が参考になります。

まとめ

DontDestroyOnLoadは、Unityで永続的なオブジェクトを管理するための強力なツールです。この記事で学んだ重要なポイントをまとめます。

  • DontDestroyOnLoadの役割: シーンが切り替わっても、特定のGameObjectを破棄されずに保持するために使用します。BGMやゲームマネージャーなどの永続的なデータ管理に適しています。
  • 基本的な使い方: 永続化したいオブジェクトにアタッチされたスクリプトのAwake()内でDontDestroyOnLoad(this.gameObject)を呼び出します。
  • 最大の注意点: DontDestroyOnLoadを単独で使用すると、シーンを切り替えるたびにオブジェクトが重複して生成され、バグの原因となる可能性があります。
  • 実践的な解決策: オブジェクトの重複を防ぎ、ゲーム全体でインスタンスが一つであることを保証するために、DontDestroyOnLoadシングルトンパターンを組み合わせて使用するのが最も推奨される方法です。
  • アクセス方法: シングルトン化することで、クラス名.Instanceを通じて、ゲーム内のどこからでも安全かつ簡単に永続オブジェクトにアクセスできるようになります。

これらの知識を活用することで、あなたのUnityプロジェクトにおけるシーン管理とオブジェクトの永続化は、より洗練されたものになるでしょう。快適なゲーム開発をお楽しみください。