using System; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.Events; using Core; namespace Script.Gameplay.Global { /// /// 全局关卡倒计时管理器(UniTimer 版) /// public sealed class GameCountdownManager : MonoSingleton { [Header("默认关卡时长(秒)")] [SerializeField] private float defaultDuration = 60f; [Header("是否受 Time.timeScale 影响")] [SerializeField] private bool useUnscaledTime = false; [Header("事件:每秒刷新(剩余秒数)")] public UnityEvent OnTick; [Header("事件:倒计时结束")] public UnityEvent OnFinish; private UniTimer _timer = new UniTimer(); /*------------------------------------------------------*/ protected override void Awake() { base.Awake(); // 确保事件实例化,避免其他脚本订阅时报 NullReferenceException OnTick ??= new UnityEvent(); OnFinish ??= new UnityEvent(); } /// /// 启动关卡倒计时(默认时长) /// public UniTask StartLevelTimer() => StartLevelTimer(defaultDuration); /// /// 启动关卡倒计时(指定时长) /// /// 秒 public UniTask StartLevelTimer(float duration) { StopTimer(); // 先清掉旧计时器 // 用 unscaledDeltaTime 就不受 Time.timeScale 影响 Time.timeScale = 1f; // 可根据需求保留或去掉 return _timer.StartAsync( duration, isCountDown: true, onTick: left => { OnTick?.Invoke(left); }, onComplete: () => { OnFinish?.Invoke(); // 这里可以统一处理“时间到”逻辑 TimeOutHandle(); }); } /// 暂停 public void Pause() => _timer.Pause(); /// 继续 public void Resume() => _timer.Resume(); /// 立即结束并触发 OnFinish public void StopTimer() => _timer.Stop(); /// 剩余时间(秒) public float Remaining => _timer.Remaining; /// 是否正在跑 public bool IsRunning => _timer.IsRunning; /*------------------------------------------------------*/ // 统一处理“时间到” private void TimeOutHandle() { Debug.Log("[GameCountdown] 关卡时间到!"); // 可以在这里弹 UI、播放音效、加载结算场景等 } /*------------------------------------------------------*/ // 方便外部 await 等待结束 public UniTask WaitForTimeOutAsync() => _timer.WaitForFinishAsync(); } }