363 lines
11 KiB
C#
363 lines
11 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using AibisDream.FixSystem;
|
|
using AibisDream.Framework;
|
|
using AibisDream.Kit;
|
|
using AibisDream.UI;
|
|
using AibisDream.Utility;
|
|
using UnityEngine;
|
|
using UnityEngine.AddressableAssets;
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
using Yarn.Unity;
|
|
|
|
namespace AibisDream
|
|
{
|
|
public class GameManager : Singleton<GameManager>, IGameManager
|
|
{
|
|
#region 运行模式相关
|
|
|
|
public GameLoopState state;
|
|
|
|
private TalkSceneSO[] _totalSceneSos;
|
|
|
|
public RunMode runMode;
|
|
|
|
[Header("生产环境数据(一般不动)")] public TalkSceneSO firstTalkSo;
|
|
[Header("单场景测试")] public TalkSceneSO testTalkSo;
|
|
[Header("存档测试")] public string saveFileName;
|
|
|
|
#endregion
|
|
|
|
private BindProperty<TalkSceneSO> _currentTalkSceneSo;
|
|
private readonly GameLoopData _data = new();
|
|
|
|
private void Start()
|
|
{
|
|
// 管理游戏开始时各部分的初始化
|
|
SettingLoader.Init();
|
|
// 数据类注册
|
|
StorageSystem.Instance.RegisterData(_data);
|
|
// 场景So事件注册
|
|
_currentTalkSceneSo = new BindProperty<TalkSceneSO>();
|
|
_currentTalkSceneSo.Register(item => _data.curSceneSoName = item.name);
|
|
// 事件广播
|
|
EnumEventSystem.Global.Send(GameLoopEnum.AppStart);
|
|
// 加载SO
|
|
Addressables.LoadAssetsAsync<TalkSceneSO>("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<PlayToolPanel>().FadeInSync(0))
|
|
.Coroutine(() => SceneLoader.Instance.LoadSceneAsync("ClinicOut"))
|
|
.Callback(() => UIManager.Instance.GetPanel<PlayToolPanel>().FadeOutSync())
|
|
.Start(this);
|
|
}
|
|
#else
|
|
SceneLoader.Instance.LoadScene("ClinicOut");
|
|
runMode = RunMode.Product;
|
|
#endif
|
|
}
|
|
|
|
private void LoadTalkSo(AsyncOperationHandle<IList<TalkSceneSO>> 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()
|
|
{
|
|
ChapterController.Instance.UnlockChapter(_currentTalkSceneSo.Value);
|
|
yield return UIManager.Instance.GetPanel<PlayToolPanel>().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
|
|
DialogUIManager.Instance.CloseCanvas();
|
|
}
|
|
|
|
public void ContinueGame()
|
|
{
|
|
// 系统继续
|
|
Time.timeScale = 1;
|
|
// 交互继续
|
|
EnumEventSystem.Global.Send(GameLoopEnum.UnPauseGame);
|
|
// 音频继续
|
|
AudioManager.Instance.UnPauseAll();
|
|
// 打开Dialog
|
|
DialogUIManager.Instance.OpenCanvas();
|
|
}
|
|
|
|
public void QuitGame()
|
|
{
|
|
// 系统继续
|
|
Time.timeScale = 1;
|
|
// 重置屏幕效果
|
|
ScreenEffectManager.Instance?.ResetSaturation();
|
|
// 卸载当前场景
|
|
StartCoroutine(RestartCoroutine());
|
|
}
|
|
|
|
public void QuitApp()
|
|
{
|
|
Application.Quit();
|
|
}
|
|
|
|
private IEnumerator RestartCoroutine()
|
|
{
|
|
UIManager.Instance.GetPanel<PlayToolPanel>().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
|
|
DialogUIManager.Instance.OpenCanvas();
|
|
|
|
yield return UIManager.Instance.GetPanel<PlayToolPanel>().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;
|
|
}
|
|
|
|
ActionKit.DelayFrame(1, () => CameraKit.Instance.UpdateCameraViewport(windowMode == "Windowed"))
|
|
.StartGlobal();
|
|
}
|
|
|
|
#endregion
|
|
|
|
public IEnumerator NextSceneSo()
|
|
{
|
|
if (_currentTalkSceneSo.Value && _currentTalkSceneSo.Value.nextScene)
|
|
{
|
|
_currentTalkSceneSo.Value = _currentTalkSceneSo.Value.nextScene;
|
|
ChapterController.Instance.UnlockChapter(_currentTalkSceneSo.Value);
|
|
yield return UIManager.Instance.GetPanel<PlayToolPanel>().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;
|
|
}
|
|
|
|
#region 事件处理
|
|
|
|
private IUnRegister[] _unRegisters;
|
|
|
|
private void OnEnable()
|
|
{
|
|
RegisterEvents();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
UnRegisterEvents();
|
|
}
|
|
|
|
private void RegisterEvents()
|
|
{
|
|
_unRegisters = new IUnRegister[6];
|
|
|
|
_unRegisters[0] = EnumEventSystem.Global.Register(GameLoopEnum.GameStart, () => state.OnGame(true));
|
|
_unRegisters[1] = EnumEventSystem.Global.Register(GameLoopEnum.PauseGame, () => state.OnPause(true));
|
|
|
|
_unRegisters[2] = EnumEventSystem.Global.Register(GameLoopEnum.GameQuit, () => state.OnGame(false));
|
|
_unRegisters[3] = EnumEventSystem.Global.Register(GameLoopEnum.UnPauseGame, () => state.OnPause(false));
|
|
|
|
_unRegisters[4] = EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, () => state.OnDialog(true));
|
|
_unRegisters[5] = EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, () => state.OnDialog(false));
|
|
}
|
|
|
|
private void UnRegisterEvents()
|
|
{
|
|
foreach (var unRegister in _unRegisters)
|
|
{
|
|
unRegister.UnRegister();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>
|
|
/// GameManager应该包含什么功能?
|
|
/// 1. 游戏状态管理。开始/暂停/结束
|
|
/// 2. 全局设置 即SettingLoader
|
|
/// 3. 场景管理 有SceneLoader类,暂无必要
|
|
/// 4. 资源管理 似无必要
|
|
/// 5. 时间管理 主要供暂停使用
|
|
/// 6. 日志和调试 日志已有
|
|
/// </summary>
|
|
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 struct GameLoopState
|
|
{
|
|
public bool isInGame;
|
|
public bool isInDialog;
|
|
public bool isInPause;
|
|
|
|
public void OnGame(bool isInGame)
|
|
{
|
|
this.isInGame = isInGame;
|
|
}
|
|
|
|
public void OnPause(bool isInPause)
|
|
{
|
|
this.isInPause = isInPause;
|
|
}
|
|
|
|
public void OnDialog(bool isInDialog)
|
|
{
|
|
this.isInDialog = isInDialog;
|
|
}
|
|
|
|
public bool IsInputAvailable()
|
|
{
|
|
return isInGame && isInDialog && !isInPause;
|
|
}
|
|
}
|
|
|
|
public enum RunMode
|
|
{
|
|
Product,
|
|
SingleScene,
|
|
SaveFile
|
|
}
|
|
} |