Files
AppleHillsProduction/docs/save_system_architecture.md

112 lines
3.4 KiB
Markdown
Raw Normal View History

# Save System Architecture
**Project:** AppleHills
**Date:** November 3, 2025
---
## Critical Decision: All Save Data is Level-Specific
**IMPORTANT:** In AppleHills, **ALL save data is level-specific**. There is no global persistent save data that carries across all levels.
### What This Means
-**DO NOT use ISaveParticipant pattern** for new components
-**DO use OnSaveRequested() / OnRestoreRequested() lifecycle hooks** instead
- ✅ All save/load operations are tied to the current level/scene
### Migration Impact
For existing components that implement ISaveParticipant:
- **Remove ISaveParticipant interface** implementation
- **Remove SaveLoadManager.RegisterParticipant()** calls
- **Add OnSaveRequested()** override to save level-specific state
- **Add OnRestoreRequested()** override to restore level-specific state
- **Use SaveLoadManager's existing save/load system** within these hooks
### Examples
#### ❌ OLD Pattern (Don't use)
```csharp
public class PuzzleManager : MonoBehaviour, ISaveParticipant
{
void Awake()
{
BootCompletionService.RegisterInitAction(() => {
SaveLoadManager.Instance.RegisterParticipant(this);
});
}
public string GetSaveId() => "PuzzleManager";
public string Save()
{
return JsonUtility.ToJson(puzzleState);
}
public void Restore(string data)
{
puzzleState = JsonUtility.FromJson<PuzzleState>(data);
}
}
```
#### ✅ NEW Pattern (Use this)
```csharp
public class PuzzleManager : ManagedBehaviour
{
protected override int ManagedAwakePriority => 120;
protected override void OnSaveRequested()
{
// Save level-specific puzzle state
string saveData = JsonUtility.ToJson(puzzleState);
SaveLoadManager.Instance.SaveLevelData("PuzzleManager", saveData);
}
protected override void OnRestoreRequested()
{
// Restore level-specific puzzle state
string saveData = SaveLoadManager.Instance.LoadLevelData("PuzzleManager");
if (!string.IsNullOrEmpty(saveData))
{
puzzleState = JsonUtility.FromJson<PuzzleState>(saveData);
}
}
}
```
### Components Affected by This Decision
All components that currently use ISaveParticipant:
1. PuzzleManager - puzzle state per level
2. PlayerTouchController - player position/state per level
3. FollowerController - follower state per level
4. CardSystemManager - card collection per level
5. SaveableInteractable - interactable state per level
6. AppleMachine - apple machine state per level
**All of these will be migrated to use OnSaveRequested/OnRestoreRequested instead of ISaveParticipant.**
---
## SaveLoadManager Integration
The SaveLoadManager will continue to work as before, but components will interact with it through lifecycle hooks:
### Lifecycle Flow
1. **Before scene unloads:** `LifecycleManager.BroadcastSaveRequested(sceneName)`
- All ManagedBehaviours in that scene get `OnSaveRequested()` called
- Each component saves its level-specific data via SaveLoadManager
2. **SaveLoadManager.Save()** called to persist all level data
3. **Scene unloads**
4. **New scene loads**
5. **After scene loads:** `LifecycleManager.BroadcastRestoreRequested(sceneName)`
- All ManagedBehaviours in that scene get `OnRestoreRequested()` called
- Each component restores its level-specific data from SaveLoadManager
---
**End of Document**