using System.Collections; using UnityEngine; using UnityEngine.SceneManagement; namespace NightclubArcadia.Core { /// /// The entry point. Loads the persistent Systems scene, then a level, additively. /// /// Splitting the game across scenes is what lets a level be edited without touching /// the systems wiring, and stops a corrupted level from taking the dialogue runner, /// the UI layer and the player with it. The cost is that serialized references /// cannot cross a scene boundary — Unity nulls those — so the handful of level /// objects that need a system resolve it at runtime instead. See SceneServices. /// public sealed class GameBootstrap : MonoBehaviour { [Tooltip("Persistent scene holding dialogue, skills, UI, the camera rig and the player.")] [SerializeField] string systemsScene = "Systems"; [Tooltip("Level to open on start. Leave empty to load only the systems layer.")] [SerializeField] string startLevel = "SC101_ConferenceHall"; IEnumerator Start() { yield return LoadIfNeeded(systemsScene); if (!string.IsNullOrEmpty(startLevel)) { yield return LoadIfNeeded(startLevel); var level = SceneManager.GetSceneByName(startLevel); if (level.IsValid() && level.isLoaded) { // The active scene decides where new objects land and which // lighting settings apply, so it must be the level, not this one. SceneManager.SetActiveScene(level); } } } static IEnumerator LoadIfNeeded(string sceneName) { if (string.IsNullOrEmpty(sceneName)) { yield break; } var existing = SceneManager.GetSceneByName(sceneName); if (existing.IsValid() && existing.isLoaded) { yield break; } var op = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive); if (op == null) { Debug.LogError($"[GameBootstrap] '{sceneName}' is not in the build settings."); yield break; } yield return op; } } }