Files
AppleHillsProduction/docs/critical_boot_lifecycle_bug_fix.md
2025-11-05 20:37:16 +01:00

5.3 KiB

CRITICAL BUG: BroadcastSceneReady Never Called During Boot

Problem Report

User reported: "I don't have that log in my console" referring to:

LogDebug($"Broadcasting SceneReady for scene: {sceneName}");

Root Cause Analysis

The Discovery

Searched console logs for "Broadcasting" - ZERO results!

This means BroadcastSceneReady() was NEVER called, which explains why:

  • LevelSwitch.OnSceneReady() never called
  • PuzzleManager.OnSceneReady() never called (before we fixed it)
  • All scene lifecycle hooks completely broken during boot

The Investigation

Where BroadcastSceneReady SHOULD be called:

  1. SceneManagerService.SwitchSceneAsync() - line 364 - BUT NOT USED DURING BOOT
  2. BootSceneController.LoadMainScene() - MISSING!

The Problem Code Path:

When you play from StartingScene:

// BootSceneController.LoadMainScene() - line 192
var op = SceneManager.LoadSceneAsync(mainSceneName, LoadSceneMode.Additive);
// ... waits for scene to load
SceneManagerService.Instance.CurrentGameplayScene = mainSceneName;
_sceneLoadingProgress = 1f;
// ❌ STOPS HERE - NO LIFECYCLE BROADCASTS!

What's missing:

  • No call to LifecycleManager.BroadcastSceneReady()
  • No call to LifecycleManager.BroadcastRestoreRequested()
  • Components in the loaded scene never get their lifecycle hooks!

Why It Happened

BootSceneController was implemented BEFORE the lifecycle system was fully integrated. It loads scenes directly using Unity's SceneManager.LoadSceneAsync() instead of using SceneManagerService.SwitchSceneAsync(), which means it completely bypasses the lifecycle broadcasts.

The Broken Flow:

StartingScene loads
  ↓
BootSceneController.OnManagedAwake()
  ↓
LoadMainScene()
  ↓
SceneManager.LoadSceneAsync("AppleHillsOverworld") ← Direct Unity call
  ↓
Scene loads, all Awake() methods run
  ↓
LevelSwitch registers with LifecycleManager
  ↓
... nothing happens ❌
  ↓
NO BroadcastSceneReady() ❌
NO OnSceneReady() calls ❌

The Fix

Added lifecycle broadcasts to BootSceneController after scene loading completes:

// Update the current gameplay scene in SceneManagerService
SceneManagerService.Instance.CurrentGameplayScene = mainSceneName;

// Ensure progress is complete
_sceneLoadingProgress = 1f;

// CRITICAL: Broadcast lifecycle events so components get their OnSceneReady callbacks
LogDebugMessage($"Broadcasting OnSceneReady for: {mainSceneName}");
LifecycleManager.Instance?.BroadcastSceneReady(mainSceneName);

LogDebugMessage($"Broadcasting OnRestoreRequested for: {mainSceneName}");
LifecycleManager.Instance?.BroadcastRestoreRequested(mainSceneName);

The Corrected Flow

StartingScene loads
  ↓
BootSceneController.OnManagedAwake()
  ↓
LoadMainScene()
  ↓
SceneManager.LoadSceneAsync("AppleHillsOverworld")
  ↓
Scene loads, all Awake() methods run
  ↓
LevelSwitch registers with LifecycleManager (late registration)
  ↓
✅ BroadcastSceneReady("AppleHillsOverworld") ← NEW!
  ↓
✅ LevelSwitch.OnSceneReady() called!
  ↓
✅ BroadcastRestoreRequested("AppleHillsOverworld")
  ↓
✅ Components can restore save data

Expected Logs After Fix

When playing from StartingScene, you should now see:

[BootSceneController] Loading main menu scene: AppleHillsOverworld
[BootSceneController] Broadcasting OnSceneReady for: AppleHillsOverworld
[LifecycleManager] Broadcasting SceneReady for scene: AppleHillsOverworld  ← THIS WAS MISSING!
[LevelSwitch] OnSceneReady called for CementFactory  ← NOW WORKS!
[LevelSwitch] OnSceneReady called for Quarry
[LevelSwitch] OnSceneReady called for Dump
[BootSceneController] Broadcasting OnRestoreRequested for: AppleHillsOverworld
[LifecycleManager] Broadcasting RestoreRequested for scene: AppleHillsOverworld

Impact

Before Fix

  • Boot scene loading bypassed lifecycle system completely
  • No OnSceneReady() calls during initial boot
  • No OnRestoreRequested() calls
  • Late registration check in LifecycleManager only helped with subsequent scene loads
  • All scene-specific initialization broken during boot!

After Fix

  • Boot scene loading now properly integrates with lifecycle system
  • OnSceneReady() called for all components in initial scene
  • OnRestoreRequested() called for save/load integration
  • Consistent lifecycle behavior whether loading from boot or switching scenes
  • Full lifecycle system functional!

Files Modified

  1. BootSceneController.cs - Added lifecycle broadcasts after scene load

Design Lesson

ANY code that loads scenes must broadcast lifecycle events!

This includes:

  • SceneManagerService.SwitchSceneAsync() - already does this
  • BootSceneController.LoadMainScene() - NOW does this
  • ⚠️ Any future scene loading code must also do this!

The lifecycle broadcasts are NOT automatic - they must be explicitly called after scene loading completes.

This single fix resolves:

  1. LevelSwitch.OnSceneReady() not being called during boot
  2. Any component's OnSceneReady() not being called during boot
  3. OnRestoreRequested() not being called during boot
  4. Save/load integration broken during boot
  5. Inconsistent lifecycle behavior between boot and scene switching

Status: FIXED - Boot scene loading now properly broadcasts lifecycle events!