293 lines
8.9 KiB
Markdown
293 lines
8.9 KiB
Markdown
|
|
# Bootstrapped Manager Initialization Review - Summary
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Performed a comprehensive review of all bootstrapped singleton managers to ensure critical initialization happens in `Awake()` rather than `OnManagedAwake()`, making infrastructure available when other components' `OnManagedAwake()` runs.
|
||
|
|
|
||
|
|
## Key Principle
|
||
|
|
|
||
|
|
**Awake() = Infrastructure Setup**
|
||
|
|
- Singleton instance registration
|
||
|
|
- Critical service initialization (settings, scene tracking, input setup)
|
||
|
|
- Component configuration
|
||
|
|
- State that OTHER components depend on
|
||
|
|
|
||
|
|
**OnManagedAwake() = Dependent Initialization**
|
||
|
|
- Initialization that depends on OTHER managers
|
||
|
|
- Event subscriptions to other managers
|
||
|
|
- Non-critical setup
|
||
|
|
|
||
|
|
## Managers Updated
|
||
|
|
|
||
|
|
### 1. GameManager (Priority 10) ✅
|
||
|
|
|
||
|
|
**Moved to Awake():**
|
||
|
|
- Settings provider creation
|
||
|
|
- Settings initialization (InitializeSettings, InitializeDeveloperSettings)
|
||
|
|
- Verbosity settings loading
|
||
|
|
|
||
|
|
**Rationale:** Other managers need settings in their OnManagedAwake(). Settings MUST be available early.
|
||
|
|
|
||
|
|
**Impact:** All other managers can now safely call `GameManager.GetSettingsObject<T>()` in their OnManagedAwake().
|
||
|
|
|
||
|
|
```csharp
|
||
|
|
private new void Awake()
|
||
|
|
{
|
||
|
|
_instance = this;
|
||
|
|
|
||
|
|
// Create settings providers - CRITICAL for other managers
|
||
|
|
SettingsProvider.Instance.gameObject.name = "Settings Provider";
|
||
|
|
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider";
|
||
|
|
|
||
|
|
// Load all settings synchronously - CRITICAL infrastructure
|
||
|
|
InitializeSettings();
|
||
|
|
InitializeDeveloperSettings();
|
||
|
|
|
||
|
|
_settingsLogVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().settingsLogVerbosity;
|
||
|
|
_managerLogVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().gameManagerLogVerbosity;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. SceneManagerService (Priority 15) ✅
|
||
|
|
|
||
|
|
**Moved to Awake():**
|
||
|
|
- Scene tracking initialization (InitializeCurrentSceneTracking)
|
||
|
|
- Bootstrap scene loading
|
||
|
|
|
||
|
|
**Kept in OnManagedAwake():**
|
||
|
|
- Loading screen reference (depends on LoadingScreenController instance)
|
||
|
|
- Event setup (depends on loading screen)
|
||
|
|
- Verbosity settings
|
||
|
|
|
||
|
|
**Rationale:** Scene tracking is critical state. Loading screen setup depends on LoadingScreenController's instance being set first.
|
||
|
|
|
||
|
|
```csharp
|
||
|
|
private new void Awake()
|
||
|
|
{
|
||
|
|
_instance = this;
|
||
|
|
|
||
|
|
// Initialize current scene tracking - CRITICAL for scene management
|
||
|
|
InitializeCurrentSceneTracking();
|
||
|
|
|
||
|
|
// Ensure BootstrapScene is loaded
|
||
|
|
var bootstrap = SceneManager.GetSceneByName(BootstrapSceneName);
|
||
|
|
if (!bootstrap.isLoaded)
|
||
|
|
{
|
||
|
|
SceneManager.LoadScene(BootstrapSceneName, LoadSceneMode.Additive);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void OnManagedAwake()
|
||
|
|
{
|
||
|
|
// DEPENDS on LoadingScreenController instance
|
||
|
|
_loadingScreen = LoadingScreenController.Instance;
|
||
|
|
SetupLoadingScreenEvents();
|
||
|
|
|
||
|
|
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().sceneLogVerbosity;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. InputManager (Priority 25) ✅
|
||
|
|
|
||
|
|
**Moved to Awake():**
|
||
|
|
- Verbosity settings loading
|
||
|
|
- Settings reference initialization
|
||
|
|
- PlayerInput component setup
|
||
|
|
- Input action subscriptions
|
||
|
|
- Initial input mode setup
|
||
|
|
|
||
|
|
**Kept in OnManagedAwake():**
|
||
|
|
- SceneManagerService event subscriptions (depends on SceneManagerService instance)
|
||
|
|
|
||
|
|
**Rationale:** Input system MUST be functional immediately. Event subscriptions to other managers wait until OnManagedAwake().
|
||
|
|
|
||
|
|
```csharp
|
||
|
|
private new void Awake()
|
||
|
|
{
|
||
|
|
_instance = this;
|
||
|
|
|
||
|
|
// Load settings early (GameManager sets these up in its Awake)
|
||
|
|
_logVerbosity = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().inputLogVerbosity;
|
||
|
|
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
||
|
|
|
||
|
|
// Set up PlayerInput component and actions - CRITICAL for input to work
|
||
|
|
playerInput = GetComponent<PlayerInput>();
|
||
|
|
// ... set up actions and subscriptions
|
||
|
|
|
||
|
|
// Initialize input mode for current scene
|
||
|
|
SwitchInputOnSceneLoaded(SceneManager.GetActiveScene().name);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void OnManagedAwake()
|
||
|
|
{
|
||
|
|
// DEPENDS on SceneManagerService instance
|
||
|
|
if (SceneManagerService.Instance != null)
|
||
|
|
{
|
||
|
|
SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoadCompleted;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. SaveLoadManager (Priority 20) ✅
|
||
|
|
|
||
|
|
**Moved to Awake():**
|
||
|
|
- Critical state initialization (IsSaveDataLoaded, IsRestoringState)
|
||
|
|
|
||
|
|
**Kept in OnManagedAwake():**
|
||
|
|
- Discovery of saveables
|
||
|
|
- Loading save data (depends on settings)
|
||
|
|
|
||
|
|
**Rationale:** State flags should be initialized immediately. Discovery and loading depend on settings and scene state.
|
||
|
|
|
||
|
|
```csharp
|
||
|
|
private new void Awake()
|
||
|
|
{
|
||
|
|
_instance = this;
|
||
|
|
|
||
|
|
// Initialize critical state immediately
|
||
|
|
IsSaveDataLoaded = false;
|
||
|
|
IsRestoringState = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void OnManagedAwake()
|
||
|
|
{
|
||
|
|
// Discovery and loading depend on settings and scene state
|
||
|
|
DiscoverInactiveSaveables("RestoreInEditor");
|
||
|
|
if (DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().useSaveLoadSystem)
|
||
|
|
{
|
||
|
|
Load();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5. LoadingScreenController (Priority 45) ✅
|
||
|
|
|
||
|
|
**Moved to Awake():**
|
||
|
|
- Container reference setup
|
||
|
|
- Initial state (hidden, inactive)
|
||
|
|
|
||
|
|
**Rationale:** SceneManagerService (priority 15) needs to access LoadingScreenController.Instance in its OnManagedAwake(). The loading screen MUST be properly configured before that.
|
||
|
|
|
||
|
|
```csharp
|
||
|
|
private new void Awake()
|
||
|
|
{
|
||
|
|
_instance = this;
|
||
|
|
|
||
|
|
// Set up container reference early
|
||
|
|
if (loadingScreenContainer == null)
|
||
|
|
loadingScreenContainer = gameObject;
|
||
|
|
|
||
|
|
// Ensure the loading screen is initially hidden
|
||
|
|
if (loadingScreenContainer != null)
|
||
|
|
{
|
||
|
|
loadingScreenContainer.SetActive(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 6. PauseMenu (Priority 55) ✅
|
||
|
|
|
||
|
|
**Moved to Awake():**
|
||
|
|
- CanvasGroup component setup
|
||
|
|
- Initial state (hidden, non-interactive)
|
||
|
|
|
||
|
|
**Kept in OnSceneReady():**
|
||
|
|
- Event subscriptions to SceneManagerService and UIPageController
|
||
|
|
|
||
|
|
**Rationale:** Component configuration should happen immediately. Event subscriptions wait for scene ready.
|
||
|
|
|
||
|
|
### 7. SceneOrientationEnforcer (Priority 70) ✅
|
||
|
|
|
||
|
|
**Moved to Awake():**
|
||
|
|
- Verbosity settings loading
|
||
|
|
- Scene loaded event subscription
|
||
|
|
- Initial orientation enforcement
|
||
|
|
|
||
|
|
**Rationale:** Orientation enforcement should start immediately when scenes load.
|
||
|
|
|
||
|
|
## Critical Dependencies Resolved
|
||
|
|
|
||
|
|
### Before This Review
|
||
|
|
```
|
||
|
|
SceneManagerService.OnManagedAwake() → tries to access LoadingScreenController.Instance
|
||
|
|
→ NULL if LoadingScreenController.OnManagedAwake() hasn't run yet!
|
||
|
|
```
|
||
|
|
|
||
|
|
### After This Review
|
||
|
|
```
|
||
|
|
All Awake() methods run (order doesn't matter):
|
||
|
|
- GameManager.Awake() → Sets up settings
|
||
|
|
- SceneManagerService.Awake() → Sets up scene tracking
|
||
|
|
- InputManager.Awake() → Sets up input system
|
||
|
|
- LoadingScreenController.Awake() → Sets up loading screen
|
||
|
|
- etc.
|
||
|
|
|
||
|
|
Then OnManagedAwake() runs in priority order:
|
||
|
|
- GameManager.OnManagedAwake() (10)
|
||
|
|
- SceneManagerService.OnManagedAwake() (15) → LoadingScreenController.Instance is GUARANTEED available
|
||
|
|
- InputManager.OnManagedAwake() (25) → SceneManagerService.Instance is GUARANTEED available
|
||
|
|
- etc.
|
||
|
|
```
|
||
|
|
|
||
|
|
## Design Guidelines Established
|
||
|
|
|
||
|
|
### What Goes in Awake()
|
||
|
|
1. ✅ Singleton instance assignment (`_instance = this`)
|
||
|
|
2. ✅ Critical infrastructure (settings, scene tracking)
|
||
|
|
3. ✅ Component setup (`GetComponent`, initial state)
|
||
|
|
4. ✅ State initialization that others depend on
|
||
|
|
5. ✅ Subscriptions to Unity events (SceneManager.sceneLoaded)
|
||
|
|
|
||
|
|
### What Goes in OnManagedAwake()
|
||
|
|
1. ✅ Event subscriptions to OTHER managers
|
||
|
|
2. ✅ Initialization that depends on settings
|
||
|
|
3. ✅ Non-critical setup
|
||
|
|
4. ✅ Logging (depends on settings)
|
||
|
|
|
||
|
|
### What Stays in OnSceneReady()
|
||
|
|
1. ✅ Scene-specific initialization
|
||
|
|
2. ✅ Event subscriptions that are scene-dependent
|
||
|
|
|
||
|
|
## Compilation Status
|
||
|
|
|
||
|
|
✅ **No compilation errors**
|
||
|
|
⚠️ **Only pre-existing naming convention warnings**
|
||
|
|
|
||
|
|
## Impact
|
||
|
|
|
||
|
|
### Before
|
||
|
|
- Race conditions possible if managers accessed each other's instances
|
||
|
|
- Settings might not be available when needed
|
||
|
|
- Input system might not be configured when accessed
|
||
|
|
- Loading screen might not be set up when SceneManagerService needs it
|
||
|
|
|
||
|
|
### After
|
||
|
|
- All critical infrastructure guaranteed available in OnManagedAwake()
|
||
|
|
- Settings always available for all managers
|
||
|
|
- Input system always functional
|
||
|
|
- Loading screen always configured
|
||
|
|
- Clean separation: Awake = infrastructure, OnManagedAwake = orchestration
|
||
|
|
|
||
|
|
## Testing Recommendations
|
||
|
|
|
||
|
|
1. ✅ Test boot sequence from StartingScene
|
||
|
|
2. ✅ Test level switching via LevelSwitch
|
||
|
|
3. ✅ Verify loading screen shows correctly
|
||
|
|
4. ✅ Verify input works after scene loads
|
||
|
|
5. ✅ Check console for any null reference exceptions
|
||
|
|
|
||
|
|
## Files Modified
|
||
|
|
|
||
|
|
1. GameManager.cs
|
||
|
|
2. SceneManagerService.cs
|
||
|
|
3. InputManager.cs
|
||
|
|
4. SaveLoadManager.cs
|
||
|
|
5. LoadingScreenController.cs
|
||
|
|
6. PauseMenu.cs
|
||
|
|
7. SceneOrientationEnforcer.cs
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Status**: ✅ COMPLETE - All bootstrapped managers properly initialized with correct Awake/OnManagedAwake separation
|
||
|
|
|