Files
AppleHillsProduction/Assets/Scripts/Bootstrap/BootSceneController.cs
2025-10-16 11:14:41 +02:00

178 lines
6.8 KiB
C#

using System;
using UnityEngine;
using UI;
using Core;
using UnityEngine.SceneManagement;
namespace Bootstrap
{
/// <summary>
/// Controller for the boot scene that coordinates bootstrap initialization with loading screen
/// </summary>
public class BootSceneController : MonoBehaviour
{
[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()
{
Debug.Log("[BootSceneController] Boot scene started");
// Ensure the loading screen controller exists
if (LoadingScreenController.Instance == null)
{
Debug.LogError("[BootSceneController] No LoadingScreenController found in the scene!");
return;
}
// Show the loading screen immediately with our combined progress provider
LoadingScreenController.Instance.ShowLoadingScreen(
progressProvider: GetCombinedProgress,
onComplete: () => {
Debug.Log("[BootSceneController] Loading screen fully hidden, boot sequence completed");
}
);
// Start the boot process if not already initialized
if (!CustomBoot.Initialised)
{
// Subscribe to the boot completion event
CustomBoot.OnBootCompleted += OnBootCompleted;
CustomBoot.OnBootProgressChanged += OnBootProgressChanged;
// Start initialization
CustomBoot.PerformInitialisation();
}
else
{
// If already initialized (can happen in editor testing), proceed immediately
Debug.Log("[BootSceneController] Bootstrap already initialized, proceeding to main menu");
OnBootCompleted();
}
// In debug mode, log additional information
if (debugMode)
{
InvokeRepeating(nameof(LogDebugInfo), 0.1f, 0.5f);
}
}
private void OnDestroy()
{
// Clean up event subscriptions
CustomBoot.OnBootCompleted -= OnBootCompleted;
CustomBoot.OnBootProgressChanged -= OnBootProgressChanged;
if (debugMode)
{
CancelInvoke(nameof(LogDebugInfo));
}
}
/// <summary>
/// Progress provider that combines bootstrap and scene loading progress
/// </summary>
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] Bootstrap progress: {progress:P0}, Combined: {GetCombinedProgress():P0}");
}
}
private void LogDebugInfo()
{
Debug.Log($"[BootSceneController] Debug - Phase: {_currentPhase}, Bootstrap: {CustomBoot.CurrentProgress:P0}, " +
$"Scene: {_sceneLoadingProgress:P0}, Combined: {GetCombinedProgress():P0}, Boot Complete: {_bootComplete}");
}
private void OnBootCompleted()
{
// Unsubscribe to prevent duplicate calls
CustomBoot.OnBootCompleted -= OnBootCompleted;
Debug.Log("[BootSceneController] Boot process completed");
_bootComplete = true;
// After a small delay, start loading the main menu
// This prevents jerky transitions if boot happens very quickly
Invoke(nameof(StartLoadingMainMenu), minDelayAfterBoot);
}
private void StartLoadingMainMenu()
{
if (_hasStartedLoading)
return;
_hasStartedLoading = true;
_currentPhase = LoadingPhase.SceneLoading;
LoadMainMenu();
}
private async void LoadMainMenu()
{
Debug.Log($"[BootSceneController] Loading main menu scene: {mainMenuSceneName}");
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<float>(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();
}
}
}
}