在哪里存储我所有的场景名称在一个地方
Where to Store all my scene name in one place
我正在 Unity 中制作一个项目,并希望通过一次播放来访问我所有的 SceneNaming;
现在在UI,我必须手动设置场景名称。
我想将我所有的场景名称存储在一个对象中,这样我就可以使用拖放来选择我所有的场景名称。
我试着放一个静态的 class 然后像这样
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
使用客户编辑器脚本,您可以使用 SceneAsset
来存储场景的路径。
我将在这里使用 CustomEditor,因为对于初学者来说,它更容易理解那里发生的事情。稍后您可能想将其切换为 CustomPropertyDrawer
wot 适当的 class 或什至作为属性。
将其放在 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 组件。
然后您可以通过拖放操作简单地在检查器中引用目标场景。它在内部存储相应的 ScenePath。
现在 onClick
改为使用 SceneLoader.Load
。
注:
如前所述 here 仅存储场景路径可能不是 "save" 并且如果您稍后移动相应场景或重命名它会中断。因此,将相应的对象引用存储为一种后备方式可能是一个很好的扩展。
您也可以使用这种方法并将其扩展为中央管理器,而不是像
// 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
字段(比如枚举)以便 select 你想要的场景
[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();
}
}
这应该会为您提供场景的 selection 下拉菜单。
注意 但是,如果没有对象引用,因为支持字段中断任何这些字符串或索引的更改速度更快...
但是您也可以与您的经理一起使用它,而无需整个 SceneAsset
方法,但仅适用于简单的字符串。
在我的智能手机上打字,所以没有保修,但我希望我能表达清楚
我正在 Unity 中制作一个项目,并希望通过一次播放来访问我所有的 SceneNaming;
现在在UI,我必须手动设置场景名称。
我想将我所有的场景名称存储在一个对象中,这样我就可以使用拖放来选择我所有的场景名称。
我试着放一个静态的 class 然后像这样
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
使用客户编辑器脚本,您可以使用 SceneAsset
来存储场景的路径。
我将在这里使用 CustomEditor,因为对于初学者来说,它更容易理解那里发生的事情。稍后您可能想将其切换为 CustomPropertyDrawer
wot 适当的 class 或什至作为属性。
将其放在 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 组件。
然后您可以通过拖放操作简单地在检查器中引用目标场景。它在内部存储相应的 ScenePath。
现在 onClick
改为使用 SceneLoader.Load
。
注:
如前所述 here 仅存储场景路径可能不是 "save" 并且如果您稍后移动相应场景或重命名它会中断。因此,将相应的对象引用存储为一种后备方式可能是一个很好的扩展。
您也可以使用这种方法并将其扩展为中央管理器,而不是像
// 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
字段(比如枚举)以便 select 你想要的场景
[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();
}
}
这应该会为您提供场景的 selection 下拉菜单。
注意 但是,如果没有对象引用,因为支持字段中断任何这些字符串或索引的更改速度更快...
但是您也可以与您的经理一起使用它,而无需整个 SceneAsset
方法,但仅适用于简单的字符串。
在我的智能手机上打字,所以没有保修,但我希望我能表达清楚