UhiyamaLAB個人開発者の創作備忘録

【Unity】シーン遷移先を文字列ではなくリストから選択できるようにする方法!

2024/04/022024/12/08ゲーム開発Unity

Unityでのシーン遷移は、SceneManager.LoadScene("シーン名")を用いることで簡易に実現可能です。しかし、「シーン名を文字列で指定する」方法は、シーン名変更時の修正やタイプミスによるエラーを引き起こし、保守性を損ないます。
本記事では、UnityEditor.SceneAssetとOnValidateを組み合わせてシーン指定を簡略化・安全化する方法を紹介します。これにより、エディタ上で直感的にシーンを選択でき、ビルド後も文字列として有効なシーン名を保持できるため、日々の開発をよりスムーズに進められます。


  1. シーン遷移の問題点
  2. 基本的な実装方法
  3. 改良版の実装方法
  4. 技術的な解説
  5. その他のアプローチ
  6. まとめ

1. シーン遷移の問題点

1.1 string指定の課題

シーン名を文字列で指定する場合、地味に悩まされる問題が多く潜んでいます:

  • Scene名を変更すると、関連コード内の文字列も全て更新が必要
  • タイプミス(typo)でシーンを正しくロードできず、原因特定に手間がかかる
  • シーン増加に伴い管理が煩雑化し、保守性が低下

こういった問題は、開発が進むにつれ雪だるま式に増え、プロジェクトの保守コストを押し上げます。

1.2 解決策の概要

そこで、UnityEditor.SceneAssetOnValidateを組み合わせた方法が役立ちます:

  • エディタ上で直感的にシーンを選択(SceneAsset)し、文字入力ミスを防止
  • OnValidateによって選択されたシーンを文字列として保持することで、ビルド後も問題なくロード可能
  • シーン指定の手間やリスクを軽減し、保守性・開発効率を大幅改善

2. 基本的な実装方法

2.1 通常のシーン遷移コード

まずはオーソドックスな例です。以下は、プレイヤーが特定のトリガーに入ったときに文字列で指定したシーンへ移行するスクリプトです。

using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneSettingTest : MonoBehaviour
{
    [SerializeField] private string sceneToLoad;

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            SceneManager.LoadScene(sceneToLoad);
        }
    }
}

基本的なシーン遷移コードのインスペクタ表示

2.2 BuildSettingsの設定

忘れがちですが、指定したシーンがBuildSettingsに追加されていないとロードできません。

  1. File > Build Settingsを開く
  2. 対象のシーンをウィンドウへドラッグ&ドロップして追加

BuildSettingsの設定画面


3. 改良版の実装方法

3.1 SceneAssetを使用したコード

UnityEditor.SceneAssetを用いれば、インスペクタ上でシーンを直接選択でき、文字列手入力によるミスを防げます。しかしこのままでは、実行環境(ビルド後)でシーン名を取得できません。ここでOnValidateがカギとなります。

改良版コードのインスペクタ表示

using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneSettingTest : MonoBehaviour
{
    [HideInInspector]
    [SerializeField] private string sceneToLoad; // 実行時に使うシーン名(非表示)

#if UNITY_EDITOR
    [Header("遷移先シーン選択")]
    [SerializeField] private UnityEditor.SceneAsset sceneToLoadAsset; // エディタ用
#endif

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            SceneManager.LoadScene(sceneToLoad);
        }
    }

#if UNITY_EDITOR
    private void OnValidate()
    {
        // エディタ上でsceneToLoadAssetが変更されるたびに呼ばれ、
        // シーン名を文字列としてsceneToLoadへ保存します
        if (sceneToLoadAsset != null)
        {
            sceneToLoad = sceneToLoadAsset.name;
        }
    }
#endif
}

3.2 なぜOnValidateが必要か

「SceneAssetで直接シーンを指定できるなら、そのままでいいじゃないか」と思うかもしれません。しかし、実はそれだけでは不十分です。

UnityEditor.SceneAssetはエディタ専用機能であり、ビルド後の実行環境では参照できません。そのため、もしOnValidateで事前にシーン名を文字列へと変換しておかないと、ビルド後には「シーン名が見つからない!」というエラーが発生してしまいます。

つまり、OnValidateは「エディタ専用のSceneAsset参照」を「ビルド後も有効な文字列」へ変換する橋渡し的役割を担っています。エディタでSceneAssetを選んだ段階でOnValidateが発動し、そのときにシーン名文字列をsceneToLoadに書き込むことで、ビルド後もシーンロードが可能な状態をキープしているのです。

この一手間のおかげで、SceneAssetを使った直感的なシーン指定と、ビルド後のスムーズなシーン遷移が両立できるようになります。


4. 技術的な解説

4.1 UnityEditor.SceneAssetについて

UnityEditor.SceneAssetは、その名のとおりエディタ専用のアセット参照クラスです。エディタ上でシーンを視覚的に選ぶには便利ですが、ビルド済みゲームからは利用不可です。
参考:UnityEditor.SceneAsset (Unityドキュメント)

4.2 OnValidateの役割

OnValidateは、インスペクタで値が変更されるたびに実行される特殊なメソッドです。エディタ作業中に行われる微妙な変更も即座に反映でき、今回のような「エディタ専用参照からビルド後有効なデータへの変換」をシームレスに行うのに向いています。
参考:MonoBehaviour.OnValidate()

4.3 実際の処理の流れ

  1. エディタ上でsceneToLoadAssetにシーンを選択
  2. OnValidateが呼ばれ、sceneToLoadAsset.namesceneToLoadへコピー
  3. ビルド後はsceneToLoad(文字列)が有効なので、SceneManager.LoadScene(sceneToLoad)で正常にシーン遷移可能

この流れで、ビルド前後での参照問題をクリアし、エディタ上での快適なシーン指定とビルド後の確実なシーンロードを両立します。


5. その他のアプローチ

今回紹介した手法以外にも、定数化/enum化したシーン名の参照や、ScriptableObjectでリスト管理、Addressable Assetsによるシーンのロードなど、さまざまな方法があります。
しかし、SceneAsset + OnValidateを使った方法は、エディタ上で直接シーンを選べる手軽さとビルド時の安全性が程よくバランスしており、特に小~中規模のプロジェクトで効果的です。


6. まとめ

シーン名を文字列で指定する問題に対して、UnityEditor.SceneAssetOnValidateを組み合わせることで、エディタでの視覚的なシーン選択とビルド後の確実なロードを両立可能にしました。
これにより、タイプミスやシーン名変更時の煩雑な修正が大幅に減り、保守性と開発効率が向上します。
シーン数が増えて管理が難しくなってきたら、ぜひこのアプローチを検討してみてください。

この記事をシェアする