ARTICLE AD BOX
I'm trying to make a chapter system similar to Half-Life, where players will be able to select which chapter to start a new game in with each chapter containing several maps/scenes. However, I'm not sure what the best way to do this is, since Unity is stupid when it comes to with putting scenes into scripts by hand.
I want to be able to simply drag and drop scene objects into my scriptable objects that will represent each chapter of the game. I want to be able to store the starting scene and all other scenes in each chapter so I can reference and load them, but I don't want to fumble around with build indexes, or worse, strings.
However, you can't store scenes directly with the "scene" type and serialize it. UnityEditor provides the just as effective but serializable SceneAsset type, but that's Editor only and I don't want to mess with that stuff. I tried asking AI but it's telling me to juggle with Editor-only, so does anyone else have any good solutions or should I just do this?
ChatGPT wrote these classes, which I have also edited a bit to fix a compiler error:
using UnityEngine; using UnityEngine.SceneManagement; using UnityEditor; [CreateAssetMenu(fileName = "NewChapter", menuName = "World Power/Chapter")] public class ChapterSO : ScriptableObject { [Header("Basic Info")] public string chapterName; // Display name public int chapterOrder; // 1, 2, 3, etc. [Header("Scene Info")] public SceneAsset startMap; // First scene to load in the chapter public SceneAsset endMap; // Optional: last scene public SceneAsset[] includedMaps; // All scenes included in the chapter } using UnityEngine; [CreateAssetMenu(fileName = "ChapterDatabase", menuName = "World Power/Chapter Database")] public class ChapterDatabaseSO : ScriptableObject { public ChapterSO[] chapters; } using UnityEngine; using UnityEngine.SceneManagement; public class ChapterLoader : MonoBehaviour { public void LoadChapter(ChapterSO chapter) { if (chapter == null || chapter.startMap == null) { Debug.LogError("Chapter or start map is null!"); return; } string sceneName = chapter.startMap.name; SceneManager.LoadScene(sceneName); } }As you can see, I need UnityEditor to use the SceneAsset type that is actually serializable, but that doesn't work in builds at all. I think it's stupid that Unity has a whole separate type instead of just making it possible to SF scene references, but hey! What can I do about it?
ChatGPT then suggested having two separate sets of variables to store the scenes, with SceneAssets that are Editor-only and then string references, and an EditorOnly script that will automatically update the references:
#if UNITY_EDITOR using UnityEditor; [CustomEditor(typeof(ChapterSO))] public class ChapterSOEditor : Editor { public override void OnInspectorGUI() { DrawDefaultInspector(); ChapterSO chapter = (ChapterSO)target; if (GUILayout.Button("Sync Scene Names")) { if (chapter.startMapEditor != null) chapter.startMapName = chapter.startMapEditor.name; if (chapter.endMapEditor != null) chapter.endMapName = chapter.endMapEditor.name; if (chapter.includedMapsEditor != null && chapter.includedMapsEditor.Length > 0) { chapter.includedMapNames = new string[chapter.includedMapsEditor.Length]; for (int i = 0; i < chapter.includedMapsEditor.Length; i++) chapter.includedMapNames[i] = chapter.includedMapsEditor[i].name; } EditorUtility.SetDirty(chapter); // Save changes AssetDatabase.SaveAssets(); Debug.Log("Scene names synced!"); } } } #endifI don't want to do this, since it seems too complex (and I don't want 4 different scripts for one system) so I'm hoping that there's a simpler solution that's still as convenient as what ChatGPT proposed.
Until I get an answer I'm going to use this, but I'm not going to use the entire system it made; I already have a simpler loading script, and I'll just make a meta static or persistent SceneManager script to load scenes from both transition portals AND main menu chapter selection.
