diff --git a/Assets/Scripts/Bootstrap/BootSceneController.cs b/Assets/Scripts/Bootstrap/BootSceneController.cs index 3c9a2b99..239d8b0c 100644 --- a/Assets/Scripts/Bootstrap/BootSceneController.cs +++ b/Assets/Scripts/Bootstrap/BootSceneController.cs @@ -14,9 +14,16 @@ namespace Bootstrap [SerializeField] private string mainMenuSceneName = "MainMenu"; [SerializeField] private float minDelayAfterBoot = 0.5f; // Small delay after boot to ensure smooth transition [SerializeField] private bool debugMode = false; - + + // Progress distribution between bootstrap and scene loading + [SerializeField, Range(0.1f, 0.9f)] private float bootProgressWeight = 0.5f; // Default 50/50 split + + private enum LoadingPhase { Bootstrap, SceneLoading } + private LoadingPhase _currentPhase = LoadingPhase.Bootstrap; + private bool _bootComplete = false; private bool _hasStartedLoading = false; + private float _sceneLoadingProgress = 0f; private void Start() { @@ -29,12 +36,12 @@ namespace Bootstrap return; } - // Show the loading screen immediately + // Show the loading screen immediately with our combined progress provider LoadingScreenController.Instance.ShowLoadingScreen( - // Use the CustomBoot progress as the progress provider - progressProvider: () => CustomBoot.CurrentProgress, - // When loading screen is fully hidden, load main menu - onComplete: () => LoadMainMenu() + progressProvider: GetCombinedProgress, + onComplete: () => { + Debug.Log("[BootSceneController] Loading screen fully hidden, boot sequence completed"); + } ); // Start the boot process if not already initialized @@ -73,17 +80,38 @@ namespace Bootstrap } } + /// + /// Progress provider that combines bootstrap and scene loading progress + /// + private float GetCombinedProgress() + { + switch (_currentPhase) + { + case LoadingPhase.Bootstrap: + // Scale bootstrap progress from 0 to bootProgressWeight + return CustomBoot.CurrentProgress * bootProgressWeight; + + case LoadingPhase.SceneLoading: + // Scale scene loading progress from bootProgressWeight to 1.0 + return bootProgressWeight + (_sceneLoadingProgress * (1f - bootProgressWeight)); + + default: + return 0f; + } + } + private void OnBootProgressChanged(float progress) { if (debugMode) { - Debug.Log($"[BootSceneController] Boot progress: {progress:P0}"); + Debug.Log($"[BootSceneController] Bootstrap progress: {progress:P0}, Combined: {GetCombinedProgress():P0}"); } } private void LogDebugInfo() { - Debug.Log($"[BootSceneController] Debug - Boot Progress: {CustomBoot.CurrentProgress:P0}, Boot Complete: {_bootComplete}, Loading Started: {_hasStartedLoading}"); + Debug.Log($"[BootSceneController] Debug - Phase: {_currentPhase}, Bootstrap: {CustomBoot.CurrentProgress:P0}, " + + $"Scene: {_sceneLoadingProgress:P0}, Combined: {GetCombinedProgress():P0}, Boot Complete: {_bootComplete}"); } private void OnBootCompleted() @@ -94,34 +122,56 @@ namespace Bootstrap Debug.Log("[BootSceneController] Boot process completed"); _bootComplete = true; - // After a small delay, tell the loading screen we're done + // After a small delay, start loading the main menu // This prevents jerky transitions if boot happens very quickly - Invoke(nameof(CompleteLoadingScreen), minDelayAfterBoot); + Invoke(nameof(StartLoadingMainMenu), minDelayAfterBoot); } - private void CompleteLoadingScreen() + private void StartLoadingMainMenu() { - Debug.Log("[BootSceneController] Hiding loading screen"); - - // Tell loading screen that loading is complete - if (LoadingScreenController.Instance != null) - { - LoadingScreenController.Instance.HideLoadingScreen(); - } - } - - private async void LoadMainMenu() - { - // Prevent multiple scene loads if (_hasStartedLoading) return; _hasStartedLoading = true; + _currentPhase = LoadingPhase.SceneLoading; + LoadMainMenu(); + } + + private async void LoadMainMenu() + { Debug.Log($"[BootSceneController] Loading main menu scene: {mainMenuSceneName}"); - // Load the main menu scene - var progress = new Progress(p => Debug.Log($"Loading main menu: {p * 100:F0}%")); - await SceneManagerService.Instance.SwitchSceneAsync(mainMenuSceneName, progress); + try + { + // Initialize scene loading progress to 0 to ensure proper remapping + _sceneLoadingProgress = 0f; + + // Create a progress object that remaps scene loading progress (0-1) to our second phase range + var progress = new Progress(p => { + // Store the raw scene loading progress (0-1) + _sceneLoadingProgress = p; + + if (debugMode) + { + Debug.Log($"[BootSceneController] Scene loading raw: {p:P0}, Combined: {GetCombinedProgress():P0}"); + } + }); + + // Load the scene but don't auto-hide loading screen (we're managing that ourselves) + await SceneManagerService.Instance.SwitchSceneAsync(mainMenuSceneName, progress, autoHideLoadingScreen: false); + + // Ensure progress is complete + _sceneLoadingProgress = 1f; + + // Scene is fully loaded, we can now hide the loading screen + LoadingScreenController.Instance.HideLoadingScreen(); + } + catch (Exception e) + { + Debug.LogError($"[BootSceneController] Error loading main menu: {e.Message}"); + // Still try to hide the loading screen even if there was an error + LoadingScreenController.Instance.HideLoadingScreen(); + } } } } diff --git a/Assets/Scripts/Cinematics/CinematicsManager.cs b/Assets/Scripts/Cinematics/CinematicsManager.cs index e8dbf1a5..884090d1 100644 --- a/Assets/Scripts/Cinematics/CinematicsManager.cs +++ b/Assets/Scripts/Cinematics/CinematicsManager.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Core; using UnityEngine; @@ -146,11 +147,11 @@ namespace Cinematics _addressableHandles.Clear(); } - private void Awake() + private void Start() { - PlayStartCinematicOnGameLoad(); + } - + /// /// Loads a cinematic asynchronously while showing a loading screen, then plays it /// diff --git a/Assets/Scripts/Core/SceneManagerService.cs b/Assets/Scripts/Core/SceneManagerService.cs index 3ecc6a8f..c36e7405 100644 --- a/Assets/Scripts/Core/SceneManagerService.cs +++ b/Assets/Scripts/Core/SceneManagerService.cs @@ -264,14 +264,25 @@ namespace Core // Tracks the currently loaded gameplay scene (not persistent/bootstrapper) public string CurrentGameplayScene { get; private set; } = "MainMenu"; - public async Task ReloadCurrentScene(IProgress progress = null) + public async Task ReloadCurrentScene(IProgress 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 progress = null) + /// + /// Switches from current gameplay scene to a new one + /// + /// Name of the scene to load + /// Optional progress reporter + /// Whether to automatically hide the loading screen when complete. If false, caller must hide it manually. + public async Task SwitchSceneAsync(string newSceneName, IProgress 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(FindObjectsSortMode.None); foreach (var astar in astarPaths) @@ -304,6 +315,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(); + } } } }