Unityプロジェクトでのシーン管理は、シーンの遷移や再読み込みなど多くの場所で必要になります。今回は、SceneFieldというカスタムクラスを使って、シーン選択を簡単に行えるようにする方法を解説します。また、シーン遷移を管理するための便利なユーティリティスクリプトや、シーン遷移を扱うためのカスタムスクリプトも紹介します。
GitHub
シーン選択のカスタムクラス: SceneField
SceneFieldは、シーン名をインスペクターで選択できるようにするカスタムクラスです。シーン名を文字列として扱いながらも、プルダウン形式でインスペクターから簡単に選択できるのがポイントです。
using UnityEngine;
[System.Serializable]
public class SceneField
{
[SerializeField] private string sceneName;
public string SceneName => sceneName;
public static implicit operator string(SceneField sceneField)
{
return sceneField.SceneName;
}
}
このクラスでは、sceneNameというプライベートな変数にシーン名を格納します。SceneNameプロパティでその値を取得できるようにしています。また、implicit operator stringを定義することで、このクラスを文字列のように扱うことも可能です。これにより、シーン名を簡単に取得できるようになります。
インスペクターでのシーン選択: SceneFieldPropertyDrawer
SceneField クラスを使ってインスペクターにてプルダウン形式でシーンを選択するためには、Unityエディタ向けのカスタムプロパティドロワーを定義する必要があります。これが SceneFieldPropertyDrawer です。
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(SceneField))]
public class SceneFieldPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// シーン名プロパティの取得
SerializedProperty sceneNameProperty = property.FindPropertyRelative("sceneName");
// ビルド設定に含まれるシーン名の配列を取得
string[] scenes = GetSceneNames();
// 現在のシーン名を取得
string currentSceneName = sceneNameProperty.stringValue;
// 現在のシーン名のインデックスを取得
int currentIndex = -1;
for (int i = 0; i < scenes.Length; i++)
{
if (scenes[i] == currentSceneName)
{
currentIndex = i;
break;
}
}
// プルダウンメニューを表示
int selectedIndex = EditorGUI.Popup(position, label.text, currentIndex, scenes);
// 選択されたシーン名を更新
if (selectedIndex >= 0 && selectedIndex < scenes.Length)
{
sceneNameProperty.stringValue = scenes[selectedIndex];
}
}
private string[] GetSceneNames()
{
var sceneList = new System.Collections.Generic.List<string>();
foreach (var scene in EditorBuildSettings.scenes)
{
if (!scene.enabled) continue;
string scenePath = scene.path;
string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath);
sceneList.Add(sceneName);
}
return sceneList.ToArray();
}
}
#endif
・シーン名プロパティの取得
FindPropertyRelative("sceneName") を使って、SceneFieldクラス内のsceneNameプロパティにアクセスしています。
・ビルド設定に含まれるシーン名の取得
GetSceneNames()メソッドで、プロジェクトのビルド設定に含まれているすべてのシーン名を取得しています。これは、シーンパスから名前を抽出してリスト化し、配列として返しています。
・プルダウンメニューの表示
EditorGUI.Popup() を使って、インスペクターにプルダウン形式のシーン選択メニューを表示しています。現在のシーン名に応じて、選択中のインデックスを更新し、選択されたシーン名をプロパティに反映します。
シーン遷移の管理: SceneTransitionUtility
次に、シーンの読み込みやリロードなどの操作を行うための SceneTransitionUtility クラスを紹介します。このユーティリティクラスを使うことで、シーン遷移を簡単に実装できます。
using UnityEngine.SceneManagement;
public static class SceneTransitionUtility
{
// 指定したシーンを同期的に読み込む
public static void LoadScene(string sceneName)
{
if (SceneExists(sceneName))
{
SceneManager.LoadScene(sceneName);
}
else
{
UnityEngine.Debug.LogError($"シーン '{sceneName}' は存在しません");
}
}
// 現在のシーンをリロードする
public static void ReloadScene()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
// シーンが存在するか確認する
private static bool SceneExists(string sceneName)
{
for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++)
{
string path = SceneUtility.GetScenePathByBuildIndex(i);
string name = System.IO.Path.GetFileNameWithoutExtension(path);
if (name == sceneName)
{
return true;
}
}
return false;
}
}
・シーンのロード
LoadScene() メソッドを使って、指定されたシーン名が存在するか確認し、存在する場合はシーンをロードします。
・シーンのリロード
ReloadScene() メソッドでは、現在のシーン名を取得してリロードします。シーンのデバッグやテスト時に使えます。
・シーンの存在確認
SceneExists() メソッドで、ビルド設定に含まれるシーン名と一致するかどうかを確認します。
実際にシーン遷移を実行する: CustomSceneManager
最後に、SceneField クラスと SceneTransitionUtility を統合して実際にシーンを遷移させる CustomSceneManager スクリプトを紹介します。
using UnityEngine;
public class CustomSceneManager : MonoBehaviour
{
[SerializeField] private SceneField sceneToLoad;
// シーンを同期的に読み込むメソッド
public void LoadScene()
{
SceneTransitionUtility.LoadScene(sceneToLoad.SceneName);
}
// 現在のシーンをリロードする
public void ReloadScene()
{
SceneTransitionUtility.ReloadScene();
}
}
・sceneToLoad には SceneField を使用して、インスペクターで簡単にシーンを選択できるようにしています。
・LoadScene() メソッドでは、選択されたシーン名を使ってシーンを読み込みます。
・ReloadScene() メソッドで、現在のシーンを再読み込みします。
使い方
-
オブジェクトにアタッチ
Hierarchyビューで空のゲームオブジェクトを作成し、名前を「SceneManager」などに変更します。このオブジェクトに、先ほど作成した CustomSceneManager スクリプトをアタッチします。 -
シーンの指定
インスペクターに SceneToLoad というフィールドが表示されるので、ここにビルド設定に含まれているシーンを指定します。SceneField が有効になっているため、プルダウンメニューからシーンを簡単に選択できます。
プロジェクトに応じてカスタマイズしてください。