我正在Unity中创建一个probject,并且想通过一个游戏来访问我所有的SceneNaming;
现在在用户界面中,我必须手动设置场景名称。
我想将所有场景名称存储在一个对象中,这样我就可以使用拖放选择所有场景名称。
我试图放置一个静态类,然后像这样
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
答案 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
方法的情况下,与您的经理一起使用此功能,而仅适用于简单的字符串。
在智能手机上键入内容,因此没有保修,但我希望我能阐明我的观点