存档功能

This commit is contained in:
2025-01-08 11:41:20 +08:00
parent c67366664c
commit 43b99f98e7
49 changed files with 2498 additions and 5762 deletions
+143 -30
View File
@@ -1,5 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using AibisDream.FixSystem;
using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.Utility;
using Newtonsoft.Json.Linq;
using UnityEngine;
using Yarn.Unity;
@@ -7,42 +13,50 @@ namespace AibisDream
{
public class GameLoopManager : Singleton<GameLoopManager>
{
[Header("运行模式")]
[SerializeField]
private RunMode runMode;
#region
[Header("正式环境参数")]
[SerializeField] private TalkSceneSO firstTalkSo;
[Header("可用so合集")]
public TalkSceneSO[] totalSceneSos;
public RunMode runMode;
[Header("生产环境数据(一般不动)")] public TalkSceneSO firstTalkSo;
[Header("单场景测试")] public TalkSceneSO testTalkSo;
[Header("存档测试")] public string saveFileName;
#endregion
private TalkSceneSO _currentTalkSceneSo;
[SerializeField]
private string clinicScene;
[Header("测试环境参数")]
[SerializeField] private string testYarnProject;
public void Start()
{
if (runMode == RunMode.Test)
#if UNITY_EDITOR
if (runMode == RunMode.SingleScene)
{
MainUIController.Instance.TVFadeOut(1);
GameObject.Find("Menu Canvas").SetActive(false);
StartCoroutine(StartTestGame());
StartSingleSceneTest();
}
else if (runMode == RunMode.SaveFile)
{
MainUIController.Instance.TVFadeOut(1);
GameObject.Find("Menu Canvas").SetActive(false);
StartCoroutine(LoadSaveFile(saveFileName));
}
#else
runMode = RunMode.Product;
#endif
}
public void StartNewGame()
{
_currentTalkSceneSo = firstTalkSo;
StartCoroutine(LoadClinicScene());
}
public void StartNewGame(TalkSceneSO sceneSo)
private void StartSingleSceneTest()
{
_currentTalkSceneSo = sceneSo;
_currentTalkSceneSo = testTalkSo;
StartCoroutine(LoadClinicScene());
}
@@ -53,15 +67,6 @@ namespace AibisDream
DialogController.Instance.StartDialog(_currentTalkSceneSo.yarnProject);
}
public IEnumerator StartTestGame()
{
// TODO 全部改好之后这里要直接进入FixScene
yield return null;
//yield return SceneLoader.Instance.LoadSceneAsync(clinicScene);
var proj = Resources.Load<YarnProject>($"Yarn/{testYarnProject}/{testYarnProject}");
DialogController.Instance.StartDialog(proj);
}
public IEnumerator NextSceneSo()
{
if (_currentTalkSceneSo && _currentTalkSceneSo.nextScene)
@@ -77,11 +82,119 @@ namespace AibisDream
Debug.Log("没有下个场景了");
}
}
#region
private static readonly string SaveFilePath = Application.streamingAssetsPath + "/SaveFiles";
// 维修系统相关数据
public static readonly DataContainer FixDataContainer = new();
// 对话变量存储
private VariableStorageBehaviour _dialogStorage;
// 当前场景
private string _curSceneKey;
// 状态机
private string _fixStateArgs;
private FixState _fixState;
public override void OnSingletonInit()
{
_dialogStorage = FindObjectOfType<VariableStorageBehaviour>();
}
/// <summary>
/// 当前场景自行更新
/// </summary>
/// <param name="sceneName">当前scene</param>
public void UpdateCurScene(string sceneName)
{
_curSceneKey = sceneName;
}
/// <summary>
/// 状态机状态更新
/// </summary>
/// <param name="curState"></param>
/// <param name="curArgs"></param>
public void UpdateFixState(FixState curState, string curArgs)
{
_fixState = curState;
_fixStateArgs = curArgs;
}
private IEnumerator LoadSaveFile(string saveName)
{
var saveFile = JsonUtil.ReadJObject($"{SaveFilePath}/{saveName}");
// 先加载对话数据
var floatDict = saveFile["floatDict"]?.ToObject<Dictionary<string, float>>();
var stringDict = saveFile["stringDict"]?.ToObject<Dictionary<string, string>>();
var boolDict = saveFile["boolDict"]?.ToObject<Dictionary<string, bool>>();
_dialogStorage.SetAllVariables(floatDict, stringDict, boolDict);
// 再加载场景
_currentTalkSceneSo = Array.Find(totalSceneSos, so => so.name == saveFile["curTalkSceneSo"]?.ToString());
yield return SceneLoader.Instance.LoadSceneAsync(saveFile["curSceneKey"]?.ToString());
if (saveFile["fixDataContainer"] is not JObject fixDataJson)
{
Debug.Log("维修数据读取问题");
yield break;
}
// 场景加载完成之后把数据填回去
FixDataContainer.LoadByJson(fixDataJson);
// 初始化维修状态机
_fixState = saveFile["fixState"]!.ToObject<FixState>();
_fixStateArgs = saveFile["fixStateArgs"]!.ToString();
FixSystemCenter.StateMachine.SwitchState(_fixState, _fixStateArgs);
// 开启对话
DialogController.Instance.StartDialog(_currentTalkSceneSo.yarnProject);
}
public void Save()
{
JObject saveFile = new JObject();
// 场景维修相关数据保存
var fixData = FixDataContainer.SaveAsJson();
saveFile["fixDataContainer"] = fixData;
// 保存对话变量
var (floatDict, stringDict, boolDict) = _dialogStorage.GetAllVariables();
saveFile["floatDict"] = JObject.FromObject(floatDict);
saveFile["stringDict"] = JObject.FromObject(stringDict);
saveFile["boolDict"] = JObject.FromObject(boolDict);
// 保存场景数据
saveFile["curSceneKey"] = _curSceneKey;
saveFile["curTalkSceneSo"] = _currentTalkSceneSo.name;
// 保存状态机数据
saveFile["fixState"] = (int) _fixState;
saveFile["fixStateArgs"] = _fixStateArgs;
// 存为Json
JsonUtil.SaveJObject(saveFile, GetSavePath());
}
private string GetSavePath()
{
_dialogStorage.TryGetValue("$gameStage", out float gameStage);
return $"{SaveFilePath}/{_currentTalkSceneSo.name}_{gameStage}_{DateTime.Now:yyyyMMdd_HHmmss}";
}
#endregion
}
public enum RunMode
{
Test, Pro, FixTest
Product,
SingleScene,
SaveFile
}
}
}
+27 -28
View File
@@ -1,5 +1,5 @@
using System;
using System.Collections;
using AibisDream.Framework;
using AibisDream.Kit;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
@@ -11,17 +11,21 @@ namespace AibisDream
{
#region
private string currentScene;
private BindProperty<string> _currentScene;
private AsyncOperationHandle _loadHandle;
private string sceneToLoad;
private bool isLoading;
#endregion
#region
public event Action LoadSceneEvent;
public event Action UnloadSceneEvent;
private string _sceneToLoad;
private bool _isLoading;
public override void OnSingletonInit()
{
_currentScene = new BindProperty<string>();
_currentScene.Register(GameLoopManager.Instance.UpdateCurScene);
}
public override void OnSingletonDestroy()
{
_currentScene.UnRegister(GameLoopManager.Instance.UpdateCurScene);
}
#endregion
@@ -41,50 +45,45 @@ namespace AibisDream
/// <returns></returns>
public IEnumerator LoadSceneAsync(string targetScene)
{
if (isLoading)
if (_isLoading)
{
yield return null;
}
else
{
// 场景转换参数
isLoading = true;
sceneToLoad = targetScene;
if (currentScene != null)
_isLoading = true;
_sceneToLoad = targetScene;
if (string.IsNullOrEmpty(_currentScene.Value))
{
UnloadSceneEvent?.Invoke();
yield return Addressables.UnloadSceneAsync(_loadHandle);
}
_loadHandle = Addressables.LoadSceneAsync(sceneToLoad, LoadSceneMode.Additive);
_loadHandle = Addressables.LoadSceneAsync(_sceneToLoad, LoadSceneMode.Additive);
yield return _loadHandle;
LoadSceneEvent?.Invoke();
currentScene = sceneToLoad;
isLoading = false;
_currentScene.Value = _sceneToLoad;
_isLoading = false;
}
}
public IEnumerator UnloadSceneAsync(string sceneToUnload)
{
if (isLoading)
if (_isLoading)
{
yield return null;
}
else
{
isLoading = true;
_isLoading = true;
if (currentScene == sceneToUnload)
if (_currentScene.Value == sceneToUnload)
{
UnloadSceneEvent?.Invoke();
yield return Addressables.UnloadSceneAsync(_loadHandle, true);
currentScene = null;
_currentScene.Value = null;
}
isLoading = false;
_isLoading = false;
}
}
}
-34
View File
@@ -14,8 +14,6 @@ namespace AibisDream {
[SerializeField] private GameObject startTab;
[SerializeField] private GameObject levelTab;
[SerializeField] private TalkSceneSO[] talkSceneSoArray;
[SerializeField] private GameObject buttonPrefab;
private void OnEnable()
@@ -40,38 +38,6 @@ namespace AibisDream {
public void SelectLevel()
{
SwitchToLevelTab();
// 生成关卡按钮
GeneLevelButtons();
}
private void GeneLevelButtons()
{
// 销毁原来的按钮
foreach (Transform child in levelTab.transform)
{
if (child.gameObject.name == "Suggestion")
{
continue;
}
Destroy(child.gameObject);
}
// 生成新按钮
for (int i = 0; i < talkSceneSoArray.Length; i++)
{
var tempButton = Instantiate(buttonPrefab, levelTab.transform);
tempButton.GetComponent<TextMeshProUGUI>().text = $"第{i + 1}关";
var idx = i;
tempButton.GetComponent<Button>().onClick.AddListener(() =>
{
GameLoopManager.Instance.StartNewGame(talkSceneSoArray[idx]);
});
}
// 生成返回按钮
var returnButton = Instantiate(buttonPrefab, levelTab.transform);
returnButton.GetComponent<TextMeshProUGUI>().text = "返回";
returnButton.GetComponent<Button>().onClick.AddListener(SwitchToStartTab);
}
private void SwitchToLevelTab()