パハットノート

※当サイトではGoogleアドセンス広告を利用しています

Unity SceneAssetからシーンの切り替え





導入

SceneManager.LoadScene("シーン名");

でシーンを切り替えるとシーンファイルの名称を変えた際にこの部分をすべて変更する手間が発生します。

そのため、本記事ではSceneAssetからシーン名を取得してシーンを切り替える方法を紹介します。




SceneAssetのメリット・デメリット

SceneAssetを利用するメリットは、シーンファイルそのものを参照しているためシーン名を変更してもシリアライズ化した変数においてその参照が消えないことです

しかし、

using UnityEditor;

をしないと使えないので、エディタ上以外で利用しようとすると少し手間がかかるというデメリットもあります。




エディタ上以外(ビルト先)での利用方法

エディタ上以外(ビルト先)で利用するために、SceneAssetが変更されたときにシーン名を取得するという処理をエディタ拡張で行いました。
具体的には「PropetyDrawer」クラスを利用して実現しました。

using UnityEngine;
using System;

#if UNITY_EDITOR
using UnityEditor;


[CustomPropertyDrawer(typeof(MySceneAsset))]
public class MySceneAssetDrawer : PropertyDrawer
{
    SerializedProperty nameProperty;
    SerializedProperty sceneAssetProperty;

    private void Init(SerializedProperty property)
    {
        nameProperty = property.FindPropertyRelative("_name");
        sceneAssetProperty = property.FindPropertyRelative("sceneAsset");
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        //初期化
        Init(property);

        //描画範囲を決定
        var fieldRect = position;
        fieldRect.height = EditorGUIUtility.singleLineHeight;

        // Prefab化した後プロパティに変更を加えた際に太字にしたりする機能を加えるためPropertyScopeを使う
        using (new EditorGUI.PropertyScope(fieldRect, label, property))
        {
            // ラベルを表示し、ラベルの右側のプロパティを描画すべき領域のpositionを得る
            fieldRect = EditorGUI.PrefixLabel(fieldRect, GUIUtility.GetControlID(FocusType.Passive), label);

            //シーンアセットの入力フィールドを表示
            var sceneRect = fieldRect;
            EditorGUI.PropertyField(sceneRect, sceneAssetProperty, GUIContent.none);

            //シーン名を取得
            nameProperty.stringValue = (sceneAssetProperty.objectReferenceValue as SceneAsset)?.name;
        }
    }

    //高さを取得
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        => EditorGUIUtility.singleLineHeight;
}
#endif

[Serializable]
public class MySceneAsset
{
#if UNITY_EDITOR
    [SerializeField] SceneAsset sceneAsset;
#endif

    [SerializeField] string _name;

    public string Name => _name;

    //文字列に黙示的に変換
    public static implicit operator string(MySceneAsset mySceneAsset)
    {
        return mySceneAsset._name;
    }
}





使用方法

[SerializeField] MySceneAsset testScene;

などのようにして、インスペクターに表示できるようにします。

すると、エディタ上でシーンを変数名として追加できます(下の例では「Test」というシーン名を追加しています。)。



SceneManager.LoadScene(testScene);

とすることで指定したシーンをロードすることができます。