605 lines
17 KiB
Markdown
605 lines
17 KiB
Markdown
|
|
# SceneManagerService Independent Review & Migration Opportunities
|
||
|
|
|
||
|
|
**Date:** November 4, 2025
|
||
|
|
**Reviewer:** AI Assistant
|
||
|
|
**Context:** Post-BootCompletionService migration, lifecycle system fully operational
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Executive Summary
|
||
|
|
|
||
|
|
SceneManagerService is currently **partially integrated** with the lifecycle system but is **missing critical lifecycle orchestration** as outlined in the roadmap. The service manages scene loading/unloading effectively but doesn't broadcast lifecycle events to ManagedBehaviour components during scene transitions.
|
||
|
|
|
||
|
|
**Key Finding:** ⚠️ **Phase 3 of the roadmap (Scene Orchestration) was never implemented**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Part 1: SceneManagerService Review
|
||
|
|
|
||
|
|
### Current State Analysis
|
||
|
|
|
||
|
|
#### ✅ **Strengths**
|
||
|
|
|
||
|
|
1. **ManagedBehaviour Migration Complete**
|
||
|
|
- Inherits from ManagedBehaviour ✅
|
||
|
|
- Priority: 15 (core infrastructure) ✅
|
||
|
|
- Uses OnManagedAwake() properly ✅
|
||
|
|
- Removed BootCompletionService dependency ✅
|
||
|
|
|
||
|
|
2. **Solid Event-Driven Architecture**
|
||
|
|
- 6 public events for scene lifecycle
|
||
|
|
- Clean async/await pattern
|
||
|
|
- Progress reporting support
|
||
|
|
- Loading screen integration
|
||
|
|
|
||
|
|
3. **Good Scene Management Features**
|
||
|
|
- Additive scene loading
|
||
|
|
- Multi-scene support
|
||
|
|
- Bootstrap scene tracking
|
||
|
|
- Current scene tracking
|
||
|
|
|
||
|
|
#### ⚠️ **Critical Gaps**
|
||
|
|
|
||
|
|
1. **Missing Lifecycle Orchestration**
|
||
|
|
- ❌ Does NOT call `LifecycleManager.BroadcastSceneUnloading()`
|
||
|
|
- ❌ Does NOT call `LifecycleManager.BroadcastSaveRequested()`
|
||
|
|
- ❌ Does NOT call `LifecycleManager.BroadcastSceneReady()`
|
||
|
|
- ❌ Does NOT call `LifecycleManager.BroadcastRestoreRequested()`
|
||
|
|
|
||
|
|
2. **No Save/Load Integration**
|
||
|
|
- Scene transitions don't trigger automatic saves
|
||
|
|
- No restoration hooks after scene load
|
||
|
|
- SaveLoadManager not invoked during transitions
|
||
|
|
|
||
|
|
3. **Incomplete Scene Transition Flow**
|
||
|
|
```csharp
|
||
|
|
// CURRENT (Incomplete):
|
||
|
|
SwitchSceneAsync() {
|
||
|
|
1. Show loading screen
|
||
|
|
2. Destroy AstarPath
|
||
|
|
3. Unload old scene
|
||
|
|
4. Load new scene
|
||
|
|
5. Hide loading screen
|
||
|
|
}
|
||
|
|
|
||
|
|
// MISSING (Per Roadmap Phase 3):
|
||
|
|
SwitchSceneAsync() {
|
||
|
|
1. Show loading screen
|
||
|
|
2. BroadcastSceneUnloading(oldScene) ❌ MISSING
|
||
|
|
3. BroadcastSaveRequested(oldScene) ❌ MISSING
|
||
|
|
4. SaveLoadManager.Save() ❌ MISSING
|
||
|
|
5. Destroy AstarPath
|
||
|
|
6. Unload old scene (Unity OnDestroy)
|
||
|
|
7. Load new scene
|
||
|
|
8. BroadcastSceneReady(newScene) ❌ MISSING
|
||
|
|
9. BroadcastRestoreRequested(newScene) ❌ MISSING
|
||
|
|
10. Hide loading screen
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 📊 **Code Quality Assessment**
|
||
|
|
|
||
|
|
**Good:**
|
||
|
|
- Clean separation of concerns
|
||
|
|
- Well-documented public API
|
||
|
|
- Null safety checks
|
||
|
|
- Proper async handling
|
||
|
|
- DontDestroyOnLoad handled correctly
|
||
|
|
|
||
|
|
**Could Improve:**
|
||
|
|
- Add lifecycle orchestration (critical)
|
||
|
|
- Integrate SaveLoadManager
|
||
|
|
- Add scene validation before transitions
|
||
|
|
- Consider cancellation token support
|
||
|
|
- Add scene transition state tracking
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Recommended Changes to SceneManagerService
|
||
|
|
|
||
|
|
#### Priority 1: Add Lifecycle Orchestration (Critical)
|
||
|
|
|
||
|
|
**Location:** `SwitchSceneAsync()` method
|
||
|
|
|
||
|
|
**Changes Needed:**
|
||
|
|
```csharp
|
||
|
|
public async Task SwitchSceneAsync(string newSceneName, IProgress<float> progress = null, bool autoHideLoadingScreen = true)
|
||
|
|
{
|
||
|
|
// PHASE 1: Show loading screen
|
||
|
|
if (_loadingScreen != null && !_loadingScreen.IsActive)
|
||
|
|
{
|
||
|
|
_loadingScreen.ShowLoadingScreen();
|
||
|
|
}
|
||
|
|
|
||
|
|
string oldSceneName = CurrentGameplayScene;
|
||
|
|
|
||
|
|
// PHASE 2: Broadcast scene unloading (NEW)
|
||
|
|
LogDebugMessage($"Broadcasting scene unloading for: {oldSceneName}");
|
||
|
|
LifecycleManager.Instance?.BroadcastSceneUnloading(oldSceneName);
|
||
|
|
|
||
|
|
// PHASE 3: Broadcast save request (NEW)
|
||
|
|
LogDebugMessage($"Broadcasting save request for: {oldSceneName}");
|
||
|
|
LifecycleManager.Instance?.BroadcastSaveRequested(oldSceneName);
|
||
|
|
|
||
|
|
// PHASE 4: Trigger global save (NEW)
|
||
|
|
if (SaveLoadManager.Instance != null &&
|
||
|
|
DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>().useSaveLoadSystem)
|
||
|
|
{
|
||
|
|
LogDebugMessage("Saving global game state");
|
||
|
|
SaveLoadManager.Instance.Save();
|
||
|
|
}
|
||
|
|
|
||
|
|
// PHASE 5: Cleanup (existing)
|
||
|
|
var astarPaths = FindObjectsByType<AstarPath>(FindObjectsSortMode.None);
|
||
|
|
foreach (var astar in astarPaths)
|
||
|
|
{
|
||
|
|
if (Application.isPlaying)
|
||
|
|
Destroy(astar.gameObject);
|
||
|
|
else
|
||
|
|
DestroyImmediate(astar.gameObject);
|
||
|
|
}
|
||
|
|
|
||
|
|
// PHASE 6: Unload old scene (existing)
|
||
|
|
if (!string.IsNullOrEmpty(oldSceneName) && oldSceneName != BootstrapSceneName)
|
||
|
|
{
|
||
|
|
var prevScene = SceneManager.GetSceneByName(oldSceneName);
|
||
|
|
if (prevScene.isLoaded)
|
||
|
|
{
|
||
|
|
await UnloadSceneAsync(oldSceneName);
|
||
|
|
// Unity automatically calls OnDestroy → OnManagedDestroy()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// PHASE 7: Ensure bootstrap loaded (existing)
|
||
|
|
var bootstrap = SceneManager.GetSceneByName(BootstrapSceneName);
|
||
|
|
if (!bootstrap.isLoaded)
|
||
|
|
{
|
||
|
|
SceneManager.LoadScene(BootstrapSceneName, LoadSceneMode.Additive);
|
||
|
|
}
|
||
|
|
|
||
|
|
// PHASE 8: Load new scene (existing)
|
||
|
|
await LoadSceneAsync(newSceneName, progress);
|
||
|
|
CurrentGameplayScene = newSceneName;
|
||
|
|
|
||
|
|
// PHASE 9: Broadcast scene ready (NEW)
|
||
|
|
LogDebugMessage($"Broadcasting scene ready for: {newSceneName}");
|
||
|
|
LifecycleManager.Instance?.BroadcastSceneReady(newSceneName);
|
||
|
|
|
||
|
|
// PHASE 10: Broadcast restore request (NEW)
|
||
|
|
LogDebugMessage($"Broadcasting restore request for: {newSceneName}");
|
||
|
|
LifecycleManager.Instance?.BroadcastRestoreRequested(newSceneName);
|
||
|
|
|
||
|
|
// PHASE 11: Hide loading screen (existing)
|
||
|
|
if (autoHideLoadingScreen && _loadingScreen != null)
|
||
|
|
{
|
||
|
|
_loadingScreen.HideLoadingScreen();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Impact:** 🔴 **HIGH** - Critical for proper lifecycle integration
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Part 2: Components Depending on Scene Loading Events
|
||
|
|
|
||
|
|
### Analysis Results
|
||
|
|
|
||
|
|
I found **6 components** that currently subscribe to SceneManagerService events. Here's the breakdown:
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Component 1: **PauseMenu** ✅ Already Using Lifecycle
|
||
|
|
|
||
|
|
**Current Implementation:**
|
||
|
|
```csharp
|
||
|
|
protected override void OnSceneReady()
|
||
|
|
{
|
||
|
|
SceneManagerService.Instance.SceneLoadCompleted += SetPauseMenuByLevel;
|
||
|
|
// ...
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Status:** ✅ **ALREADY OPTIMAL**
|
||
|
|
- Uses OnSceneReady() hook
|
||
|
|
- Subscribes to SceneLoadCompleted for per-scene visibility logic
|
||
|
|
- **No migration needed** - dual approach is appropriate here
|
||
|
|
|
||
|
|
**Rationale:** PauseMenu needs to know about EVERY scene load (not just transitions), so event subscription is correct.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Component 2: **QuickAccess** ⚠️ Should Migrate to Lifecycle
|
||
|
|
|
||
|
|
**File:** `Assets/Scripts/Core/QuickAccess.cs`
|
||
|
|
|
||
|
|
**Current Implementation:**
|
||
|
|
```csharp
|
||
|
|
public class QuickAccess : MonoBehaviour // ← Not ManagedBehaviour!
|
||
|
|
{
|
||
|
|
private void Awake()
|
||
|
|
{
|
||
|
|
_instance = this;
|
||
|
|
|
||
|
|
if (!_initialized)
|
||
|
|
{
|
||
|
|
if (SceneManager != null)
|
||
|
|
{
|
||
|
|
SceneManager.SceneLoadCompleted += OnSceneLoadCompleted;
|
||
|
|
}
|
||
|
|
_initialized = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnSceneLoadCompleted(string sceneName)
|
||
|
|
{
|
||
|
|
ClearReferences(); // Invalidates cached GameObjects
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Issues:**
|
||
|
|
- ❌ Not using ManagedBehaviour
|
||
|
|
- ❌ Manual event subscription in Awake
|
||
|
|
- ❌ No automatic cleanup
|
||
|
|
- ❌ Uses event for scene transitions
|
||
|
|
|
||
|
|
**Recommended Migration:**
|
||
|
|
```csharp
|
||
|
|
public class QuickAccess : ManagedBehaviour
|
||
|
|
{
|
||
|
|
public override int ManagedAwakePriority => 5; // Very early
|
||
|
|
|
||
|
|
protected override void OnManagedAwake()
|
||
|
|
{
|
||
|
|
_instance = this;
|
||
|
|
_initialized = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void OnSceneUnloading(string sceneName)
|
||
|
|
{
|
||
|
|
// Clear references BEFORE scene unloads
|
||
|
|
ClearReferences();
|
||
|
|
}
|
||
|
|
|
||
|
|
// REMOVE: Awake() method
|
||
|
|
// REMOVE: OnSceneLoadCompleted() method
|
||
|
|
// REMOVE: SceneLoadCompleted subscription
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Benefits:**
|
||
|
|
- ✅ Automatic cleanup (no manual unsubscribe)
|
||
|
|
- ✅ Clear references at proper time (before unload, not after load)
|
||
|
|
- ✅ Consistent with lifecycle pattern
|
||
|
|
- ✅ One less event subscription
|
||
|
|
|
||
|
|
**Impact:** 🟡 **MEDIUM** - Improves cleanup timing and consistency
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Component 3: **CardSystemSceneVisibility** ✅ Already Migrated
|
||
|
|
|
||
|
|
**File:** `Assets/Scripts/UI/CardSystem/CardSystemSceneVisibility.cs`
|
||
|
|
|
||
|
|
**Current Implementation:**
|
||
|
|
```csharp
|
||
|
|
protected override void OnSceneReady()
|
||
|
|
{
|
||
|
|
// Replaces SceneLoadCompleted subscription
|
||
|
|
SetVisibilityForScene(sceneName);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Status:** ✅ **ALREADY MIGRATED**
|
||
|
|
- Uses OnSceneReady() lifecycle hook
|
||
|
|
- No event subscription
|
||
|
|
- **No action needed**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Component 4: **PuzzleManager** ✅ Already Migrated
|
||
|
|
|
||
|
|
**File:** `Assets/Scripts/PuzzleS/PuzzleManager.cs`
|
||
|
|
|
||
|
|
**Current Implementation:**
|
||
|
|
```csharp
|
||
|
|
protected override void OnSceneReady()
|
||
|
|
{
|
||
|
|
// Replaces SceneLoadCompleted subscription
|
||
|
|
string sceneName = SceneManagerService.Instance.CurrentGameplayScene;
|
||
|
|
OnSceneLoadCompleted(sceneName);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void OnSceneLoadCompleted(string sceneName)
|
||
|
|
{
|
||
|
|
// Load puzzle data for scene
|
||
|
|
// ...
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Status:** ✅ **ALREADY MIGRATED**
|
||
|
|
- Uses OnSceneReady() lifecycle hook
|
||
|
|
- Method renamed but could be cleaned up
|
||
|
|
- **Minor cleanup recommended** (rename OnSceneLoadCompleted → LoadPuzzlesForScene)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Component 5: **InputManager** ✅ Already Migrated
|
||
|
|
|
||
|
|
**File:** `Assets/Scripts/Input/InputManager.cs`
|
||
|
|
|
||
|
|
**Current Implementation:**
|
||
|
|
```csharp
|
||
|
|
protected override void OnSceneReady()
|
||
|
|
{
|
||
|
|
// Replaces SceneLoadCompleted subscription
|
||
|
|
UpdateInputModeForScene();
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Status:** ✅ **ALREADY MIGRATED**
|
||
|
|
- Uses OnSceneReady() lifecycle hook
|
||
|
|
- **No action needed**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Component 6: **ItemManager** ✅ Already Migrated
|
||
|
|
|
||
|
|
**File:** `Assets/Scripts/Core/ItemManager.cs`
|
||
|
|
|
||
|
|
**Current Implementation:**
|
||
|
|
```csharp
|
||
|
|
protected override void OnSceneUnloading(string sceneName)
|
||
|
|
{
|
||
|
|
// Replaces SceneLoadStarted subscription for clearing registrations
|
||
|
|
ClearItemRegistrations();
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Status:** ✅ **ALREADY MIGRATED**
|
||
|
|
- Uses OnSceneUnloading() lifecycle hook
|
||
|
|
- **No action needed**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Component 7: **SaveLoadManager** ⚠️ Has Orphaned Methods
|
||
|
|
|
||
|
|
**File:** `Assets/Scripts/Core/SaveLoad/SaveLoadManager.cs`
|
||
|
|
|
||
|
|
**Current Implementation:**
|
||
|
|
```csharp
|
||
|
|
protected override void OnSceneReady()
|
||
|
|
{
|
||
|
|
// Replaces SceneLoadCompleted event subscription
|
||
|
|
string sceneName = SceneManagerService.Instance.CurrentGameplayScene;
|
||
|
|
OnSceneLoadCompleted(sceneName);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnSceneLoadCompleted(string sceneName)
|
||
|
|
{
|
||
|
|
// Restore global save data
|
||
|
|
// ...
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnSceneUnloadStarted(string sceneName)
|
||
|
|
{
|
||
|
|
// Save global data before unload
|
||
|
|
// ...
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Issues:**
|
||
|
|
- ⚠️ Has `OnSceneUnloadStarted()` method but doesn't override `OnSceneUnloading()`
|
||
|
|
- ⚠️ Should use `OnSaveRequested()` instead of custom method
|
||
|
|
- ⚠️ Method naming inconsistent with lifecycle pattern
|
||
|
|
|
||
|
|
**Recommended Changes:**
|
||
|
|
```csharp
|
||
|
|
protected override void OnSceneReady()
|
||
|
|
{
|
||
|
|
string sceneName = SceneManagerService.Instance.CurrentGameplayScene;
|
||
|
|
RestoreGlobalData(sceneName); // Renamed for clarity
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void OnSaveRequested(string sceneName)
|
||
|
|
{
|
||
|
|
// Replaces OnSceneUnloadStarted
|
||
|
|
SaveGlobalData(sceneName);
|
||
|
|
}
|
||
|
|
|
||
|
|
// REMOVE: OnSceneLoadCompleted() - rename to RestoreGlobalData()
|
||
|
|
// REMOVE: OnSceneUnloadStarted() - replace with OnSaveRequested()
|
||
|
|
```
|
||
|
|
|
||
|
|
**Impact:** 🟡 **MEDIUM** - Cleanup and consistency
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Part 3: Migration Summary & Recommendations
|
||
|
|
|
||
|
|
### Components Needing Migration
|
||
|
|
|
||
|
|
| Component | Current State | Action Required | Priority | Estimated Time |
|
||
|
|
|-----------|---------------|-----------------|----------|----------------|
|
||
|
|
| **SceneManagerService** | Missing lifecycle broadcasts | Add lifecycle orchestration | 🔴 **CRITICAL** | 30 min |
|
||
|
|
| **QuickAccess** | MonoBehaviour, uses events | Migrate to ManagedBehaviour | 🟡 **MEDIUM** | 20 min |
|
||
|
|
| **SaveLoadManager** | Has orphaned methods | Cleanup and use lifecycle hooks | 🟡 **MEDIUM** | 15 min |
|
||
|
|
| **PuzzleManager** | Minor naming issue | Rename method | 🟢 **LOW** | 5 min |
|
||
|
|
|
||
|
|
**Total Estimated Time:** ~70 minutes
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Migration Benefits
|
||
|
|
|
||
|
|
#### After Full Migration:
|
||
|
|
|
||
|
|
1. **Proper Scene Lifecycle Flow**
|
||
|
|
```
|
||
|
|
Scene Transition Triggers:
|
||
|
|
1. OnSceneUnloading() - Components clean up
|
||
|
|
2. OnSaveRequested() - Save level-specific data
|
||
|
|
3. SaveLoadManager.Save() - Save global data
|
||
|
|
4. [Scene Unload] - Unity OnDestroy
|
||
|
|
5. [Scene Load] - Unity Awake
|
||
|
|
6. OnSceneReady() - Components initialize
|
||
|
|
7. OnRestoreRequested() - Restore level-specific data
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Fewer Event Subscriptions**
|
||
|
|
- Current: 7 event subscriptions across 6 components
|
||
|
|
- After: 1 event subscription (PauseMenu only)
|
||
|
|
- Reduction: ~86%
|
||
|
|
|
||
|
|
3. **Consistent Pattern**
|
||
|
|
- All components use lifecycle hooks
|
||
|
|
- Clear separation: boot vs scene lifecycle
|
||
|
|
- Predictable execution order
|
||
|
|
|
||
|
|
4. **Automatic Cleanup**
|
||
|
|
- No manual event unsubscription
|
||
|
|
- ManagedBehaviour handles cleanup
|
||
|
|
- Fewer memory leak opportunities
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Part 4: Detailed Implementation Plan
|
||
|
|
|
||
|
|
### Step 1: Update SceneManagerService (30 min) 🔴 **CRITICAL**
|
||
|
|
|
||
|
|
**Priority:** Must do this first - enables all other migrations
|
||
|
|
|
||
|
|
**Changes:**
|
||
|
|
1. Add lifecycle broadcasts to `SwitchSceneAsync()`
|
||
|
|
2. Integrate SaveLoadManager.Save() call
|
||
|
|
3. Add debug logging for lifecycle events
|
||
|
|
4. Test scene transitions thoroughly
|
||
|
|
|
||
|
|
**Testing:**
|
||
|
|
- Verify lifecycle order in console logs
|
||
|
|
- Check save/load triggers correctly
|
||
|
|
- Ensure OnSceneReady fires after scene fully loaded
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Step 2: Migrate QuickAccess (20 min) 🟡 **MEDIUM**
|
||
|
|
|
||
|
|
**Changes:**
|
||
|
|
1. Change base class to ManagedBehaviour
|
||
|
|
2. Set priority to 5 (very early)
|
||
|
|
3. Override OnManagedAwake()
|
||
|
|
4. Override OnSceneUnloading() for cleanup
|
||
|
|
5. Remove Awake() and event subscription
|
||
|
|
6. Test reference caching works
|
||
|
|
|
||
|
|
**Testing:**
|
||
|
|
- Verify references cached correctly
|
||
|
|
- Check clearing happens before scene unload
|
||
|
|
- Ensure singleton works across scenes
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Step 3: Cleanup SaveLoadManager (15 min) 🟡 **MEDIUM**
|
||
|
|
|
||
|
|
**Changes:**
|
||
|
|
1. Rename `OnSceneLoadCompleted()` → `RestoreGlobalData()`
|
||
|
|
2. Replace `OnSceneUnloadStarted()` with `OnSaveRequested()` override
|
||
|
|
3. Update method documentation
|
||
|
|
4. Verify save/load flow
|
||
|
|
|
||
|
|
**Testing:**
|
||
|
|
- Test global data saves before scene unload
|
||
|
|
- Verify restoration after scene load
|
||
|
|
- Check ISaveParticipant integration
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Step 4: Minor Cleanups (5 min) 🟢 **LOW**
|
||
|
|
|
||
|
|
**PuzzleManager:**
|
||
|
|
- Rename `OnSceneLoadCompleted()` → `LoadPuzzlesForScene()`
|
||
|
|
- Update documentation
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Part 5: Risk Assessment
|
||
|
|
|
||
|
|
### Low Risk ✅
|
||
|
|
- PauseMenu, CardSystemSceneVisibility, InputManager, ItemManager already migrated
|
||
|
|
- Lifecycle system battle-tested from previous migrations
|
||
|
|
|
||
|
|
### Medium Risk ⚠️
|
||
|
|
- **SceneManagerService changes** - Critical path, test thoroughly
|
||
|
|
- **QuickAccess migration** - Used throughout codebase, verify references work
|
||
|
|
- **SaveLoadManager cleanup** - Save/load is critical, extensive testing needed
|
||
|
|
|
||
|
|
### Mitigation Strategies
|
||
|
|
1. **Test after each migration** - Don't batch changes
|
||
|
|
2. **Use git checkpoints** - Commit after each component
|
||
|
|
3. **Playtest thoroughly** - Full game loop after SceneManagerService update
|
||
|
|
4. **Keep backups** - Copy methods before deleting
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Part 6: Next Steps Recommendation
|
||
|
|
|
||
|
|
### Immediate Actions (This Session)
|
||
|
|
|
||
|
|
**Option A: Full Migration (Recommended)**
|
||
|
|
1. ✅ Update SceneManagerService with lifecycle orchestration (30 min)
|
||
|
|
2. ✅ Migrate QuickAccess to ManagedBehaviour (20 min)
|
||
|
|
3. ✅ Cleanup SaveLoadManager (15 min)
|
||
|
|
4. ✅ Test thoroughly (30 min)
|
||
|
|
**Total: ~95 minutes**
|
||
|
|
|
||
|
|
**Option B: Critical Path Only**
|
||
|
|
1. ✅ Update SceneManagerService only (30 min)
|
||
|
|
2. ✅ Test scene transitions (20 min)
|
||
|
|
3. ⏸️ Defer other migrations
|
||
|
|
**Total: ~50 minutes**
|
||
|
|
|
||
|
|
**Option C: Review Only**
|
||
|
|
- ✅ This document completed
|
||
|
|
- ⏸️ Wait for user approval before proceeding
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Part 7: Expected Outcomes
|
||
|
|
|
||
|
|
### After Complete Migration:
|
||
|
|
|
||
|
|
**Architecture:**
|
||
|
|
- ✅ Scene transitions fully orchestrated by LifecycleManager
|
||
|
|
- ✅ Automatic save/load during scene transitions
|
||
|
|
- ✅ All components use lifecycle hooks consistently
|
||
|
|
- ✅ Event subscriptions minimized (7 → 1)
|
||
|
|
|
||
|
|
**Developer Experience:**
|
||
|
|
- ✅ Clear lifecycle flow for debugging
|
||
|
|
- ✅ Predictable initialization order
|
||
|
|
- ✅ Less manual cleanup code
|
||
|
|
- ✅ Consistent patterns across codebase
|
||
|
|
|
||
|
|
**Performance:**
|
||
|
|
- ✅ Fewer active event subscriptions
|
||
|
|
- ✅ Better memory management
|
||
|
|
- ✅ No change in frame time (lifecycle is event-driven)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Conclusion
|
||
|
|
|
||
|
|
**Key Finding:** SceneManagerService is missing the critical lifecycle orchestration outlined in **Phase 3 of the roadmap**. This is the final piece needed to complete the lifecycle system implementation.
|
||
|
|
|
||
|
|
**Recommendation:** Implement SceneManagerService lifecycle orchestration (Step 1) immediately. This unlocks the full potential of the lifecycle system and completes the architectural vision from the roadmap.
|
||
|
|
|
||
|
|
**Next Action:** Await user approval to proceed with implementation.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Review Completed:** November 4, 2025
|
||
|
|
**Status:** Ready for implementation
|
||
|
|
**Estimated Total Time:** 70-95 minutes
|
||
|
|
|