游易光年的Unity3D测试题,不明白哪里错了
题目:游戏中会出现很多计时器,比如建筑建造时间,商店刷新计时,限时活动等,用文字和伪代码结合的形式写出怎么管理这些计时器,答案尽量解耦和易读,并需要考虑以下两点:
a.计时器倒计时的UI显示
b.到时间后需要执行的逻辑
我的代码:
遵循三层架构,倒计时是临时使用也不需要事件,难道是商业项目中的实现完全不同?
public class TestUIPanel : SingletonMonoGlobal<TestUIPanel> { //时间显示的组件 public Text timeText; public void SetTime(int second) { timeText.text = second.ToString(); } } // 控制层 public class BuildMgr { //注册事件 void StartBuild(int buildTime) { //开启定时器 TimeMgr.Instance.StartCountDown(buildTime, seconds => TestUIPanel.Instance.SetTime(seconds), FinishBuild); } //完成建造 void FinishBuild() { } } // 具体数据处理 --数据层 public class TimeMgr : SingletonMonoGlobal<TimeMgr> { public event Action<int> onTimeChange; public void StartCountDown(int seconds, Action<int> onTimeChange, Action onCountDownFinish) { StartCoroutine(StartCountDownAsync(seconds, onTimeChange, onCountDownFinish)); } IEnumerator StartCountDownAsync(int seconds, Action<int> onTimeChange, Action onCountDownFinish) { while (seconds > 0) { yield return new WaitForSeconds(1f); seconds--; onTimeChange?.Invoke(seconds); } onCountDownFinish?.Invoke(); } }
用ai生成了一下破案了,要将timer对象化并且使用对象池,没做过这种业务确实很难想到
// Timer.cs public class Timer { public float Duration { get; private set; } private float elapsedTime; private bool isRunning; public event Action OnTimerCompleted; public Timer(float duration, Action onTimerCompleted = null) { Duration = duration; OnTimerCompleted = onTimerCompleted; } public void Start() { isRunning = true; elapsedTime = 0f; } public void Stop() { isRunning = false; } public void Update(float deltaTime) { if (!isRunning) return; elapsedTime += deltaTime; if (elapsedTime >= Duration) { isRunning = false; OnTimerCompleted?.Invoke(); } } public float GetTimeRemaining() => Duration - elapsedTime; } // TimerManager.cs public class TimerManager : MonoBehaviour { private List<Timer> timers = new List<Timer>(); public Timer CreateTimer(float duration, Action onTimerCompleted) { var timer = new Timer(duration, onTimerCompleted); timers.Add(timer); timer.Start(); return timer; } private void Update() { float deltaTime = Time.deltaTime; for (int i = timers.Count - 1; i >= 0; i--) { timers[i].Update(deltaTime); if (!timers[i].IsRunning) timers.RemoveAt(i); } } } // UI更新示例 public class TimerUI : MonoBehaviour { [SerializeField] private Text timerText; private Timer timer; private void Start() { timer = TimerManager.Instance.CreateTimer(60f, OnTimerComplete); InvokeRepeating(nameof(UpdateUI), 0f, 1f); } private void UpdateUI() { if (timer != null) timerText.text = timer.GetTimeRemaining().ToString("F1"); } private void OnTimerComplete() { timerText.text = "Complete!"; } }#2022届毕业生现状##我的求职思考##23届找工作求助阵地#