diff --git a/Assets/Scenes/Persistence.unity b/Assets/Scenes/Persistence.unity index fe400857f..2405c273a 100644 --- a/Assets/Scenes/Persistence.unity +++ b/Assets/Scenes/Persistence.unity @@ -2414,7 +2414,6 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 314243162} - - component: {fileID: 314243163} m_Layer: 0 m_Name: Storage System m_TagString: Untagged @@ -2437,18 +2436,6 @@ Transform: m_Children: [] m_Father: {fileID: 1936621685} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &314243163 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 314243161} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: bd2f44edfbd942b49bb7a37f80d7a5eb, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1 &319430488 GameObject: m_ObjectHideFlags: 0 @@ -12775,12 +12762,12 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: yarnProject: {fileID: 0} - variableStorage: {fileID: 314243163} - lineProvider: {fileID: 331068880} + variableStorage: {fileID: 0} + lineProvider: {fileID: 0} saliencyStrategy: 0 dialoguePresenters: - - {fileID: 381795663} - - {fileID: 1829169897} + - {fileID: 0} + - {fileID: 0} verboseLogging: 1 autoStart: 0 startNode: Start diff --git a/Assets/Scripts/Game Loop/GameManager.cs b/Assets/Scripts/Game Loop/GameManager.cs index a10770b71..8e763b2b1 100644 --- a/Assets/Scripts/Game Loop/GameManager.cs +++ b/Assets/Scripts/Game Loop/GameManager.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using AibisDream.FixSystem; using AibisDream.Framework; using AibisDream.Kit; +using AibisDream.SaveSystem; using AibisDream.UI; using AibisDream.Utility; using UnityEngine; @@ -27,8 +28,6 @@ namespace AibisDream #endregion private BindProperty _currentTalkSceneSo; - private readonly GameLoopData _data = new(); - public override void OnSingletonInit() { LoadAllSceneSos(); @@ -38,11 +37,9 @@ namespace AibisDream { // 管理游戏开始时各部分的初始化 SettingLoader.Init(); - // 数据类注册 - StorageSystem.Instance.RegisterData(_data); + SnapshotBootstrap.EnsureInitialized(); // 场景So事件注册 _currentTalkSceneSo = new BindProperty(); - _currentTalkSceneSo.Register(item => _data.curSceneSoName = item.name); #if UNITY_EDITOR if (runMode == RunMode.SingleScene) @@ -114,7 +111,12 @@ namespace AibisDream // 游戏开始 EnumEventSystem.Global.Send(GameLoopEnum.GameStart); - StorageSystem.Instance.Load(fileName); + StartCoroutine(LoadFromSaveFile(fileName)); + } + + private IEnumerator LoadFromSaveFile(string fileName) + { + yield return SaveRestoreOrchestrator.RestoreFromFile(fileName); } private IEnumerator LoadFirstScene() @@ -270,6 +272,11 @@ namespace AibisDream DialogController.Instance.LoadDialog(_currentTalkSceneSo.Value.yarnProject); } + public TalkSceneSO GetCurrentTalkSceneSo() + { + return _currentTalkSceneSo?.Value; + } + public string GetSceneSoName() { return _currentTalkSceneSo.Value.name; @@ -336,26 +343,12 @@ namespace AibisDream #endregion } - [Serializable] - [LoadIndex(10)] - public class GameLoopData : IData - { - public string curSceneSoName; - - public IEnumerator Load() - { - GameManager.Instance.SetSceneSoByName(curSceneSoName); - GameManager.Instance.StartDialog(); - yield break; - } - } - public static class GameLoopYarnCommand { [YarnCommand("auto_save")] public static void AutoSave() { - StorageSystem.Instance.Save(); + SaveRestoreOrchestrator.SaveToTestPath(); } } diff --git a/Assets/Scripts/Game Loop/SceneLoader.cs b/Assets/Scripts/Game Loop/SceneLoader.cs index 6e1bddf22..34d039f62 100644 --- a/Assets/Scripts/Game Loop/SceneLoader.cs +++ b/Assets/Scripts/Game Loop/SceneLoader.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections; +using System.Collections; using AibisDream.Framework; using AibisDream.Kit; using AibisDream.FixSystem; @@ -19,11 +18,12 @@ namespace AibisDream private string _sceneToLoad; private bool _isLoading; - private readonly SceneData _data = new(); + private string _currentSceneName; + + public string CurrentSceneName => _currentSceneName; public override void OnSingletonInit() { - StorageSystem.Instance.RegisterData(_data); } #endregion @@ -56,7 +56,7 @@ namespace AibisDream _sceneToLoad = targetScene; // 在卸载场景前清理所有系统 - if (!string.IsNullOrEmpty(_data.sceneName)) + if (!string.IsNullOrEmpty(_currentSceneName)) { DOTween.KillAll(); @@ -79,7 +79,7 @@ namespace AibisDream // 场景加载完成,通知各系统 EnumEventSystem.Global.Send(EventEnum.SceneLoad, _sceneToLoad); - _data.sceneName = _sceneToLoad; + _currentSceneName = _sceneToLoad; UIManager.Instance.GetPanel().HideLoading(); _isLoading = false; } @@ -100,7 +100,7 @@ namespace AibisDream ResourceSystem.ReleaseSceneLoader(); yield return Addressables.UnloadSceneAsync(_loadHandle); - _data.sceneName = null; + _currentSceneName = null; } _isLoading = false; @@ -108,16 +108,4 @@ namespace AibisDream } } - [Serializable] - [LoadIndex(1)] - public class SceneData : IData - { - public string sceneName; - - public IEnumerator Load() - { - // yield return UIManager.Instance.GetPanel().FadeInAsync(); - yield return SceneLoader.Instance.LoadSceneAsync(sceneName); - } - } } \ No newline at end of file diff --git a/Assets/Scripts/Game Loop/StorageSystem.cs b/Assets/Scripts/Game Loop/StorageSystem.cs deleted file mode 100644 index a71d90653..000000000 --- a/Assets/Scripts/Game Loop/StorageSystem.cs +++ /dev/null @@ -1,368 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using AibisDream.Framework; -using AibisDream.Kit; -using AibisDream.Utility; -using AibisDream.UI; -using Newtonsoft.Json.Linq; -using UnityEngine; -using Yarn.Unity; - - -namespace AibisDream -{ - public class StorageSystem : VariableStorageBehaviour - { - private const string VariablePrefix = "$"; - private const string GlobalPrefix = "$global_"; - private const string DataPrefix = "$data."; - private const int MaxSaveNum = 200; - - #region 存储部分 - - private readonly Dictionary _variableDict = new(); - private readonly DataContainer _dataContainer = new(); - - #endregion - - #region 数据类注册和注销 - - public void RegisterData(T data) where T : IData - { - _dataContainer.Register(data); - } - - public void UnregisterData() where T : class, IData - { - _dataContainer.Unregister(); - } - - #endregion - - #region 变量设置 - - public override void SetValue(string variableName, bool boolValue) - { - SetValue(variableName, boolValue); - } - - public override void SetValue(string variableName, string stringValue) - { - SetValue(variableName, stringValue); - } - - public override void SetValue(string variableName, float floatValue) - { - SetValue(variableName, floatValue); - } - - private void SetValue(string variableName, T value) - { - var variableType = ValidateVariableName(variableName); - - if (variableType == VariableType.Illegal) - { - Debug.LogError($"{variableName}: 缺少$前缀"); - return; - } - - if (variableType == VariableType.DataField) - { - Debug.LogError($"{variableName}: 暂时不支持直接设置系统数据"); - return; - } - - // Global和Local直接设置 - _variableDict[variableName] = value; - - // 数据设置事件广播 - var variableItem = new VariableItem - { - variableName = variableName, - value = value - }; - EnumEventSystem.Global.Send(StorageEvent.VariableSet, variableItem); - } - - public override void Clear() - { - _variableDict.Clear(); - } - - public void ClearLocal() - { - // 收集所有Local类型的变量 - var locals = _variableDict.Keys.Where(item => ValidateVariableName(item) == VariableType.Local).ToArray(); - // 清除 - foreach (var localKey in locals) - { - _variableDict.Remove(localKey); - } - } - - #endregion - - #region 变量获取 - - public override bool Contains(string variableName) - { - var variableType = ValidateVariableName(variableName); - if (variableType == VariableType.Illegal) - { - return false; - } - - return variableType == VariableType.DataField - ? _dataContainer.TryGetFieldValue(variableName, out _) - : _variableDict.ContainsKey(variableName); - } - - public override bool TryGetValue(string variableName, out T result) - { - var variableType = ValidateVariableName(variableName); - // 非法的直接pass - if (variableType == VariableType.Illegal) - { - result = default; - return false; - } - - // 在系统数据中查找 - if (variableType == VariableType.DataField) - { - return _dataContainer.TryGetFieldValue(variableName, out result); - } - - // 直接查找数据 - if (_variableDict.TryGetValue(variableName, out var value)) - { - if (value is T target) - { - result = target; - return true; - } - } - - result = default; - return false; - } - - #endregion - - #region 序列化 - - public override void SetAllVariables(Dictionary floats, Dictionary strings, - Dictionary bools, bool clear = true) - { - if (clear) - { - Clear(); - } - - foreach (var value in floats) - { - SetValue(value.Key, value.Value); - } - - foreach (var value in strings) - { - SetValue(value.Key, value.Value); - } - - foreach (var value in bools) - { - SetValue(value.Key, value.Value); - } - } - - public override (Dictionary FloatVariables, Dictionary StringVariables, - Dictionary BoolVariables) GetAllVariables() - { - var floatDict = new Dictionary(); - var stringDict = new Dictionary(); - var boolDict = new Dictionary(); - - foreach (var variablePair in _variableDict) - { - switch (variablePair.Value) - { - case float: - { - var value = Convert.ToSingle(variablePair.Value); - floatDict.Add(variablePair.Key, value); - break; - } - case string: - { - var value = Convert.ToString(variablePair.Value); - stringDict.Add(variablePair.Key, value); - break; - } - case bool: - { - var value = Convert.ToBoolean(variablePair.Value); - boolDict.Add(variablePair.Key, value); - break; - } - default: - Debug.Log($"{variablePair.Key} is not a valid type"); - break; - } - } - - return (floatDict, stringDict, boolDict); - } - - #endregion - - #region 保存/加载 - - public void Save() - { - ActionKit.Sequence() - .Callback(() => UIManager.Instance.GetPanel().ShowSaveLoading()) - .Delay(1f) - .Callback(() => UIManager.Instance.GetPanel().HideSaveLoading()) - .Start(this); - - using (new CodeTimer("Save")) - { - // 先序列化Yarn变量 - var saveFile = new JObject(); - - // 保存版本号 - saveFile["version"] = $"Ver.{Application.version}"; - saveFile["time"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); - - // 保存系统数据 - saveFile["systemData"] = _dataContainer.SaveAsJson(); - - // 保存对话变量 - var (floatDict, stringDict, boolDict) = GetAllVariables(); - saveFile["floatDict"] = JObject.FromObject(floatDict); - saveFile["stringDict"] = JObject.FromObject(stringDict); - saveFile["boolDict"] = JObject.FromObject(boolDict); - - // 存为Json - JsonUtil.SaveJObject(saveFile, GetSavePath()); -#if !UNITY_EDITOR - DeleteOldSave(); -#endif - } - } - - private void DeleteOldSave() - { - if (Directory.Exists(ConstRef.SaveFilePath)) - { - var fileList = Directory.GetFiles(ConstRef.SaveFilePath); - if (fileList.Length > MaxSaveNum) - { - var sorted = fileList.OrderByDescending(f => f).ToArray(); - for (var i = MaxSaveNum; i < fileList.Length; i++) - { - File.Delete(sorted[i]); - } - } - } - else - { - Directory.CreateDirectory(ConstRef.SaveFilePath); - } - } - - public void Load(string savePath) - { - // 先将存档文件转为JObject - var saveData = JsonUtil.ReadJObject(savePath); - // 加载Yarn数据 - var floatDict = saveData["floatDict"]?.ToObject>(); - var stringDict = saveData["stringDict"]?.ToObject>(); - var boolDict = saveData["boolDict"]?.ToObject>(); - SetAllVariables(floatDict, stringDict, boolDict); - - // 加载系统数据 - if (saveData["systemData"] is not JObject systemDataJson) - { - Debug.Log("维修数据读取问题"); - return; - } - - StartCoroutine(_dataContainer.LoadByJson(systemDataJson)); - } - - private string GetSavePath() - { - Directory.CreateDirectory(ConstRef.SaveFilePath); - - string gameStage; - if (TryGetValue("$gameStage", out float gameStageFloat)) - { - gameStage = gameStageFloat.ToString(CultureInfo.InvariantCulture); - } - else - { - TryGetValue("$gameStage", out string gameStageStr); - gameStage = gameStageStr; - } - - return - $"{ConstRef.SaveFilePath}/{DateTime.Now:yyyyMMdd-HHmmss}_{GameManager.Instance.GetSceneSoName()}_{gameStage}"; - } - - #endregion - - private static VariableType ValidateVariableName(string variableName) - { - if (string.IsNullOrWhiteSpace(variableName) || !variableName.StartsWith(VariablePrefix)) - { - return VariableType.Illegal; - } - - if (variableName.StartsWith(GlobalPrefix)) - { - return VariableType.Global; - } - - if (variableName.StartsWith(DataPrefix)) - { - return VariableType.DataField; - } - - return VariableType.Local; - } - - #region 单例部分 - - public static StorageSystem Instance { get; private set; } - - private void Awake() - { - if (Instance != null) - { - Destroy(gameObject); - } - - Instance = this; - } - - #endregion - } - - public enum VariableType - { - Local, - Global, - DataField, - Illegal - } - - public struct VariableItem - { - public string variableName; - public object value; - } -} \ No newline at end of file diff --git a/Assets/Scripts/Game Loop/StorageSystem.cs.meta b/Assets/Scripts/Game Loop/StorageSystem.cs.meta deleted file mode 100644 index 8d87d35be..000000000 --- a/Assets/Scripts/Game Loop/StorageSystem.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: bd2f44edfbd942b49bb7a37f80d7a5eb -timeCreated: 1742802488 \ No newline at end of file