Ваш вопрос очень широкий ...
Чтобы поместить сцены в список в Инспекторе, я использовал это:
public class ScenePathManager : MonoBehaviour
{
[Serializable]
public class SceneElement
{
string Path;
string Name;
}
public List<SceneElement> Scenes = new List<SceneElement>();
// Loading scenes by path is more secure
// since two scenes might have the same name
// but the path is always unique
public void LoadScene(string path)
{
if(string.IsNullOrEmpty(path))
{
Debug.LogError("Given path is null or empty!", this);
return;
}
if(!Scenes.Any(s=>string.Equals(s.Path, path)))
{
Debug.LogError("Given path " + path + " is invalid!", this);
return;
}
// Load the Scene here e.g. using
SceneManager.LoadSceneAsync(path);
}
}
скрипт редактора (его нужно поместить впапка с именем Editor
)
using UnityEditor
[CustomEditor(typeof(ScenePathManager))]
private partial class ScenePathManagerEditor : Editor
{
private SerializedProperty _scenes;
private ReorderableList _sceneList;
private void OnEnable()
{
_scenes = serializedObject.FindProperty("Scenes");
_sceneList = new ReorderableList(serializedObject, _scenes)
{
displayAdd = true,
displayRemove = true,
draggable = true,
drawHeaderCallback = rect => EditorGUI.LabelField(rect, "Scenes"),
drawElementCallback = (rect, index, selected, highlighted) =>
{
var element = _scenes.GetArrayElementAtIndex(index);
var path = element.FindPropertyRelative("Path");
var name = element.FindPropertyRelative("Name");
// get the SceneAsset that belongs to the current path
var scene = AssetDatabase.LoadAssetAtPath<SceneAsset>(path.stringValue);
// draw an object field in the editor
scene = (SceneAsset)EditorGUI.ObjectField(new Rect(rect.x, rect.y, rect.width * 0.5f, EditorGUIUtility.singleLineHeight), scene, typeof(SceneAsset), false);
// write back the path of the SceneAsset
path.stringValue = AssetDatabase.GetAssetOrScenePath(scene);
name.stringValue = scene.name;
},
elementHeight = EditorGUIUtility.singleLineHeight * 1.2f
};
}
public override void OnInspectorGUI()
{
DrawScriptField();
serializedObject.Update();
// Disable editing of the list on runtime
EditorGUI.BeginDisabledGroup(true);
_sceneList.DoLayoutList();
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
}
// Draws the usual Script field in the Inspector
private void DrawScriptField()
{
// Disable editing
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.ObjectField("Script", MonoScript.FromMonoBehaviour((ScenePathManager)target), typeof(ScenePathManager), false);
EditorGUI.EndDisabledGroup();
EditorGUILayout.Space();
}
}
Теперь вы можете просто сослаться на ресурсы сцены и получить соответствующие ScenePaths и имена.
Теперь к кнопкам,Самый простой способ - использовать одну кнопку в качестве префаба, создавать и настраивать кнопки во время выполнения, например,
public class ButtonSpawner : MonoBehaviour
{
// somehow get this reference e.g. via drag and drop in the Inspector
[SerializeField] private ScenePathManager _scenePathManager;
// reference your prefab here
[SerializeField] private Button _buttonPrefab;
public void SpawnButtons()
{
foreach(var scene in _scenePathManager.Scenes)
{
// ofcourse you will want to spawn this maybe as
// child of another object or position them etc
var button = Instantiate(_buttonPrefab);
// However you want to get the text. You could also give each button
// special MonoBehaviour class and reference all components you need
var buttonText = button.GetComponentInChildren<Text>(true);
buttonText.text = scene.Name;
button.onClick.AddListener(() =>
{
_scenePathManager.LoadScene(scene.Path);
});
}
}
}
Вы даже можете автоматически добавлять все сцены, на которые есть ссылки в настройках сборки (я использовал это только для добавлениязагрузка сцены, но это только идея;))
#if UNITY_EDITOR
public void AddListsToBuildSettings()
{
var editorBuildSettingsScenes = new List<EditorBuildSettingsScene>
{
// Pre-add the current Scene
new EditorBuildSettingsScene(SceneManager.GetActiveScene().path, true)
};
// Add all scenes in ScenePaths to the EditorBuildSettings
foreach (var scene in ScenePaths)
{
// ignore unsaved scenes
if (string.IsNullOrEmpty(scene?.Path)) continue;
// skip if scene already in buildSettings
if (editorBuildSettingsScenes.Any(s => string.Equals(s.path, scene))) continue;
editorBuildSettingsScenes.Add(new EditorBuildSettingsScene(scene.Path, true));
}
// Set the Build Settings window Scene list
EditorBuildSettings.scenes = editorBuildSettingsScenes.ToArray();
}
#endif