Minor reset fixes

This commit is contained in:
Michal Pikulski
2025-11-05 20:36:13 +01:00
parent 0791616772
commit c5a5e4a96b
4 changed files with 69 additions and 10 deletions

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -242,6 +242,35 @@ namespace Core.SaveLoad
return currentSaveData.unlockedMinigames.AsReadOnly(); return currentSaveData.unlockedMinigames.AsReadOnly();
} }
/// <summary>
/// Clears all save data for a specific level/scene.
/// Removes all participant states that belong to the specified scene.
/// Useful for "restart level" functionality to wipe progress.
/// </summary>
/// <param name="sceneName">The name of the scene to clear data for</param>
public void ClearLevelData(string sceneName)
{
if (string.IsNullOrEmpty(sceneName))
{
Logging.Warning("[SaveLoadManager] Cannot clear level data - scene name is null or empty");
return;
}
if (currentSaveData == null || currentSaveData.participantStates == null)
{
Logging.Warning("[SaveLoadManager] Cannot clear level data - no save data loaded");
return;
}
// SaveId format is "SceneName/ObjectName/ComponentType"
// Remove all entries that start with "sceneName/"
string scenePrefix = $"{sceneName}/";
int removedCount = currentSaveData.participantStates.RemoveAll(entry =>
entry.saveId.StartsWith(scenePrefix));
Logging.Debug($"[SaveLoadManager] Cleared {removedCount} save entries for level: {sceneName}");
}
#endregion #endregion
#region State Restoration #region State Restoration

View File

@@ -283,9 +283,9 @@ namespace Core
// Tracks the currently loaded gameplay scene (not persistent/bootstrapper) // Tracks the currently loaded gameplay scene (not persistent/bootstrapper)
public string CurrentGameplayScene { get; set; } = "AppleHillsOverworld"; public string CurrentGameplayScene { get; set; } = "AppleHillsOverworld";
public async Task ReloadCurrentScene(IProgress<float> progress = null, bool autoHideLoadingScreen = true) public async Task ReloadCurrentScene(IProgress<float> progress = null, bool autoHideLoadingScreen = true, bool skipSave = false)
{ {
await SwitchSceneAsync(CurrentGameplayScene, progress, autoHideLoadingScreen); await SwitchSceneAsync(CurrentGameplayScene, progress, autoHideLoadingScreen, skipSave);
} }
/// <summary> /// <summary>
@@ -294,7 +294,8 @@ namespace Core
/// <param name="newSceneName">Name of the scene to load</param> /// <param name="newSceneName">Name of the scene to load</param>
/// <param name="progress">Optional progress reporter</param> /// <param name="progress">Optional progress reporter</param>
/// <param name="autoHideLoadingScreen">Whether to automatically hide the loading screen when complete. If false, caller must hide it manually.</param> /// <param name="autoHideLoadingScreen">Whether to automatically hide the loading screen when complete. If false, caller must hide it manually.</param>
public async Task SwitchSceneAsync(string newSceneName, IProgress<float> progress = null, bool autoHideLoadingScreen = true) /// <param name="skipSave">If true, skips saving scene data during transition. Useful for level restart to prevent re-saving cleared data.</param>
public async Task SwitchSceneAsync(string newSceneName, IProgress<float> progress = null, bool autoHideLoadingScreen = true, bool skipSave = false)
{ {
string oldSceneName = CurrentGameplayScene; string oldSceneName = CurrentGameplayScene;
@@ -309,8 +310,8 @@ namespace Core
LogDebugMessage($"Broadcasting OnSceneUnloading for: {oldSceneName}"); LogDebugMessage($"Broadcasting OnSceneUnloading for: {oldSceneName}");
LifecycleManager.Instance?.BroadcastSceneUnloading(oldSceneName); LifecycleManager.Instance?.BroadcastSceneUnloading(oldSceneName);
// PHASE 3: Save scene-specific data via SaveLoadManager // PHASE 3: Save scene-specific data via SaveLoadManager (unless skipSave is true)
if (SaveLoadManager.Instance != null) if (!skipSave && SaveLoadManager.Instance != null)
{ {
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>(); var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
if (debugSettings.useSaveLoadSystem) if (debugSettings.useSaveLoadSystem)
@@ -319,6 +320,10 @@ namespace Core
SaveLoadManager.Instance.SaveSceneData(); SaveLoadManager.Instance.SaveSceneData();
} }
} }
else if (skipSave)
{
LogDebugMessage($"Skipping save for: {oldSceneName} (skipSave=true)");
}
// PHASE 5: Remove all AstarPath (A* Pathfinder) singletons before loading the new scene // PHASE 5: Remove all AstarPath (A* Pathfinder) singletons before loading the new scene
var astarPaths = FindObjectsByType<AstarPath>(FindObjectsSortMode.None); var astarPaths = FindObjectsByType<AstarPath>(FindObjectsSortMode.None);
@@ -364,7 +369,7 @@ namespace Core
LifecycleManager.Instance?.BroadcastSceneReady(newSceneName); LifecycleManager.Instance?.BroadcastSceneReady(newSceneName);
// PHASE 11: Restore scene-specific data via SaveLoadManager // PHASE 11: Restore scene-specific data via SaveLoadManager
if (SaveLoadManager.Instance != null) if (!skipSave && SaveLoadManager.Instance != null)
{ {
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>(); var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
if (debugSettings.useSaveLoadSystem) if (debugSettings.useSaveLoadSystem)
@@ -373,6 +378,10 @@ namespace Core
SaveLoadManager.Instance.RestoreSceneData(); SaveLoadManager.Instance.RestoreSceneData();
} }
} }
else if (skipSave)
{
LogDebugMessage($"Skipping restore for: {newSceneName} (skipSave=true)");
}
// PHASE 12: Only hide the loading screen if autoHideLoadingScreen is true // PHASE 12: Only hide the loading screen if autoHideLoadingScreen is true
if (autoHideLoadingScreen && _loadingScreen != null) if (autoHideLoadingScreen && _loadingScreen != null)

