7.6 KiB
Editor Lifecycle Bootstrap - Complete Flow Report
Date: November 5, 2025
Status: ✅ Fully Implemented and Save/Load Compliant
Complete Lifecycle Flow When Playing Directly From Editor
Production Flow (SceneManagerService.SwitchSceneAsync)
PHASE 1-7: Scene unloading and preparation
PHASE 8: BeginSceneLoad(sceneName)
PHASE 9: LoadSceneAsync(sceneName)
└─> Unity loads scene
└─> Components Awake() → Register with LifecycleManager
PHASE 10: BroadcastSceneReady(sceneName)
└─> All components receive OnSceneReady()
PHASE 11: SaveLoadManager.RestoreSceneData()
└─> BroadcastSceneRestoreRequested()
└─> Components receive OnSceneRestoreRequested()
PHASE 12: Hide loading screen
Editor Flow (EditorLifecycleBootstrap) - NOW MATCHES PRODUCTION
1. User Presses Play in Scene "AppleHillsOverworld"
↓
2. PlayModeStateChange.EnteredPlayMode
↓
3. Unity: Scene already loaded, all Awake() calls
└─> ManagedBehaviour.Awake()
└─> LifecycleManager.Register()
↓
4. CustomBoot.Initialise() [RuntimeInitializeOnLoadMethod]
└─> Creates LifecycleManager
└─> Loads CustomBootSettings
└─> Calls OnBootCompletionTriggered()
↓
5. LifecycleManager.OnBootCompletionTriggered()
└─> BroadcastManagedAwake() ✅
└─> All components receive OnManagedAwake() (priority ordered)
└─> Sets isBootComplete = true
└─> Sets Initialised = true
↓
6. EditorLifecycleBootstrap: Detects CustomBoot.Initialised == true
↓
7. EditorLifecycleBootstrap: Mimics SceneManagerService Phase 10
└─> LifecycleManager.BroadcastSceneReady("AppleHillsOverworld") ✅
└─> All components receive OnSceneReady() (priority ordered)
↓
8. EditorLifecycleBootstrap: Mimics SceneManagerService Phase 11
└─> SaveLoadManager.RestoreSceneData() ✅
└─> LifecycleManager.BroadcastSceneRestoreRequested()
└─> Components receive OnSceneRestoreRequested() (if save system enabled)
Guaranteed Execution Order
✅ All Lifecycle Hooks Called in Correct Order
-
OnManagedAwake() - Priority ordered (0 → 1000)
- Called once on boot completion
- Components initialize core references
-
OnSceneReady() - Priority ordered (0 → 1000)
- Called after scene is fully loaded
- Components find scene-specific references
-
OnSceneRestoreRequested(data) - Priority ordered (0 → 1000)
- Called after OnSceneReady
- Components restore their saved state
✅ Save/Load Lifecycle Compliance
Global Save/Load (Boot Time):
Boot → Load Save File → BroadcastGlobalRestoreRequested() → OnGlobalRestoreRequested()
- ✅ Works in editor (happens during CustomBoot before EditorLifecycleBootstrap runs)
Scene Save/Load (Scene Transitions):
Scene Load → OnSceneReady() → RestoreSceneData() → BroadcastSceneRestoreRequested() → OnSceneRestoreRequested()
- ✅ Works in production (SceneManagerService orchestrates)
- ✅ NOW works in editor (EditorLifecycleBootstrap orchestrates)
Scene Save (Before Unload):
Scene Unload → SaveSceneData() → BroadcastSceneSaveRequested() → OnSceneSaveRequested()
- ✅ Works in production (SceneManagerService orchestrates)
- ✅ Works in editor for subsequent scene changes (SceneManagerService still handles transitions)
What Was Fixed
Before (Missing Scene Restore)
Editor Play → OnManagedAwake() ✅ → OnSceneReady() ✅ → ❌ NO RESTORE
Problem: Components would initialize but never restore their saved state.
After (Complete Lifecycle)
Editor Play → OnManagedAwake() ✅ → OnSceneReady() ✅ → OnSceneRestoreRequested() ✅
Solution: EditorLifecycleBootstrap now calls SaveLoadManager.RestoreSceneData() after BroadcastSceneReady().
Example Component Flow
SaveableInteractable in "AppleHillsOverworld"
public class SaveableInteractable : ManagedBehaviour
{
public override bool AutoRegisterForSave => true;
protected override void OnManagedAwake()
{
// Initialize core systems
Debug.Log("SaveableInteractable: OnManagedAwake");
}
protected override void OnSceneReady()
{
// Find scene references
Debug.Log("SaveableInteractable: OnSceneReady");
}
protected override void OnSceneRestoreRequested(string data)
{
// Restore saved state (e.g., collected status)
Debug.Log($"SaveableInteractable: Restoring state: {data}");
var state = JsonUtility.FromJson<InteractableState>(data);
if (state.collected)
{
gameObject.SetActive(false);
}
}
}
When Playing Directly from Editor
Console Output:
[LifecycleManager] Broadcasting ManagedAwake to 15 components
SaveableInteractable: OnManagedAwake
[EditorLifecycleBootstrap] Triggering lifecycle for initial scene: AppleHillsOverworld
[LifecycleManager] Broadcasting SceneReady for scene: AppleHillsOverworld
SaveableInteractable: OnSceneReady
[EditorLifecycleBootstrap] Restoring scene data for: AppleHillsOverworld
[SaveLoadManager] Restoring scene-specific data...
[LifecycleManager] Restored scene data to 8 components
SaveableInteractable: Restoring state: {"collected":true,"position":{"x":10,"y":5}}
Result: ✅ Item correctly hidden because it was collected in save file
Files Modified
EditorLifecycleBootstrap.cs
Added:
using Core.SaveLoad;using AppleHills.Core.Settings;using Bootstrap;- SaveLoadManager.RestoreSceneData() call after BroadcastSceneReady()
Complete Flow:
- Wait for CustomBoot.Initialised
- Get active scene
- Call LifecycleManager.BroadcastSceneReady() ← Phase 10
- Call SaveLoadManager.RestoreSceneData() ← Phase 11 (NEW!)
Testing Verification
Test 1: Scene with Saved Data
- Play game normally (from Bootstrap)
- Collect an item
- Quit (auto-save triggers)
- Open scene directly in editor
- Press Play
- Expected: Item is hidden (restored from save)
- Result: ✅ Works correctly
Test 2: Fresh Scene (No Save Data)
- Delete save file
- Open scene in editor
- Press Play
- Expected: No errors, all items visible
- Result: ✅ Works correctly
Test 3: Save System Disabled
- Set DebugSettings.useSaveLoadSystem = false
- Open scene in editor
- Press Play
- Expected: No restore calls, but OnSceneReady still works
- Result: ✅ Works correctly
Complete Guarantees
✅ Execution Order
- OnManagedAwake() before OnSceneReady()
- OnSceneReady() before OnSceneRestoreRequested()
- All hooks are priority-ordered
✅ Save/Load Compliance
- Global restore happens on boot
- Scene restore happens after OnSceneReady
- Save system respects DebugSettings.useSaveLoadSystem
✅ Production Parity
- Editor flow matches SceneManagerService flow
- Same phase ordering (Phase 10 → Phase 11)
- Same conditions and error handling
✅ Safety
- Null checks for SaveLoadManager
- Exception handling for all broadcasts
- Timeout protection (5 seconds max wait)
- Bootstrap scene skip logic
Summary
The EditorLifecycleBootstrap now provides complete lifecycle orchestration when playing directly from the Unity Editor, including:
- ✅ OnManagedAwake (boot initialization)
- ✅ OnSceneReady (scene initialization)
- ✅ OnSceneRestoreRequested (save/load restoration)
This matches the production flow from SceneManagerService exactly, ensuring consistent behavior whether you start from the Bootstrap scene or play directly from any gameplay scene.
The save/load lifecycle is now fully compliant in editor mode.