Unity框架之计时器

在学习一项新事物前,要先了解我们的需求是什么,为什么需要计时器。我在试图做ACT游戏demo时,想要给角色加上技能冷却CD,在CD时间内角色不能释放技能,CD后才可以。于是有了需求就开始制作计时器吧。


计时器主体脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using UnityEngine;

public enum TimerWorkState
{
NONE,
WORKERING,
DONE
}

public class GameTimer
{
private float _startTime;
private bool _stop;
private Action _action;
public TimerWorkState _state;

public GameTimer()
{
ResetTimer();
}

/// <summary>
/// 唤醒一个计时器
/// </summary>
/// <param name="time">计时时长</param>
/// <param name="task">任务</param>
public void CallOut(float time, Action task)
{
_startTime = time;
_action = task;
_stop = false;
_state = TimerWorkState.WORKERING;
}

public void Working()
{
_startTime -= Time.deltaTime;
if (_startTime < 0)
{
_action.Invoke();
_stop = true;
_state = TimerWorkState.DONE;
}
}
public TimerWorkState GetTimerState() => _state;

public void ResetTimer()
{
_startTime = 0f;
_stop = true;
_action = null;
_state = TimerWorkState.NONE;
}
}



计时器管理器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using UnityEngine.UIElements;

public class TimerManager : SingleMono<TimerManager>
{
private List<GameTimer> _activeTimers = new List<GameTimer>();
private Queue<GameTimer> _dormancyTimers = new Queue<GameTimer>();
[SerializeField] private int _howManyTimer;
private void Awake()
{
InitTimer(_howManyTimer);
}

private void Update()
{
TimerWork();
}

//初始化计时器
private void InitTimer(int timer)
{
for (int i = 0; i < timer; i++)
{
GameTimer timer1 = new GameTimer();
_dormancyTimers.Enqueue(timer1);
}
}

public void TryGetOneTimer(float time,Action action)
{
if(_dormancyTimers.Count == 0)
{
GameTimer timer = new GameTimer();
timer.CallOut(time, action);
_activeTimers.Add(timer);
}
else
{
GameTimer timer = _dormancyTimers.Dequeue();
timer.CallOut(time, action); ;
_activeTimers.Add(timer);
}
}

private void TimerWork()
{
if(_activeTimers.Count == 0) return;
for (int i = 0; i < _activeTimers.Count; i++)
{
if(_activeTimers[i].GetTimerState() == TimerWorkState.WORKERING)
{
_activeTimers[i].Working();
}
else
{
_dormancyTimers.Enqueue(_activeTimers[i]);
_activeTimers[i].ResetTimer();
_activeTimers.Remove(_activeTimers[i]);
}
}
}
}