UFL10-2——TimeManager 具体实现
UFL10-2——TimeManager 具体实现
TimeManager 具体实现
1 | public class TimerManager : BaseManager<TimerManager> |
-
需要声明的关键成员
-
计时器字典容器
1
2
3
4/// <summary>
/// 用于管理所有计时器的字典容器
/// </summary>
private Dictionary<int, TimerItem> timerDic = new Dictionary<int, TimerItem>(); -
待移除计时器列表容器
1
2
3
4/// <summary>
/// 待移除的列表
/// </summary>
private List<TimerItem> delList = new List<TimerItem>();
等等
-
-
需要实现的关键方法
-
开启计时器管理器(实例化时就执行)
这里的计时逻辑由协程执行,因此需要声明一个协程变量,来管理开启时返的协程,便于关闭计时
1
2
3
4
5
6
7
8
9
10
11
12
13private Coroutine timer;
private TimerManager()
{
Start();
}
//开启计时器管理器的方法
public void Start()
{
timer = MonoManager.Instance.StartCoroutine(StartTiming());
} -
关闭计时器管理器
1
2
3
4
5
6
7private Coroutine timer;
//关闭计时器管理器的方法
public void Stop()
{
MonoManager.Instance.StopCoroutine(timer);
} -
计时协程
可以通过修改
intervalTime
来修改每隔多少时间记一次时,间隔越短精确度越高,但性能也越差
每记一次时间以后,就可以遍历timerDic
内的计时器对象,如果该对象有间隔时间要执行的委托,先对间隔时间减去经过的时间,再检测间隔时间是否归0,
如果归0,就执行需要间隔执行的委托,并重置间隔时间然后对总时间减去经过的时间,再检测总时间是否归0,
如果归0,执行最终要执行的委托,然后将该计时器对象移入到待移除列表delList
内然后将待移除列表内的计时器对象从
timerDic
内,并压入缓存池,最后清空待移除列表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/// <summary>
/// 用于管理所有计时器的字典容器
/// </summary>
private Dictionary<int, TimerItem> timerDic = new Dictionary<int, TimerItem>();
/// <summary>
/// 待移除的列表
/// </summary>
private List<TimerItem> delList = new List<TimerItem>();
private Coroutine timer;
/// <summary>
/// 计时器管理器中唯一计时用的协程的间隔时间
/// </summary>
private const float intervalTimeSec = 0.1f;
//计时用的协程
private IEnumerator StartTiming()
{
while (true)
{
//每隔一段时间进行一次计时
yield return new WaitForSeconds(intervalTimeSec);
foreach (TimerItem item in timerDic.Values)
{
if (!item.isRunning)
continue;
//判断计时对象是否有间隔时间执行的需求
if (item.callBack != null)
{
//减去经过的间隔时间
item.intervalTimeMiniSec -= (int)(intervalTimeSec * 1000);
if (item.intervalTimeMiniSec <= 0)
{
item.callBack.Invoke();
item.intervalTimeMiniSec = item.maxIntervalTimeMiniSec;
}
}
//总的时间更新
item.allTimeMiniSec -= (int)(intervalTimeSec * 1000);
//计时时间到,需要执行完成回调函数
if (item.allTimeMiniSec <= 0)
{
item.overCallBack.Invoke();
delList.Add(item);
}
}
//移除待移除列表中的数据
for (int i = 0; i < delList.Count; i++)
{
//从字典中移除
timerDic.Remove(delList[i].keyID);
//放入到缓存池中
PoolManager.Instance.PushObj(delList[i]);
}
//移除结束后清空列表
delList.Clear();
}
} -
创建单个计时器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/// <summary>
/// 用于记录当前将要创建的计时器对象唯一ID
/// </summary>
private int TIMER_KEY = 0;
/// <summary>
/// 创建单个计时器
/// </summary>
/// <param name="allTimeMiniSec">总延迟时间(单位:毫秒)</param>
/// <param name="overCallBack">总时间结束回调</param>
/// <param name="intervalTimeMiniSec">间隔计时时间(单位:毫秒)</param>
/// <param name="callBack">间隔计时时间结束回调</param>
/// <returns>创建出来的计时器ID,用于外部控制对应计时器</returns>
public int CreateTimer(int allTimeMiniSec, UnityAction overCallBack, int intervalTimeMiniSec = 0, UnityAction callBack = null)
{
int keyID = ++TIMER_KEY;
//从缓存池取出对应的计时器,并初始化数据,然后记录到字典内
TimerItem timerItem = PoolManager.Instance.GetObj<TimerItem>();
timerItem.InitInfo(keyID, allTimeMiniSec, overCallBack, intervalTimeMiniSec, callBack);
timerDic.Add(keyID, timerItem);
return keyID;
} -
移除单个计时器
1
2
3
4
5
6
7
8
9
10
11
12/// <summary>
/// 移除单个计时器
/// </summary>
/// <param name="keyID">要移除的计时器对象ID</param>
public void RemoveTimer(int keyID)
{
if (timerDic.ContainsKey(keyID))
{
PoolManager.Instance.PushObj(timerDic[keyID]);
timerDic.Remove(keyID);
}
} -
重置单个计时器
1
2
3
4
5
6
7
8
9
10
11/// <summary>
/// 重置单个计时器
/// </summary>
/// <param name="keyID">要重置计时的计时器对象ID</param>
public void ResetTimer(int keyID)
{
if (timerDic.ContainsKey(keyID))
{
timerDic[keyID].ResetTimer();
}
} -
开启单个计时器
1
2
3
4
5
6
7
8
9
10
11/// <summary>
/// 开启单个计时器
/// </summary>
/// <param name="keyID">要开始计时的计时器对象ID</param>
public void StartTimer(int keyID)
{
if (timerDic.ContainsKey(keyID))
{
timerDic[keyID].isRunning = true;
}
} -
停止单个计时器
1
2
3
4
5
6
7
8
9
10
11/// <summary>
/// 停止单个计时器的计时
/// </summary>
/// <param name="keyID">要停止计时的计时器对象ID</param>
public void StopTimer(int keyID)
{
if (timerDic.ContainsKey(keyID))
{
timerDic[keyID].isRunning = false;
}
}
-
使用示例
1 | private int timerID; |
按下T后输出,中途如果按下Y就会停止输出:
抛出问题
目前的计时器管理器会受到 Time.timeScale
的影响,我们应该如何让计时器管理器可以自己决定是否受到它的影响呢?
具体代码
1 | using System.Collections; |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 文KRIFE齐的博客!