using System; using System.Collections; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using IndianOceanAssets.Engine2_5D; namespace GameFramework { /// /// 全局游戏状态管理器(持久化单例)。 /// 维护 GameState,提供 GameOver / Win 触发入口与对应事件。 /// public class GameManager : PersistentSingleton { /// 游戏结束(失败)时触发。 public static Action onGameOver; /// 游戏胜利时触发。 public static Action onGameWin; public static GameState GameState { get => Instance.gameState; set => Instance.gameState = value; } [SerializeField] private GameState gameState = GameState.Playing; [Header("过场动画")] [Tooltip("光源扩大的持续时间(秒)")] [SerializeField] private float lightExpandDuration = 1.5f; [Tooltip("光源扩大目标半径")] [SerializeField] private float lightExpandTargetRadius = 20f; [Tooltip("淡出持续时间(秒)")] [SerializeField] private float fadeOutDuration = 1f; /// 触发游戏失败:设状态 + 触发事件 + 播放过场动画。 public static void GameOver() { if (Instance == null) return; GameState = GameState.GameOver; onGameOver?.Invoke(); Instance.StartCoroutine(Instance.DeathTransition()); } /// 触发游戏胜利:设状态 + 触发事件 + 播放过场动画。 public static void Win() { if (Instance == null) return; GameState = GameState.Victory; onGameWin?.Invoke(); Instance.StartCoroutine(Instance.VictoryTransition()); } /// /// 死亡过场协程:禁用控制 → 光源放大 → 淡出 → 跳转 Scoring。 /// 使用 unscaledDeltaTime 确保不受 timeScale 影响。 /// private IEnumerator DeathTransition() { // 等待一帧,让 HUD 先更新血量显示(最后一滴血消失) yield return null; // 1. 查找玩家并禁用控制 var player = GameObject.FindGameObjectWithTag("Player"); if (player != null) { // 禁用玩家移动 var playerController = player.GetComponent(); if (playerController != null) playerController.enabled = false; // 禁用相机跟随 var camFollow = Camera.main != null ? Camera.main.GetComponent() : null; if (camFollow != null) camFollow.enabled = false; // 2. 光源扩大 var lightSource = player.GetComponent(); if (lightSource != null) { float startRadius = lightSource.Radius; float elapsed = 0f; while (elapsed < lightExpandDuration) { elapsed += Time.unscaledDeltaTime; float t = Mathf.Clamp01(elapsed / lightExpandDuration); float smoothT = t * t * (3f - 2f * t); // SmoothStep lightSource.SetRadius(Mathf.Lerp(startRadius, lightExpandTargetRadius, smoothT)); yield return null; } lightSource.SetRadius(lightExpandTargetRadius); } else { // 没有光源,等待同样时间 yield return new WaitForSecondsRealtime(lightExpandDuration); } } else { // 没有玩家,等待同样时间 yield return new WaitForSecondsRealtime(lightExpandDuration); } // 3. 淡出到黑色 yield return StartCoroutine(FadeOutAndLoad()); } /// /// 胜利过场协程(与死亡相同,可后续扩展不同效果)。 /// private IEnumerator VictoryTransition() { // 胜利也使用相同的光源扩散 + 淡出效果 yield return DeathTransition(); } /// /// 创建全屏黑色遮罩并淡出,然后加载 Scoring 场景。 /// private IEnumerator FadeOutAndLoad() { // 创建全屏黑色遮罩 var canvasObj = new GameObject("FadeOverlay"); var canvas = canvasObj.AddComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; canvas.sortingOrder = 99999; canvasObj.AddComponent(); var overlay = canvasObj.AddComponent(); overlay.color = new Color(0, 0, 0, 0); // 淡出到黑色 float elapsed = 0f; while (elapsed < fadeOutDuration) { elapsed += Time.unscaledDeltaTime; float t = Mathf.Clamp01(elapsed / fadeOutDuration); overlay.color = new Color(0, 0, 0, t); yield return null; } overlay.color = new Color(0, 0, 0, 1); // 加载 Scoring 场景 if (SceneLoader.Instance != null) { SceneLoader.Instance.LoadScoringScene(); } else { SceneManager.LoadScene("Scoring"); } } } public enum GameState { Playing, Paused, GameOver, Victory, Scoring } }