# Critical Bug Fix: Missing base.Awake() Calls ## The Bug When we added custom `Awake()` methods to singleton managers using the `new` keyword to hide the base class method, **we forgot to call `base.Awake()`**, which prevented ManagedBehaviour from registering components with LifecycleManager. ### Root Cause ```csharp // BROKEN - Missing base.Awake() call private new void Awake() { _instance = this; // ... initialization } // ❌ ManagedBehaviour.Awake() NEVER CALLED! // ❌ LifecycleManager.Register() NEVER CALLED! // ❌ OnManagedAwake() NEVER INVOKED! ``` **What should have happened:** 1. `ManagedBehaviour.Awake()` registers component with LifecycleManager 2. LifecycleManager broadcasts `OnManagedAwake()` after boot completion 3. Component receives lifecycle callbacks **What actually happened:** 1. Custom `Awake()` hides base implementation 2. Component never registers with LifecycleManager 3. `OnManagedAwake()` never called ❌ ## The Fix Added `base.Awake()` as the **FIRST line** in every custom Awake() method: ```csharp // FIXED - Calls base.Awake() to register private new void Awake() { base.Awake(); // CRITICAL: Register with LifecycleManager! _instance = this; // ... initialization } // ✅ ManagedBehaviour.Awake() called! // ✅ LifecycleManager.Register() called! // ✅ OnManagedAwake() will be invoked! ``` ## Files Fixed (14 Total) ### Core Systems 1. ✅ **GameManager.cs** (Priority 10) 2. ✅ **SceneManagerService.cs** (Priority 15) 3. ✅ **SaveLoadManager.cs** (Priority 20) 4. ✅ **QuickAccess.cs** (Priority 5) ### Infrastructure 5. ✅ **InputManager.cs** (Priority 25) 6. ✅ **AudioManager.cs** (Priority 30) 7. ✅ **LoadingScreenController.cs** (Priority 45) 8. ✅ **UIPageController.cs** (Priority 50) 9. ✅ **PauseMenu.cs** (Priority 55) 10. ✅ **SceneOrientationEnforcer.cs** (Priority 70) ### Game Systems 11. ✅ **ItemManager.cs** (Priority 75) 12. ✅ **PuzzleManager.cs** (Priority 80) 13. ✅ **CinematicsManager.cs** (Priority 170) 14. ✅ **CardSystemManager.cs** (Priority 60) ## Impact ### Before Fix ❌ - Singleton instances were set (`_instance = this`) ✅ - Settings were initialized ✅ - **BUT**: Components never registered with LifecycleManager ❌ - **Result**: `OnManagedAwake()` never called ❌ - **Result**: No lifecycle hooks (OnSceneReady, OnSceneUnloading, etc.) ❌ - **Result**: Auto-registration features (IPausable, etc.) broken ❌ ### After Fix ✅ - Singleton instances set ✅ - Settings initialized ✅ - Components registered with LifecycleManager ✅ - `OnManagedAwake()` called in priority order ✅ - All lifecycle hooks working ✅ - Auto-registration features working ✅ ## Why This Happened When we moved singleton instance assignment from `OnManagedAwake()` to `Awake()`, we used the `new` keyword to hide the base class Awake method. However, **hiding is not the same as overriding**: ```csharp // Hiding (new) - base method NOT called automatically private new void Awake() { } // Overriding (override) - base method NOT called automatically protected override void Awake() { } // Both require EXPLICIT base.Awake() call! ``` We correctly used `new` (since ManagedBehaviour.Awake() is not virtual), but forgot to explicitly call `base.Awake()`. ## The Correct Pattern For any ManagedBehaviour with a custom Awake(): ```csharp public class MyManager : ManagedBehaviour { private static MyManager _instance; public static MyManager Instance => _instance; public override int ManagedAwakePriority => 50; private new void Awake() { base.Awake(); // ✅ ALWAYS CALL THIS FIRST! _instance = this; // ... other early initialization } protected override void OnManagedAwake() { // Lifecycle hooks work now! } } ``` ## Testing Checklist To verify the fix works: - [x] All files compile without errors - [ ] Run from StartingScene - verify boot sequence works - [ ] Check console for `[LifecycleManager] Registered [ComponentName]` messages - [ ] Verify OnManagedAwake() logs appear (e.g., "XAXA" from LevelSwitch) - [ ] Test scene switching - verify lifecycle hooks fire - [ ] Test pause system - verify IPausable auto-registration works - [ ] Test save/load - verify ISaveParticipant integration works ## Key Lesson **When hiding a base class method with `new`, you MUST explicitly call the base implementation if you need its functionality!** ```csharp // WRONG ❌ private new void Awake() { // Missing base.Awake() } // CORRECT ✅ private new void Awake() { base.Awake(); // Explicitly call base! // ... custom logic } ``` --- **Status**: ✅ FIXED - All 14 managers now properly call base.Awake() to ensure LifecycleManager registration!