Rework of base interactables and managed behaviors
This commit is contained in:
committed by
Michal Pikulski
parent
00e1746ac4
commit
f88bd0e2c9
169
docs/critical_boot_lifecycle_bug_fix.md
Normal file
169
docs/critical_boot_lifecycle_bug_fix.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# CRITICAL BUG: BroadcastSceneReady Never Called During Boot
|
||||
|
||||
## Problem Report
|
||||
|
||||
User reported: "I don't have that log in my console" referring to:
|
||||
```csharp
|
||||
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:
|
||||
```csharp
|
||||
// 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:
|
||||
|
||||
```csharp
|
||||
// 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.
|
||||
|
||||
## Related Issues Fixed
|
||||
|
||||
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!
|
||||
|
||||
Reference in New Issue
Block a user