SceneManagerとは?
SceneManagerは、Unityでシーンの読み込みやアンロードを行うためのクラスです。
タイトル画面からゲーム本編へ移動したり、ステージごとにシーンを分けて切り替えたりと、ゲーム制作では必ず登場する仕組みですね。
UnityEngine.SceneManagement名前空間に含まれており、using UnityEngine.SceneManagement;を書けば利用できます。
そして、シーンを切り替えた時に消えてほしくないオブジェクト(BGMを鳴らすAudioSourceや、各種マネージャークラスなど)を持ち越すにはDontDestroyOnLoadを使います。
DontDestroyOnLoadは専用の記事で詳しく解説しているので、本記事ではSceneManagerを中心に扱います。
使用するバージョン
- Unity 6 以降(Unity 2022.3 LTS でも動作確認済み)
SceneManager自体は古くから存在する機能なので、Unity 2022.3 LTS でも本記事のサンプルコードはそのまま動作します。
シーンの準備
Build Settingsへの登録
SceneManagerでロードできるシーンは、Build Profilesに登録されているシーンだけです。
File→Build ProfilesからBuild Profilesウィンドウを開き、Scenes In Buildに対象のシーンをドラッグ&ドロップで追加します。

登録すると、左側に名前、右側にインデックス番号が表示されます。
この名前またはインデックス番号を使ってシーンをロードします。
インデックス0のシーンが、ゲーム起動時に最初に読み込まれるシーンになります。
基本的な使い方
SceneManager.LoadScene
基本的なシーン遷移はSceneManager.LoadScene()で行います。
名前指定とインデックス指定のどちらでも呼べます。
using UnityEngine;
using UnityEngine.SceneManagement;
public class TitleController : MonoBehaviour
{
// 名前で指定してロードする
public void LoadGameByName()
{
SceneManager.LoadScene("Game");
}
// インデックスで指定してロードする
public void LoadGameByIndex()
{
// Build Settingsに登録した順番のインデックス
SceneManager.LoadScene(1);
}
}
呼び出した時点で現在のシーンは破棄され、新しいシーンの読み込みが始まります。
基本は名前指定がおすすめです。インデックス番号はBuild Settingsの並び替えで変わってしまうため、ミスのもとになります。
LoadSceneMode.Single と LoadSceneMode.Additive
LoadScene()の第二引数にはLoadSceneModeを指定できます。
省略時はLoadSceneMode.Singleが使われ、これは「現在のシーンを破棄してから新しいシーンを読み込む」モードです。
LoadSceneMode.Additiveを指定すると、現在のシーンを残したまま追加でシーンを読み込めます。
using UnityEngine;
using UnityEngine.SceneManagement;
public class StageLoader : MonoBehaviour
{
public void LoadStage()
{
// 既存のシーンに重ねてUIシーンを読み込む
SceneManager.LoadScene("UI", LoadSceneMode.Additive);
}
public void UnloadStage()
{
// 追加で読み込んだシーンをアンロードする
SceneManager.UnloadSceneAsync("UI");
}
}
Additiveは、
- 共通UIだけを別シーンに切り出して常時表示する
- 大きなマップを複数シーンに分割して必要な部分だけロードする
といったケースで便利です。

