定时器Timer封装,避免各个模块需要使用定时器时重复写定时器逻辑。
【计时器提供功能】
- 自动创建,自动销毁,定义了定时器池子,重复利用
- 支持帧、秒计时,支持不受TimeScale影响计时
- 支持多次计时,支持循环计时
- 提供获取当前计时总时间
还可以扩展功能,可根据对应需求增加相应接口。
Timer定时器:
using NUnit.Framework;
using System;
using UnityEngine;
public class Timer
{
// 外部传入参数
private float _delayTime;
private Action _onCall;
private uint _loopCount; //小于0表示循环
private bool _isUseRealTime;
private bool _isFrame;
// 内部定义参数
private bool _destroyed;
private bool _isLoop;
private float _startTime;
private float _nextTime;
/// <summary>
/// 外部创建Timer接口
/// </summary>
/// <param name="delayTime">延迟时间执行</param>
/// <param name="onCall">执行函数</param>
/// <param name="loopCount">循环次数,默认为1,0表示一直循环</param>
/// <param name="isFrame">true:逐帧检测, false:逐秒检测</param>
/// <param name="isUseRealTime">是否使用unScaleTime,默认false</param>
/// <returns></returns>
public static Timer CreateTimer(float delayTime, Action onCall, uint loopCount = 1, bool isFrame = false, bool isUseRealTime = false)
{
Timer timer = null;
if (!TimerManager.Instance.TryGetTimer(timer))
{
timer = new Timer();
}
timer.InitParams(delayTime, onCall, loopCount, isFrame, isUseRealTime);
return timer;
}
private Timer()
{
TimerManager.Instance.AddTimer(this);
}
private void InitParams(float delayTime, Action onCall, uint loopCount, bool isFrame, bool isUseRealTime)
{
Assert.IsTrue(delayTime > 0);
Assert.IsNotNull(onCall);
this._delayTime = delayTime;
this._onCall = onCall;
this._loopCount = loopCount;
this._isFrame = isFrame;
this._isUseRealTime = isUseRealTime;
this._destroyed = false;
this._isLoop = loopCount == 0;
_startTime = this.GetCurTime();
this._nextTime = _startTime + delayTime;
}
public void Update()
{
if (this._destroyed) return;
if (this.GetCurTime() >= this._nextTime)
{
this.Execute();
}
}
private void Execute()
{
try
{
this._onCall?.Invoke();
}
catch (Exception e)
{
LogModule.LogError("[Timer] call function error:{0}", e.ToString());
Destroy();
return;
}
this._loopCount--;
if (!this._isLoop && this._loopCount <= 0)
{
Destroy();
return;
}
this._nextTime = this.GetCurTime() + _delayTime;
}
private float GetCurTime()
{
return this._isFrame ? Time.frameCount : (this._isUseRealTime ? Time.unscaledTime : Time.time);
}
/// <summary>
/// 获取定时器过去的时间(供外部有需要调用)
/// </summary>
public float GetPassTime()
{
return this.GetCurTime() - this._startTime;
}
public bool IsRecovery()
{
return this._destroyed;
}
public void Destroy()
{
this._destroyed = true;
this._onCall = null;
}
}
TimerManager定时器管理类:
using System.Collections.Generic;
public class TimerManager : MonoSingleton<TimerManager>
{
private readonly List<Timer> _pool = new List<Timer>();
private readonly List<Timer> _updateTimerList = new List<Timer>();
protected override void Init()
{
_pool.Clear();
_updateTimerList.Clear();
}
private void Update()
{
for (int i = _updateTimerList.Count - 1; i >= 0; i--)
{
var timer = _updateTimerList[i];
timer.Update();
if (timer.IsRecovery())
{
_updateTimerList.RemoveAt(i);
_pool.Add(timer);
}
}
}
public void AddTimer(Timer timer)
{
_updateTimerList.Add(timer);
}
public bool TryGetTimer(Timer outTimer)
{
if (_pool.Count > 0)
{
outTimer = _pool[0];
_pool.RemoveAt(0);
return true;
}
return false;
}
protected override void Dispose()
{
_pool.Clear();
_updateTimerList.Clear();
}
}
使用范例:
Timer.CreateTimer(5, () =>
{
LogModule.LogError("[Timer1] 5秒后执行");
});
Timer timer = null;
timer = Timer.CreateTimer(1, () =>
{
LogModule.LogError("[Timer1] 循环,1秒执行一次,passTime = {0}", timer.GetPassTime().ToString());
}, 0);
(完)