View File

@@ -128,8 +128,16 @@ namespace Levels
private async void OnRestartSelected() private async void OnRestartSelected()
{ {
// TODO: Restart level here // Clear all save data for the target level before reloading
await OnLevelSelected(); if (Core.SaveLoad.SaveLoadManager.Instance != null && !string.IsNullOrEmpty(switchData?.targetLevelSceneName))
{
Core.SaveLoad.SaveLoadManager.Instance.ClearLevelData(switchData.targetLevelSceneName);
Logging.Debug($"[LevelSwitch] Cleared save data for level: {switchData.targetLevelSceneName}");
}
// Now reload the level with fresh state - skipSave=true prevents re-saving cleared data
var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%"));
await SceneManagerService.Instance.SwitchSceneAsync(switchData.targetLevelSceneName, progress, autoHideLoadingScreen: true, skipSave: true);
} }
private void OnMenuCancel() private void OnMenuCancel()

View File

@@ -1,5 +1,6 @@
using System; using System;
using Core; using Core;
using Core.SaveLoad;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using UI.Core; using UI.Core;
@@ -294,8 +295,20 @@ namespace UI
public async void ReloadLevel() public async void ReloadLevel()
{ {
// Clear all save data for the current gameplay level before reloading
if (SaveLoadManager.Instance != null && SceneManagerService.Instance != null)
{
string currentLevel = SceneManagerService.Instance.CurrentGameplayScene;
if (!string.IsNullOrEmpty(currentLevel))
{
SaveLoadManager.Instance.ClearLevelData(currentLevel);
Logging.Debug($"[PauseMenu] Cleared save data for current level: {currentLevel}");
}
}
// Now reload the current scene with fresh state - skipSave=true prevents re-saving cleared data
var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%")); var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%"));
await SceneManagerService.Instance.ReloadCurrentScene(progress); await SceneManagerService.Instance.ReloadCurrentScene(progress, autoHideLoadingScreen: true, skipSave: true);
} }
/// <summary> /// <summary>