feat: 增强存档管理,优化异步存档逻辑,添加错误处理机制
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Events;
|
||||
@@ -32,7 +33,16 @@ namespace BaseGames.Core.Save
|
||||
if (_timer >= _intervalSeconds)
|
||||
{
|
||||
_timer = 0f;
|
||||
_ = _saveManager.SaveAsync(EmergencySlot);
|
||||
RunFireAndForget(_saveManager.SaveAsync(EmergencySlot), "EmergencySave");
|
||||
}
|
||||
}
|
||||
|
||||
private static async void RunFireAndForget(System.Threading.Tasks.Task task, string context)
|
||||
{
|
||||
try { await task; }
|
||||
catch (Exception e)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"[EmergencySave] {context} 失败: {e.Message}\n{e.StackTrace}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,12 +88,13 @@ namespace BaseGames.Core.Save
|
||||
_current.Meta.SlotIndex = targetSlot;
|
||||
_current.Meta.SaveCount++;
|
||||
|
||||
// 先清空 checksum,序列化并计算,再序列化含 checksum 的最终版本
|
||||
// 使用 Formatting.None 减少序列化字符串体积和 GC 分配
|
||||
// 清空 checksum 后序列化,计算 HMAC,然后直接注入序列化字符串——避免第二次完整序列化。
|
||||
// Base64 字符集(A-Z a-z 0-9 + / =)不含需要 JSON 转义的字符,string.Replace 是安全替换。
|
||||
_current.Meta.Checksum = null;
|
||||
string jsonForChecksum = JsonConvert.SerializeObject(_current, Formatting.None);
|
||||
_current.Meta.Checksum = ComputeChecksum(jsonForChecksum);
|
||||
string finalJson = JsonConvert.SerializeObject(_current, Formatting.None);
|
||||
string checksum = ComputeChecksum(jsonForChecksum);
|
||||
string finalJson = jsonForChecksum.Replace("\"Checksum\":null", $"\"Checksum\":\"{checksum}\"");
|
||||
_current.Meta.Checksum = checksum; // 同步回内存,保持对象一致
|
||||
|
||||
await _storage.WriteAsync(targetSlot, finalJson);
|
||||
|
||||
|
||||
@@ -128,8 +128,7 @@ namespace BaseGames.Core.Save
|
||||
[Serializable]
|
||||
public class QuestSaveData
|
||||
{
|
||||
public Dictionary<string, QuestState> QuestStates = new();
|
||||
public List<string> AvailableQuestIds = new();
|
||||
public Dictionary<string, QuestState> QuestStates = new();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
||||
@@ -50,10 +50,7 @@ namespace BaseGames.Core.Save
|
||||
// 2.2 删除 PlayerSaveData.ShieldHP / ShieldIsBroken(护盾在存档点始终全满,无需持久化)。
|
||||
// SettingsSaveData.Language 字段保留(由 LocalizationManager 负责按存档槽读写)。
|
||||
// 旧存档中已删除的字段由 Newtonsoft.Json 的 [JsonExtensionData] 忽略,无需额外处理。
|
||||
// Equipment.MaxNotches:旧存档若为 0,EquipmentManager.OnLoad 回退到初始 Notch 数量。
|
||||
if (data.Equipment != null && data.Equipment.MaxNotches == 0)
|
||||
data.Equipment.MaxNotches = 0; // 保持 0,OnLoad 回退到 config.initialNotchCount
|
||||
|
||||
// Equipment.MaxNotches:旧存档若为 0,EquipmentManager.OnLoad 回退到 config.initialNotchCount,无需额外处理。
|
||||
Debug.Log("[SaveMigrator] 从 '2.1' 迁移至 '2.2'。");
|
||||
v = "2.2";
|
||||
}
|
||||
|
||||
@@ -129,7 +129,6 @@ namespace BaseGames.Quest
|
||||
public void OnSave(SaveData data)
|
||||
{
|
||||
data.Quests.QuestStates.Clear();
|
||||
data.Quests.AvailableQuestIds.Clear();
|
||||
foreach (var (id, state) in _questStates)
|
||||
{
|
||||
data.Quests.QuestStates[id] = new BaseGames.Core.Save.QuestState
|
||||
@@ -138,7 +137,6 @@ namespace BaseGames.Quest
|
||||
ObjectiveIndex = 0,
|
||||
ProgressCounts = BuildProgressList(id),
|
||||
};
|
||||
if (state == QuestStateEnum.Available) data.Quests.AvailableQuestIds.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using BaseGames.Core;
|
||||
using BaseGames.Core.Events;
|
||||
@@ -68,7 +70,7 @@ namespace BaseGames.World
|
||||
// 触发存档:OnSave() 由 SaveAsync 回调所有 ISaveable,包含本组件
|
||||
var svc = ServiceLocator.GetOrDefault<ISaveService>();
|
||||
if (svc != null)
|
||||
_ = svc.SaveAsync(svc.ActiveSlot);
|
||||
RunFireAndForget(svc.SaveAsync(svc.ActiveSlot));
|
||||
else
|
||||
Debug.LogWarning("[SavePoint] ISaveService 未注册,跳过存档。", this);
|
||||
}
|
||||
@@ -101,6 +103,14 @@ namespace BaseGames.World
|
||||
_isActivated = !string.IsNullOrEmpty(_savePointId)
|
||||
&& data.World.ActivatedSavePoints.Contains(_savePointId);
|
||||
}
|
||||
|
||||
private static async void RunFireAndForget(Task task)
|
||||
{
|
||||
try { await task; }
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[SavePoint] 存档失败: {e.Message}\n{e.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user