using System; using System.Collections; using System.Collections.Generic; using System.Linq; using AibisDream.FixSystem; using AibisDream.Framework; using AibisDream.Kit; using AibisDream.Utility; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using Yarn.Unity; namespace AibisDream { public class GameManager : Singleton, IGameManager { #region 运行模式相关 private TalkSceneSO[] _totalSceneSos; public RunMode runMode; [Header("生产环境数据(一般不动)")] public TalkSceneSO firstTalkSo; [Header("单场景测试")] public TalkSceneSO testTalkSo; [Header("存档测试")] public string saveFileName; #endregion private BindProperty _currentTalkSceneSo; private readonly GameLoopData _data = new(); private void Start() { // 管理游戏开始时各部分的初始化 SettingLoader.Init(); // 数据类注册 StorageSystem.Instance.RegisterData(_data); // 场景So事件注册 _currentTalkSceneSo = new BindProperty(); _currentTalkSceneSo.Register(item => _data.curSceneSoName = item.name); // 事件广播 EnumEventSystem.Global.Send(GameLoopEnum.AppStart); // 加载SO Addressables.LoadAssetsAsync("SceneSO", null).Completed += LoadTalkSo; #if UNITY_EDITOR if (runMode == RunMode.SingleScene) { StartWithLevel(testTalkSo); } else if (runMode == RunMode.SaveFile) { StartWithSaveFile($"{ConstRef.TestSaveFilePath}/{saveFileName}"); } else { ActionKit.Sequence() .Callback(() => UIManager.Instance.GetPanel().FadeInSync(0)) .Coroutine(() => SceneLoader.Instance.LoadSceneAsync("ClinicOut")) .Callback(() => UIManager.Instance.GetPanel().FadeOutSync()) .Start(this); } #else SceneLoader.Instance.LoadScene("ClinicOut"); runMode = RunMode.Product; #endif } private void LoadTalkSo(AsyncOperationHandle> handle) { if (handle.Status == AsyncOperationStatus.Succeeded) { _totalSceneSos = handle.Result.ToArray(); } else { Debug.LogError("Failed to load textures."); } } #region 游戏循环 public void StartNewGame() { // 游戏开始 EnumEventSystem.Global.Send(GameLoopEnum.GameStart); // 重置屏幕效果 ScreenEffectManager.Instance?.ResetSaturation(); // 序列 _currentTalkSceneSo.Value = firstTalkSo; StartCoroutine(LoadFirstScene()); } public void StartWithLevel(TalkSceneSO sceneSo) { // 游戏开始 EnumEventSystem.Global.Send(GameLoopEnum.GameStart); // 重置屏幕效果 ScreenEffectManager.Instance?.ResetSaturation(); _currentTalkSceneSo.Value = sceneSo; StartCoroutine(LoadFirstScene()); } public void StartWithSaveFile(string fileName) { // 游戏开始 EnumEventSystem.Global.Send(GameLoopEnum.GameStart); StorageSystem.Instance.Load(fileName); } private IEnumerator LoadFirstScene() { yield return UIManager.Instance.GetPanel().FadeInAsync(0.5f); yield return SceneLoader.Instance.LoadSceneAsync(_currentTalkSceneSo.Value.firstSceneName); DialogController.Instance.StartDialog(_currentTalkSceneSo.Value.yarnProject); } public void PauseGame() { // 系统暂停 Time.timeScale = 0; // 交互继续 EnumEventSystem.Global.Send(GameLoopEnum.PauseGame); // 音频全部暂停 AudioManager.Instance.PauseAll(); // 关闭Dialog DialogCanvasManager.Instance.CloseCanvas(); } public void ContinueGame() { // 系统继续 Time.timeScale = 1; // 交互继续 EnumEventSystem.Global.Send(GameLoopEnum.UnPauseGame); // 音频继续 AudioManager.Instance.UnPauseAll(); // 打开Dialog DialogCanvasManager.Instance.OpenCanvas(); } public void QuitGame() { // 系统继续 Time.timeScale = 1; // 重置屏幕效果 ScreenEffectManager.Instance?.ResetSaturation(); // 卸载当前场景 StartCoroutine(RestartCoroutine()); } public void QuitApp() { Application.Quit(); } private IEnumerator RestartCoroutine() { UIManager.Instance.GetPanel().FadeInSync(0.1f); // 清理所有系统注册 if (FixSystemCenter.SystemDic != null) { FixSystemCenter.SystemDic.Clear(); } // 执行场景切换等功能 CameraKit.Instance.ResetCamera(); yield return SceneLoader.Instance.LoadSceneAsync("ClinicOut"); DialogController.Instance.StopDialog(); EnumEventSystem.Global.Send(GameLoopEnum.GameQuit); // 音频继续 AudioManager.Instance.UnPauseAll(); // 打开Dialog DialogCanvasManager.Instance.OpenCanvas(); yield return UIManager.Instance.GetPanel().FadeOutAsync(); } #endregion #region 分辨率与屏幕模式 public void SetScreenMode(string windowMode) { switch (windowMode) { case "FullScreen": Screen.SetResolution(Screen.currentResolution.width, Screen.currentResolution.height, FullScreenMode.FullScreenWindow); break; case "Windowed": Screen.SetResolution(1920, 1080, FullScreenMode.Windowed); break; case "MaximizedWindow": Screen.SetResolution(Screen.currentResolution.width, Screen.currentResolution.height, FullScreenMode.MaximizedWindow); break; default: Debug.Log($"{windowMode} err"); break; } } #endregion public IEnumerator NextSceneSo() { if (_currentTalkSceneSo.Value && _currentTalkSceneSo.Value.nextScene) { _currentTalkSceneSo.Value = _currentTalkSceneSo.Value.nextScene; yield return UIManager.Instance.GetPanel().FadeInAsync(); yield return SceneLoader.Instance.LoadSceneAsync(_currentTalkSceneSo.Value.firstSceneName); DialogController.Instance.StartDialog(_currentTalkSceneSo.Value.yarnProject); } else { yield return null; Debug.Log("没有下个场景了"); } } public void SetSceneSoByName(string soName) { _currentTalkSceneSo.Value = Array.Find(_totalSceneSos, so => so.name == soName); } public void StartDialog() { DialogController.Instance.LoadDialog(_currentTalkSceneSo.Value.yarnProject); } public string GetSceneSoName() { return _currentTalkSceneSo.Value.name; } } /// /// GameManager应该包含什么功能? /// 1. 游戏状态管理。开始/暂停/结束 /// 2. 全局设置 即SettingLoader /// 3. 场景管理 有SceneLoader类,暂无必要 /// 4. 资源管理 似无必要 /// 5. 时间管理 主要供暂停使用 /// 6. 日志和调试 日志已有 /// public interface IGameManager { #region 游戏循环相关 public void StartNewGame(); public void PauseGame(); public void ContinueGame(); public void QuitGame(); public void QuitApp(); #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(); } } public enum RunMode { Product, SingleScene, SaveFile } }