这是我第一次使用Markdown,不太会用。废话不多说,直接上代码吧。
using System;
using System.Collections.Generic;
using UnityEngine;
public class GameTimer
{
private class TimeWrapper
{
public uint id;
public uint expiredFrame;
public uint durationFrame;
public Action<uint> handler;
public bool isDead = false;
}
private static GameTimer _instance;
public static GameTimer Instance
{
get
{
if (_instance == null) _instance= new GameTimer();
return _instance;
}
}
private GameTimer()
{
_running = false;
_timerID = 10001;
_currentFrameIndex = 0;
}
private bool _running;
private uint _timerID;
private uint _currentFrameIndex;
private List<TimeWrapper> _wrapperList = new List<TimeWrapper>();
private List<TimeWrapper> _deadList = new List<TimeWrapper>();
public void Run()
{
_running = true;
}
public void Stop()
{
_running = false;
}
public void OnUpdate()
{
if (_running == false) return;
_currentFrameIndex++;
_deadList.Clear();
for (int i = 0; i < _wrapperList.Count; i++)
{
var item = _wrapperList[i];
if (item.expiredFrame <= _currentFrameIndex && !item.isDead)
{
item.handler(item.id);
item.expiredFrame += item.durationFrame;
}
if (item.isDead) _deadList.Add(item);
}
for (int i = _deadList.Count - 1; i >= 0; i--)
{
_wrapperList.Remove(_deadList[i]);
}
_deadList.Clear();
}
// 根据定时器id删除定时器
public void DeleteTimer(uint timerId)
{
for (int i = 0; i < _wrapperList.Count; i++)
{
if (_wrapperList[i].id == timerId)
{
_wrapperList[i].isDead = true;
break;
}
}
}
// 删除全部定时器
public void DeleteAllTimer()
{
_wrapperList.Clear();
}
/// <summary>
/// 启动一个计时器
/// </summary>
/// <param name="intervalTime">定时帧数</param>
/// <param name="handler">定时器回调</param>
/// <param name="delayTime">首次计时的延时时间,默认为定时帧数</param>
/// <returns>定时器ID</returns>
public uint StartTimer(uint intervalTime, Action<uint> handler, uint delayTime = uint.MaxValue)
{
delayTime = delayTime == uint.MaxValue ? intervalTime : delayTime;
TimeWrapper wrapper = new TimeWrapper
{
id = _timerID++,
handler = handler,
durationFrame = intervalTime,
expiredFrame = delayTime == uint.MaxValue ? intervalTime : delayTime,
isDead = false
};
_wrapperList.Add(wrapper);
return wrapper.id;
}
/// <summary>
/// 启动一个指定次数的定时器
/// </summary>
/// <param name="duration">定时帧数</param>
/// <param name="times">计时次数</param>
/// <param name="handler">定时器回调</param>
/// <param name="callback">计时结束后回调</param>
/// <param name="delayTime">首次计时的延时时间,默认为定时帧数</param>
/// <returns>定时器ID</returns>
public uint StartInterval(uint duration, uint times, Action<uint> handler, Action callback = null, uint delayTime = uint.MaxValue)
{
Action<uint> action = id =>
{
handler(id);
times--;
if (times <= 0)
{
if (callback != null)
{
callback();
}
DeleteTimer(id);
}
};
return StartTimer(duration, action, delayTime);
}
/// <summary>
/// 启动一个定时器
/// </summary>
/// <param name="delayTime">定时帧数</param>
/// <param name="handler">定时器回调</param>
/// <returns></returns>
public uint StartTimerOnce(uint delayTime, Action<uint> handler)
{
Action<uint> action = id =>
{
handler(id);
DeleteTimer(id);
};
return StartTimer(delayTime, action, delayTime);
}
}
代码就这么多啦!!!
使用计时器之前,记得先调用一下 Run 函数,OnUpdate函数也需要在Update调用起来哦!!!
注意: 所有的函数调用,传入的参数都是帧,需要用到秒的同学可以自己重载一下函数