feat(TimeCountDown): 实现倒计时功能

This commit is contained in:
2025-10-18 10:06:12 +08:00
parent 48d872b4b9
commit 2614dab342
16 changed files with 687 additions and 70 deletions

View File

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bdaad0392e5549f0ac761238b649cc70
timeCreated: 1760751427

View File

@@ -0,0 +1,24 @@
using System;
using Core;
using UnityEngine;
namespace Script.Gameplay.Global
{
public enum GameState
{
Boot, // 初始化
MainMenu, // 主菜单
Playing, // 游戏中
Paused, // 暂停
GameOver, // 游戏结束
Victory // 胜利
}
public class GameFlowManager : MonoSingleton<GameFlowManager>
{
private void Start()
{
GameCountdownManager.Instance.StartLevelTimer();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8ff98d4d16514d27a14dc271bbbd19e7
timeCreated: 1760752445

View File

@@ -0,0 +1,37 @@
using System;
using UnityEngine;
using UnityEngine.UI;
using Script.Gameplay.Global;
namespace UI
{
public class GameCountDownViewer : MonoBehaviour
{
public Text countdownText;
private GameCountdownManager _countdownManager;
private void Start()
{
_countdownManager = GameCountdownManager.Instance;
if (_countdownManager != null)
{
_countdownManager.OnTick.AddListener(UpdateCountdown);
}
}
public void UpdateCountdown(float secondsLeft)
{
if (countdownText != null)
{
int seconds = Mathf.CeilToInt(secondsLeft);
countdownText.text = "倒计时: " + seconds.ToString();
}
}
private void OnDestroy()
{
if (_countdownManager != null)
{
_countdownManager.OnTick.RemoveListener(UpdateCountdown);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1aa400ea9061498897f3c03b0336cfda
timeCreated: 1760751782