288 lines
9.1 KiB
C#
288 lines
9.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using AibisDream.FixSystem;
|
|
using AibisDream.Framework;
|
|
using AibisDream.Kit;
|
|
using AibisDream.Utility;
|
|
using Newtonsoft.Json.Linq;
|
|
using UnityEngine;
|
|
using Yarn.Unity;
|
|
|
|
namespace AibisDream
|
|
{
|
|
public class GameLoopManager : Singleton<GameLoopManager>
|
|
{
|
|
private const int MaxSaveNum = 200;
|
|
|
|
#region 运行模式相关
|
|
|
|
[Header("可用so合集")] public TalkSceneSO[] totalSceneSos;
|
|
|
|
public RunMode runMode;
|
|
|
|
[Header("生产环境数据(一般不动)")] public TalkSceneSO firstTalkSo;
|
|
[Header("单场景测试")] public TalkSceneSO testTalkSo;
|
|
[Header("存档测试")] public string saveFileName;
|
|
|
|
#endregion
|
|
|
|
private TalkSceneSO _currentTalkSceneSo;
|
|
|
|
public void Start()
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (runMode == RunMode.SingleScene)
|
|
{
|
|
StartMenu.Instance.HideStartMenu();
|
|
StartSingleSceneTest();
|
|
}
|
|
else if (runMode == RunMode.SaveFile)
|
|
{
|
|
// MainUIController.Instance.TVFadeOut(1);
|
|
StartMenu.Instance.HideStartMenu();
|
|
StartCoroutine(LoadSaveFile($"{TestSaveFilePath}/{saveFileName}"));
|
|
}
|
|
else
|
|
{
|
|
StartCoroutine(LoadClinicOut());
|
|
}
|
|
#else
|
|
StartCoroutine(LoadClinicOut());
|
|
runMode = RunMode.Product;
|
|
#endif
|
|
}
|
|
|
|
private IEnumerator LoadClinicOut()
|
|
{
|
|
yield return SceneLoader.Instance.LoadSceneAsync("ClinicOut");
|
|
FindObjectOfType<EnvironmentManager>().SetTimeOfDayCommand("day");
|
|
}
|
|
|
|
public void StartWithTalkSceneSO(TalkSceneSO sceneSO)
|
|
{
|
|
_currentTalkSceneSo = sceneSO;
|
|
StartCoroutine(LoadScene());
|
|
}
|
|
|
|
public void StartNewGame()
|
|
{
|
|
_currentTalkSceneSo = firstTalkSo;
|
|
StartCoroutine(LoadClinicScene());
|
|
}
|
|
|
|
private void StartSingleSceneTest()
|
|
{
|
|
_currentTalkSceneSo = testTalkSo;
|
|
StartCoroutine(LoadClinicScene());
|
|
}
|
|
|
|
private IEnumerator LoadClinicScene()
|
|
{
|
|
yield return SceneLoader.Instance.LoadSceneAsync(_currentTalkSceneSo.firstSceneName);
|
|
StartMenu.Instance.HideStartMenu();
|
|
DialogController.Instance.StartDialog(_currentTalkSceneSo.yarnProject);
|
|
}
|
|
|
|
private IEnumerator LoadScene()
|
|
{
|
|
yield return SceneLoader.Instance.LoadSceneAsync(_currentTalkSceneSo.firstSceneName);
|
|
StartMenu.Instance.HideStartMenu();
|
|
DialogController.Instance.StartDialog(_currentTalkSceneSo.yarnProject);
|
|
}
|
|
|
|
public IEnumerator NextSceneSo()
|
|
{
|
|
if (_currentTalkSceneSo && _currentTalkSceneSo.nextScene)
|
|
{
|
|
_currentTalkSceneSo = _currentTalkSceneSo.nextScene;
|
|
yield return MainUIController.Instance.FadeInSync(1);
|
|
yield return LoadClinicScene();
|
|
// yield return MainUIController.Instance.FadeOutSync(1);
|
|
}
|
|
else
|
|
{
|
|
yield return null;
|
|
Debug.Log("没有下个场景了");
|
|
}
|
|
}
|
|
|
|
#region 重新开始游戏功能
|
|
|
|
/// <summary>
|
|
/// 重新开始游戏,重新加载当前场景
|
|
/// </summary>
|
|
public void RestartGame()
|
|
{
|
|
// 确保场景正在加载或卸载前,先重置相关状态
|
|
StartCoroutine(RestartGameCoroutine());
|
|
}
|
|
|
|
private IEnumerator RestartGameCoroutine()
|
|
{
|
|
yield return SceneLoader.Instance.UnloadSceneAsync();
|
|
yield return MainUIController.Instance.FadeInSync(1);
|
|
yield return LoadClinicOut();
|
|
MainUIController.Instance.ShowMainUI();
|
|
StartMenu.Instance.showStartMenu();
|
|
StartMenu.Instance.HideEndMenu();
|
|
yield return MainUIController.Instance.FadeOutSync(1);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 存档相关
|
|
|
|
private static readonly string SaveFilePath = Application.streamingAssetsPath + "/SaveFiles";
|
|
private static readonly string TestSaveFilePath = Application.streamingAssetsPath + "/TestSaveFiles";
|
|
|
|
// 维修系统相关数据
|
|
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 savePath)
|
|
{
|
|
var saveFile = JsonUtil.ReadJObject(savePath);
|
|
// 先加载对话数据
|
|
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();
|
|
yield return FixSystemCenter.StateMachine.SwitchState(_fixState, _fixStateArgs);
|
|
|
|
// 开启对话
|
|
DialogController.Instance.LoadDialog(_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());
|
|
#if !UNITY_EDITOR
|
|
DeleteOldSave();
|
|
#endif
|
|
}
|
|
|
|
private string GetSavePath()
|
|
{
|
|
string gameStageStr;
|
|
try
|
|
{
|
|
_dialogStorage.TryGetValue("$gameStage", out float gameStage);
|
|
gameStageStr = gameStage.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_dialogStorage.TryGetValue("$gameStage", out string gameStage);
|
|
gameStageStr = gameStage;
|
|
}
|
|
|
|
return $"{SaveFilePath}/{DateTime.Now:yyyyMMdd_HHmmss}_{_currentTalkSceneSo.name}_{gameStageStr}";
|
|
}
|
|
|
|
private void DeleteOldSave()
|
|
{
|
|
var fileList = Directory.GetFiles(SaveFilePath);
|
|
if (fileList.Length > MaxSaveNum)
|
|
{
|
|
var sorted = fileList.OrderByDescending(f => f).ToArray();
|
|
for (var i = MaxSaveNum; i < fileList.Length; i++)
|
|
{
|
|
File.Delete(sorted[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public enum RunMode
|
|
{
|
|
Product,
|
|
SingleScene,
|
|
SaveFile
|
|
}
|
|
|
|
public static class GameLoopYarnCommand
|
|
{
|
|
[YarnCommand("auto_save")]
|
|
public static void AutoSave()
|
|
{
|
|
GameLoopManager.Instance.Save();
|
|
}
|
|
}
|
|
} |