Unityにおける複数シーン管理の技術資料
目次
はじめに
Unityでは、プロジェクトの規模や複雑さに応じて、複数のシーンを効果的に管理することが重要です。本資料では、シーン管理をシンプルかつ効率的に行うための方法として、シングルトンパターンを適用したSceneLoaderクラスの実装方法とその使用方法について詳述します。チーム開発や大規模プロジェクトにおいても、一貫したシーン管理を実現するためのガイドとしてご活用ください。
複数シーン管理の概要
Unityでは、複数のシーンを同時にロードし、シーン間でオブジェクトやデータを共有することが可能です。これにより、以下のような利点があります。
- モジュール化: 各シーンを独立したモジュールとして扱うことで、開発の効率が向上します。
 - チーム開発: 複数の開発者が異なるシーンを同時に作業でき、統合作業が容易になります。
 - 動的ロード: ゲームの進行に応じて必要なシーンを動的にロード・アンロードすることで、メモリ管理やパフォーマンスの最適化が可能です。
 
しかし、複数シーンを管理する際には、ロードやアンロードのタイミング、シーン間の依存関係などを適切に制御する必要があります。これらを効率的に行うために、SceneLoaderクラスの導入が有効です。
シングルトンパターンの採用
シングルトン(Singleton)パターンは、クラスのインスタンスが一つだけであることを保証し、グローバルなアクセス手段を提供するデザインパターンです。SceneLoaderクラスにシングルトンパターンを適用することで、以下の利点が得られます。
シングルトンを使用する利点
グローバルアクセス:
- プロジェクト内のどこからでも
SceneLoaderに簡単にアクセスできます。例えば、SceneLoader.Instance.Load("SceneName")のように呼び出すことが可能です。 
インスタンスの一意性:
- クラスのインスタンスが一つだけであることを保証します。これにより、シーンのロードやアンロードに関する管理が一貫して行われ、競合や不整合を防ぐことができます。
 
ライフサイクルの管理:
DontDestroyOnLoadを使用することで、シーンが切り替わってもSceneLoaderが破棄されずに残ります。
シングルトンを使用する際の注意点
テストの難しさ:
- シングルトンはグローバルな状態を持つため、ユニットテストが難しくなることがあります。テスト環境でのモックやスタブの作成が複雑になる場合があります。
 
依存関係の隠蔽:
- シングルトンを多用すると、クラス間の依存関係が明確でなくなり、コードの可読性やメンテナンス性が低下する可能性があります。
 
柔軟性の低下:
- 将来的に複数の
SceneLoaderインスタンスが必要になる場合、対応が難しくなります。 
実装手順
以下のステップに従って、シングルトンパターンを適用したSceneLoaderクラスを実装し、複数のシーンを効率的に管理できるようにします。
1. SceneLoaderスクリプトの作成
まず、シングルトンパターンを適用したSceneLoaderスクリプトを作成します。
スクリプト内容
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneLoader : MonoBehaviour
{
    private static SceneLoader _instance;
    public static SceneLoader Instance
    {
        get
        {
            if (_instance == null)
            {
                // シーン内に存在しない場合は新しく作成
                GameObject obj = new GameObject("SceneLoader");
                _instance = obj.AddComponent<SceneLoader>();
                DontDestroyOnLoad(obj);
            }
            return _instance;
        }
    }
    private bool isLoaded = false;
    public void UnLoad(string sc)
    {
        if (!isLoaded) return;
        SceneManager.UnloadSceneAsync(sc).completed += OnUnLoadComplete;
    }
    void OnUnLoadComplete(AsyncOperation obj)
    {
        isLoaded = false;
        Debug.Log("アンロードが完了しました");
    }
    public void Load(string sc)
    {
        if (isLoaded) return;
        SceneManager.LoadSceneAsync(sc, LoadSceneMode.Additive).completed += OnLoadComplete;
    }
    void OnLoadComplete(AsyncOperation obj)
    {
        isLoaded = true;
        Debug.Log("ロードが完了しました");
    }
    private void Awake()
    {
        if (_instance == null)
        {
            _instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else if (_instance != this)
        {
            Destroy(gameObject);
        }
    }
}
2. SceneLoaderをシーンに追加
SceneLoaderをシングルトンとして機能させるために、シーンに一度だけ存在するように設定します。
手順
- プロジェクトビューで、
Scriptsフォルダー(存在しない場合は新規作成)を右クリックし、Create > C# Scriptを選択します。 - スクリプト名を
SceneLoaderとし、上記のコードを貼り付けて保存します。 - Hierarchyビューで、
SceneLoaderを配置するための空のGameObjectを作成します。- 右クリックして
Create Emptyを選択し、名前をSceneLoaderに変更します。 
 - 右クリックして
 - 作成した
SceneLoaderオブジェクトに、先ほど作成したSceneLoaderスクリプトをアタッチします。SceneLoaderオブジェクトを選択し、InspectorビューでAdd Componentをクリックします。SceneLoaderと検索して、スクリプトを追加します。
 - シングルトンの確認:
SceneLoaderオブジェクトが他のシーンでも持続するようにするため、DontDestroyOnLoadが既にスクリプト内で設定されています。これにより、シーンが切り替わってもSceneLoaderは破棄されません。
 
3. SceneSelecterスクリプトの修正
SceneSelecterスクリプトをシングルトンに対応するように修正します。具体的には、SceneLoaderのインスタンス取得部分をSceneLoader.Instanceに変更します。
修正後のSceneSelecterスクリプト
using UnityEngine;
public class SceneSelecter : MonoBehaviour
{
    [SerializeField]
    string gameScene;
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.L))
        {
            SceneLoader.Instance.Load(gameScene);
        }
        else if (Input.GetKeyDown(KeyCode.U))
        {
            SceneLoader.Instance.UnLoad(gameScene);
        }
    }
}
手順
- プロジェクトビューで、
Scriptsフォルダー内に新しいC#スクリプトを作成し、名前をSceneSelecterとします。 - 上記の修正後のコードを貼り付けて保存します。
 - Hierarchyビューで、
