将我所有的场景名称存储在哪里

时间:2019-03-27 05:56:49

标签: unity3d structure

我正在Unity中创建一个probject,并且想通过一个游戏来访问我所有的SceneNaming;

现在在用户界面中,我必须手动设置场景名称。

enter image description here

我想将所有场景名称存储在一个对象中,这样我就可以使用拖放选择所有场景名称。

我试图放置一个静态类,然后像这样

 public static string SCENE_MENU = "Menu";
 public static string SCENE_WORLD = "Demo";

或在枚举内

 public enum SCENE_NAME{
 Menu, Demo
 }

,然后在枚举上使用GetName来获取值

什么是最好的方法? 1:/ storage / temp / 135402-screenshot-1.png

1 个答案:

答案 0 :(得分:3)

使用客户编辑器脚本,您可以使用SceneAsset来存储场景的路径。

我将在此处使用CustomEditor,因为对于初学者而言,更容易理解在那里发生的事情。稍后,您可能需要将其切换为CustomPropertyDrawer,以获得适当的类,甚至可以将其用作属性。

将其放置在Assets

中的任何位置
public class SceneLoader : MonoBehaviour
{
    public string ScenePath;

    public void Load()
    {
        //e.g.
        SceneManager.LoadSceneAsync(ScenePath);
    }
}

将其放置在文件夹Editor内(这样它将不会包含在UnityEditor名称空间不存在的版本中)

[CustomEditor(typeof(SceneLoader), true)]
public class ScenePickerEditor : Editor
{
    private SerializedProperty _scenePath;

    private void OnEnable()
    {
        _scenePath = serializezObject.FindProperty("ScenePath");
    }

    public override void OnInspectorGUI()
    {
        // Draw the usual script field
        EditorGUI.BeginDisabledGroup(true);
         EditorGUILayout.ObjectField(.FromMonoBehaviour((SceneLoader)target), typeof(SceneLoader), false);
        EditorGUI.EndDisabledGroup();

        // Loads current Values into the serialized "copy"
        serializedObject.Update();

        // Get the current scene asset for the current path
        var currentScene = !string.IsNullOrWhiteSpace(_scenePath.stringValue) ? AssetDatabase.LoadAssetAtPath<SceneAsset>(_scenePath.stringValue) : null;          

        EditorGUI.BeginChangeCheck();
        var newScene = (SceneAsset)EditorGUILayout.ObjectField("Scene", currentScene, typeof(SceneAsset), false);

        if (EditorGUI.EndChangeCheck())
        {
            _scenePath.stringValue = newScene != Null ? AssetDatabase.GetAssetPath(newScene) : "";               
        }

        // Write back changes to the actual component
        serializedObject.ApplyModifiedProperties();
    }
}

例如在您的按钮上,附加该SceneLoader组件。

比起您可以通过拖放在Inspector中简单引用目标场景而言。而是在内部存储相应的ScenePath。

现在在onClick中使用该SceneLoader.Load


注意:
here所述,仅存储场景路径可能不会被“保存”,并且在以后移动相应场景或重命名场景时会中断。因此,也许还可以将根据对象引用存储为一种备用,这是一个很好的扩展。


您可能还可以使用这种方法并将其扩展为像

这样的中央管理器。
// It could as well be a ScriptableObject object

// this makes e.g. Awake run already in edit mode
[ExecuteInEditMode]
public class ScenePathManager : MonoBehaviour
{
    // I would prefere references but for ease of this post
    // use a Singleton for access
    public static ScenePathManager Instance;

    public List<string> AvailableScenePaths = new List<string>();

    private void Awake ()
    {
        Instance = this;
    }
}

,然后在编辑器脚本中使用列表(同样,还有一些更漂亮的方法,例如ReorderableList,在这里会变得复杂

[CustomEditor(typeof(ScenePathManager))]
public class ScenePathManagerEditor : Editor
{
    private SerializedProperty _availablePaths;

    private void OnEnable ()
    {
        _availablePaths = serializedObject.FindProperty("AvailablScenePaths");
    }

    public override OnInpectorGUI ()
    {
        // Draw the usual script field
        EditorGUI.BeginDisabledGroup(true);
        EditorGUILayout.ObjectField(.FromMonoBehaviour((SceneLoader)target), typeof(SceneLoader), false);
        EditorGUI.EndDisabledGroup();

        serializedObject.Update();

        //Do the same thing as before but this time in a loop
        for(var i=0; i<_availablePaths.arraySize; i++)
        {
            var _scenePath = _availablePaths.GetArrayElementAtIndex(i);

             // Loads current Values into the serialized "copy"
            serializedObject.Update();

            // Get the current scene asset for the current path
            var currentScene = !string.IsNullOrWhiteSpace(_scenePath.stringValue) ? AssetDatabase.LoadAssetAtPath<SceneAsset>(_scenePath.stringValue) : null;          

            EditorGUI.BeginChangeCheck();
            var newScene = (SceneAsset)EditorGUILayout.ObjectField("Scene", currentScene, typeof(SceneAsset), false);

            if (EditorGUI.EndChangeCheck())
            {
                _scenePath.stringValue = newScene != Null ? AssetDatabase.GetAssetPath(newScene) : "";               
            }
        }
        serializedObject.ApplyModifiedProperties();
    }
}

与您可以引用该经理中的所有所需场景相比,SceneLoader上要有一个Popup字段(例如枚举),以便选择所需的场景

[CustomEditor (typeof (SceneLoader))]
public class SceneLoaderEditor : Editor
{
    private SerializedProperty _scenePath;

    private void OnEnable ()
    {
        _scenePath = serializedObject.FindProperty("ScenePath");
    }

    public override void OnInpectorGUI ()
    {
        //Let me shorten it a bit this time ^^

        serializedObject.Update();
        var availablePaths = ScenePathManager.Instance ? ScenePathManager.Instance.AvailableScenePaths : new List<string>();

        var currentIndex = availablePaths.FirstOrDefault(path => string.Equals(path, _scenePath.stringValue)));

        var newIndex = EditorGUILayout.PopupField("Scene", currentIndex, availabePaths.ToArray());

        _scenePath.stringValue = availablePaths[newIndex];

        serializedObject.ApplyModifiedProperties();
    }
}

这应该为您提供场景的选择下拉列表。

注意,这可能会在没有对象引用的情况下发生,因为任何这些字符串或索引的更改都会使后备字段中断evem更快...

但是,您也可以在不使用整个SceneAsset方法的情况下,与您的经理一起使用此功能,而仅适用于简单的字符串。


在智能手机上键入内容,因此没有保修,但我希望我能阐明我的观点