不要になったシーンはSceneManager.UnloadSceneAsync()で個別にアンロードできます。
なお、Additiveで読み込んだシーンは使い終わったら必ずUnloadSceneAsync()でアンロードしないとメモリが解放されません。
重ねた分だけ常駐コストが増えるので、アンロードのタイミングはセットで設計しておきましょう。
非同期ロード(LoadSceneAsync)
LoadScene()は同期的に処理されるため、シーンが大きいと一瞬画面が固まったように見えることがあります。
これを避けたい場合や、ロード画面を表示したい場合はLoadSceneAsync()を使います。
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class AsyncSceneLoader : MonoBehaviour
{
public void LoadGame()
{
StartCoroutine(LoadSceneRoutine("Game"));
}
private IEnumerator LoadSceneRoutine(string sceneName)
{
// 非同期ロードを開始
AsyncOperation operation = SceneManager.LoadSceneAsync(sceneName);
// 完了するまで待機
while (!operation.isDone)
{
// ロード進捗を取得(0.0〜0.9)
float progress = Mathf.Clamp01(operation.progress / 0.9f);
Debug.Log($"Loading: {progress * 100:F0}%");
yield return null;
}
}
}
ロード進捗の取得
AsyncOperation.progressは0.0〜1.0の値を返しますが、実際にはシーンの読み込みが完了した時点で0.9までしか上がりません。
残りの0.1は「ロード済みのシーンをアクティブ化する処理」に使われます。
進捗バーに表示する場合は0.9で正規化するのが定番です。
// 進捗バー用に0〜1の範囲へ正規化
float displayProgress = Mathf.Clamp01(operation.progress / 0.9f);
progressBar.value = displayProgress;
allowSceneActivation で遷移タイミングを制御する
「ロードは完了しているけれど、まだ画面を切り替えたくない」というケースもあります。
例えば、
- ロード完了後に「タップでスタート」を表示してから遷移したい
- アニメーションが終わってから遷移したい
といった場面ですね。
AsyncOperation.allowSceneActivationをfalseにすると、ロードは進めつつ実際のシーン切り替えだけを保留できます。
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class TapToStartLoader : MonoBehaviour
{
[SerializeField] private GameObject _tapToStartText;
public void LoadGame()
{
StartCoroutine(LoadSceneRoutine("Game"));
}
private IEnumerator LoadSceneRoutine(string sceneName)
{
AsyncOperation operation = SceneManager.LoadSceneAsync(sceneName);
// 遷移タイミングを手動で制御する
operation.allowSceneActivation = false;
// progressが0.9になるまではロード中
while (operation.progress < 0.9f)
{
yield return null;
}
// ロード完了。「タップでスタート」を表示
_tapToStartText.SetActive(true);
// タップされるまで待機
while (!Input.GetMouseButtonDown(0))
{
yield return null;
}
// ここで初めてシーンを切り替える
operation.allowSceneActivation = true;
}
}
allowSceneActivation = falseの間はisDoneもtrueにならない点に注意してください。
進捗判定はprogress >= 0.9fで行うのが定番です。
アクティブシーンの切り替え(SetActiveScene)
Additiveで複数のシーンを開いている時、新しく生成したGameObjectはどのシーンに所属するのでしょうか?
答えは、現在のアクティブシーンです。
アクティブシーンはSceneManager.SetActiveScene()で切り替えられます。
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class StageController : MonoBehaviour
{
private IEnumerator Start()
{
// ステージシーンを追加ロード
yield return SceneManager.LoadSceneAsync("Stage1", LoadSceneMode.Additive);
// ロードしたシーンを取得してアクティブに切り替える
Scene stageScene = SceneManager.GetSceneByName("Stage1");
SceneManager.SetActiveScene(stageScene);
}
}
アクティブシーンを切り替えると、
Instantiate()で生成したオブジェクトの所属シーン- ライティング設定(環境光やスカイボックス)
がそのシーンのものに切り替わります。
Additiveを使う時はセットで覚えておきましょう。
まとめ
今回はSceneManagerによるシーンの読み込みと切り替えについて解説しました。
ポイントを振り返ると、
SceneManager.LoadScene()でシーンを切り替えられるLoadSceneMode.Additiveで複数のシーンを重ねて読み込めるLoadSceneAsync()を使えば非同期ロードや進捗表示、allowSceneActivationでの遷移タイミング制御も可能SetActiveScene()で生成先のシーンやライティングを切り替えられる- シーンを跨いでデータを残すには
DontDestroyOnLoad・ScriptableObject・staticを使い分ける
といったところです。
シーン構成の設計は、プロジェクトが大きくなるほど効いてきます。早めに押さえておくと、後の拡張がぐっと楽になりますよ。




