Revamp the prompt system, the bootstrapper system, the starting cinematic

This commit is contained in:
Michal Pikulski
2025-10-16 19:43:19 +02:00
parent df604fbc03
commit 50448c5bd3
89 changed files with 3964 additions and 677 deletions

View File

@@ -4,6 +4,7 @@ using System.Threading.Tasks;
using UI;
using UnityEngine;
using UnityEngine.SceneManagement;
using Bootstrap;
namespace Core
{
@@ -15,26 +16,11 @@ namespace Core
private LoadingScreenController _loadingScreen;
private static SceneManagerService _instance;
private static bool _isQuitting = false;
/// <summary>
/// Singleton instance of the SceneManagerService.
/// Singleton instance of the SceneManagerService. No longer creates an instance if one doesn't exist.
/// </summary>
public static SceneManagerService Instance
{
get
{
if (_instance == null && Application.isPlaying && !_isQuitting)
{
_instance = FindAnyObjectByType<SceneManagerService>();
if (_instance == null)
{
var go = new GameObject("SceneManagerService");
_instance = go.AddComponent<SceneManagerService>();
// DontDestroyOnLoad(go);
}
}
return _instance;
}
}
public static SceneManagerService Instance => _instance;
// Events for scene lifecycle
public event Action<string> SceneLoadStarted;
@@ -48,30 +34,17 @@ namespace Core
private readonly Dictionary<string, AsyncOperation> _activeUnloads = new();
private const string BootstrapSceneName = "BootstrapScene";
void Start()
{
_loadingScreen = LoadingScreenController.Instance;
// Set up loading screen event handlers
SetupLoadingScreenEvents();
}
void Awake()
{
_instance = this;
// DontDestroyOnLoad(gameObject);
#if UNITY_EDITOR
// In Editor, set CurrentGameplayScene to the currently open scene at play start
if (Application.isPlaying)
{
var activeScene = SceneManager.GetActiveScene();
if (activeScene.IsValid())
{
CurrentGameplayScene = activeScene.name;
}
}
#endif
// Initialize current scene tracking immediately in Awake
InitializeCurrentSceneTracking();
// Register for post-boot initialization
BootCompletionService.RegisterInitAction(InitializePostBoot);
// Ensure BootstrapScene is loaded at startup
var bootstrap = SceneManager.GetSceneByName(BootstrapSceneName);
if (!bootstrap.isLoaded)
@@ -79,6 +52,48 @@ namespace Core
SceneManager.LoadScene(BootstrapSceneName, LoadSceneMode.Additive);
}
}
/// <summary>
/// Initialize current scene tracking immediately in Awake
/// This ensures scene management works correctly regardless of boot timing
/// </summary>
private void InitializeCurrentSceneTracking()
{
// Get the active scene and use it as the current gameplay scene
Scene activeScene = SceneManager.GetActiveScene();
if (activeScene.IsValid())
{
// If this is the MainMenu or another gameplay scene, track it
if (activeScene.name != BootstrapSceneName)
{
CurrentGameplayScene = activeScene.name;
Logging.Debug($"[SceneManagerService] Initialized with current scene: {CurrentGameplayScene}");
}
// Otherwise default to MainMenu
else
{
CurrentGameplayScene = "MainMenu";
Logging.Debug($"[SceneManagerService] Initialized with default scene: {CurrentGameplayScene}");
}
}
else
{
CurrentGameplayScene = "MainMenu";
Logging.Debug($"[SceneManagerService] No valid active scene, defaulting to: {CurrentGameplayScene}");
}
}
private void InitializePostBoot()
{
// Set up loading screen reference and events after boot is complete
_loadingScreen = LoadingScreenController.Instance;
// Set up loading screen event handlers if available
SetupLoadingScreenEvents();
Logging.Debug($"[SceneManagerService] Post-boot initialization complete, current scene is: {CurrentGameplayScene}");
}
private void SetupLoadingScreenEvents()
{
@@ -262,16 +277,27 @@ namespace Core
}
// Tracks the currently loaded gameplay scene (not persistent/bootstrapper)
public string CurrentGameplayScene { get; private set; } = "MainMenu";
public string CurrentGameplayScene { get; set; } = "MainMenu";
public async Task ReloadCurrentScene(IProgress<float> progress = null)
public async Task ReloadCurrentScene(IProgress<float> progress = null, bool autoHideLoadingScreen = true)
{
await SwitchSceneAsync(CurrentGameplayScene, progress);
await SwitchSceneAsync(CurrentGameplayScene, progress, autoHideLoadingScreen);
}
// Switches from current gameplay scene to a new one
public async Task SwitchSceneAsync(string newSceneName, IProgress<float> progress = null)
/// <summary>
/// Switches from current gameplay scene to a new one
/// </summary>
/// <param name="newSceneName">Name of the scene to load</param>
/// <param name="progress">Optional progress reporter</param>
/// <param name="autoHideLoadingScreen">Whether to automatically hide the loading screen when complete. If false, caller must hide it manually.</param>
public async Task SwitchSceneAsync(string newSceneName, IProgress<float> progress = null, bool autoHideLoadingScreen = true)
{
// Show loading screen at the start (whether using auto-hide or not)
if (_loadingScreen != null && !_loadingScreen.IsActive)
{
_loadingScreen.ShowLoadingScreen();
}
// Remove all AstarPath (A* Pathfinder) singletons before loading the new scene
var astarPaths = FindObjectsByType<AstarPath>(FindObjectsSortMode.None);
foreach (var astar in astarPaths)
@@ -304,6 +330,12 @@ namespace Core
await LoadSceneAsync(newSceneName, progress);
// Update tracker
CurrentGameplayScene = newSceneName;
// Only hide the loading screen if autoHideLoadingScreen is true
if (autoHideLoadingScreen && _loadingScreen != null)
{
_loadingScreen.HideLoadingScreen();
}
}
}
}