SceneSelecterスクリプトを使用するGameObjectを選択し、Inspectorビューでスクリプトをアタッチします。 gameSceneフィールドに、ロードしたいシーン名を入力します。
4. シーンの準備
シーンのロードとアンロードを行うために、対象となるシーンがプロジェクトに含まれていることを確認し、Build Settingsに追加します。
手順
- File > Build Settingsを開きます。
 Scenes In Buildリストに、ロードしたいシーンが含まれていることを確認します。含まれていない場合は、Add Open Scenesボタンをクリックして追加します。
5. 動作確認
設定が完了したら、実際にシーンのロードとアンロードが正しく動作するか確認します。
手順
- Playモードでプロジェクトを実行します。
 - 指定したキー(例:
Lキー)を押すと、指定したシーンが追加でロードされることを確認します。 - 同様に、
Uキーを押すと、ロードされたシーンがアンロードされることを確認します。 - Consoleウィンドウで、"ロードが完了しました"や"アンロードが完了しました"といったログが表示されることを確認します。
 
6. 複数シーンの管理
シングルトンパターンを使用することで、複数のスクリプトやシーンからSceneLoaderにアクセスしやすくなります。以下は、他のスクリプトからSceneLoaderを使用する例です。
例: 他のスクリプトからシーンをロード・アンロードする
using UnityEngine;
public class AnotherScript : MonoBehaviour
{
    void Start()
    {
        // "AnotherScene"をロード
        SceneLoader.Instance.Load("AnotherScene");
    }
    void SomeFunction()
    {
        // "AnotherScene"をアンロード
        SceneLoader.Instance.UnLoad("AnotherScene");
    }
}
このように、SceneLoader.Instanceを通じて、どこからでもシーンのロードやアンロードを簡単に行うことができます。
注意点とベストプラクティス
注意点
- シーン名の誤り: シーン名は正確に入力する必要があります。スペルミスがあるとシーンがロードされません。
 - シーンの依存関係: ロードするシーンが他のシーンに依存している場合、依存関係を考慮してロード順序を管理する必要があります。
 - パフォーマンス: 大規模なシーンを追加でロードすると、パフォーマンスに影響を与える可能性があります。必要に応じて非同期ロードやストリーミングを活用してください。
 
ベストプラクティス
- シーン管理の一元化: 
SceneLoaderを使用して、全てのシーンロードとアンロードを一元管理することで、コードの可読性とメンテナンス性を向上させます。 - エラーハンドリングの強化: 実際のプロジェクトでは、シーンのロードやアンロードに失敗した場合の処理を追加することをおすすめします。
 - UIとの連携: シーンのロード中にUIで進捗バーを表示するなど、ユーザーエクスペリエンスを向上させる工夫を取り入れましょう。
 - 依存性注入の検討: 大規模プロジェクトやテスト可能性を重視する場合、シングルトン以外のデザインパターン(例えば依存性注入)を検討することも有益です。
 - ログの管理: ロードやアンロードの成功・失敗を適切にログに記録し、デバッグやモニタリングを容易にします。
 
まとめ
本資料では、Unityにおける複数シーン管理の効率化を目的として、シングルトンパターンを適用したSceneLoaderクラスの実装方法と使用方法について詳述しました。以下のポイントを押さえて実装を進めることで、チーム開発や大規模プロジェクトにおいても、シーン管理がスムーズに行えるようになります。
- SceneLoaderスクリプトの作成: シングルトンパターンを適用し、シーンのロードとアンロードを管理するクラスを実装します。
 - シーンへの追加: 
SceneLoaderをシーンに一度だけ配置し、DontDestroyOnLoadを設定して持続性を確保します。 - 他スクリプトからのアクセス: 
SceneLoader.Instanceを通じて、他のスクリプトからシーンのロード・アンロードを行います。 - シーンの準備と設定: ロード対象のシーンを
Build Settingsに追加し、正確なシーン名を使用します。 - 動作確認: 実際にプレイモードでシーンのロードとアンロードが正しく動作することを確認します。
 - ベストプラクティスの遵守: シーン管理を一元化し、エラーハンドリングやUI連携などを適切に実装します。
 
これにより、複数のシーンを効率的かつ一貫して管理できるようになり、プロジェクトの品質と開発効率を向上させることができます。必要に応じて機能を拡張し、プロジェクトに最適なシーン管理システムを構築してください。






ディスカッション
コメント一覧
まだ、コメントがありません