First go around with save load system

This commit is contained in:
Michal Pikulski
2025-11-02 12:48:48 +01:00
parent 5d6d4c8ba1
commit ebca297d28
13 changed files with 1511 additions and 122 deletions

View File

@@ -244,5 +244,36 @@ namespace Core
public IEnumerable<Pickup> Pickups => _pickups;
public IEnumerable<ItemSlot> ItemSlots => _itemSlots;
/// <summary>
/// Gets all registered pickups. Used by save/load system to find items by save ID.
/// </summary>
public IEnumerable<Pickup> GetAllPickups() => _pickups;
/// <summary>
/// Gets all registered item slots. Used by save/load system.
/// </summary>
public IEnumerable<ItemSlot> GetAllItemSlots() => _itemSlots;
/// <summary>
/// Finds a pickup by its save ID. Used by save/load system to restore item references.
/// </summary>
/// <param name="saveId">The save ID to search for</param>
/// <returns>The pickup's GameObject if found, null otherwise</returns>
public GameObject FindPickupBySaveId(string saveId)
{
if (string.IsNullOrEmpty(saveId)) return null;
// Search through all registered pickups
foreach (var pickup in _pickups)
{
if (pickup is SaveableInteractable saveable && saveable.GetSaveId() == saveId)
{
return pickup.gameObject;
}
}
return null;
}
}
}

View File

@@ -23,6 +23,12 @@
/// Should handle null/empty data gracefully with default behavior.
/// </summary>
void RestoreState(string serializedData);
/// <summary>
/// Returns true if this participant has already had its state restored.
/// Used to prevent double-restoration when inactive objects become active.
/// </summary>
bool HasBeenRestored { get; }
}
}

View File

@@ -48,7 +48,7 @@ namespace Core.SaveLoad
private void Start()
{
Load();
}
private void OnApplicationQuit()
@@ -67,6 +67,12 @@ namespace Core.SaveLoad
SceneManagerService.Instance.SceneUnloadStarted += OnSceneUnloadStarted;
Logging.Debug("[SaveLoadManager] Subscribed to SceneManagerService events");
}
#if UNITY_EDITOR
OnSceneLoadCompleted("RestoreInEditor");
#endif
Load();
}
void OnDestroy()
@@ -114,7 +120,8 @@ namespace Core.SaveLoad
Logging.Debug($"[SaveLoadManager] Registered participant: {saveId}");
// If we have save data loaded and we're not currently restoring, restore this participant's state immediately
if (IsSaveDataLoaded && !IsRestoringState && currentSaveData != null)
// BUT only if the participant hasn't already been restored (prevents double-restoration when inactive objects become active)
if (IsSaveDataLoaded && !IsRestoringState && currentSaveData != null && !participant.HasBeenRestored)
{
RestoreParticipantState(participant);
}
@@ -153,10 +160,28 @@ namespace Core.SaveLoad
private void OnSceneLoadCompleted(string sceneName)
{
Logging.Debug($"[SaveLoadManager] Scene '{sceneName}' loaded. Participants can now register and will be restored.");
Logging.Debug($"[SaveLoadManager] Scene '{sceneName}' loaded. Discovering inactive SaveableInteractables...");
// Participants register themselves, so we just wait for them
// After registration, they'll be automatically restored if data is available
// Find ONLY INACTIVE SaveableInteractables (active ones will register themselves via Start())
var inactiveSaveables = FindObjectsByType(
typeof(Interactions.SaveableInteractable),
FindObjectsInactive.Include,
FindObjectsSortMode.None
);
int registeredCount = 0;
foreach (var obj in inactiveSaveables)
{
var saveable = obj as Interactions.SaveableInteractable;
if (saveable != null && !saveable.gameObject.activeInHierarchy)
{
// Only register if it's actually inactive
RegisterParticipant(saveable);
registeredCount++;
}
}
Logging.Debug($"[SaveLoadManager] Discovered and registered {registeredCount} inactive SaveableInteractables");
}
private void OnSceneUnloadStarted(string sceneName)