using System; using XGame.Framework.Interfaces; namespace XGame.Framework.Time { public class Timer : ITimer, IReset { public enum TimerRunState : sbyte { None, Running, Paused, Stoped, Finished, Exception, } private int _delay; /// /// 间隔 /// private int _interval; /// /// 时间轴 /// private int _timeAxis; /// /// 循环次数上限 /// private int _loopTimes; private Action _action; private Action _actionLoop; public ITimeListener Listener { get; set; } public float TimeScale { get; set; } = 1; private int _passTimes; private TimerRunState _runState; public TimerRunState State { get => _runState; private set { _runState = value; if (value is TimerRunState.Stoped or TimerRunState.Finished or TimerRunState.Exception) { try { Listener?.OnCompleted(this); } catch (Exception ex) { Log.Exception($"定时器事件监听执行异常.", ex); } Listener = null; } } } internal Timer(int delay, int interval, int looptimes, Action action) { #if UNITY_EDITOR UnityEngine.Assertions.Assert.IsTrue(delay >= 0, "延迟不能<0"); UnityEngine.Assertions.Assert.IsTrue(!(delay == 0 && looptimes == 1), "立即执行的延迟定时器次数不能小于2"); UnityEngine.Assertions.Assert.IsTrue(interval > 0, "定时器间隔不能<=0"); UnityEngine.Assertions.Assert.IsTrue(looptimes != 0, "定时器执行次数不能为0,如果要无限循环请设置为-1"); UnityEngine.Assertions.Assert.IsNotNull(action, "定时器回调不能为null"); #endif _action = action; InnerInit(delay, interval, looptimes); } internal Timer(int delay, int interval, int looptimes, Action action) { #if UNITY_EDITOR UnityEngine.Assertions.Assert.IsTrue(delay >= 0, "延迟不能<0"); UnityEngine.Assertions.Assert.IsTrue(!(delay == 0 && looptimes == 1), "立即执行的延迟定时器次数不能小于2"); UnityEngine.Assertions.Assert.IsTrue(interval > 0, "定时器间隔不能<=0"); UnityEngine.Assertions.Assert.IsTrue(looptimes != 0, "定时器执行次数不能为0,如果要无限循环请设置为-1"); UnityEngine.Assertions.Assert.IsNotNull(action, "定时器回调不能为null"); #endif _actionLoop = action; InnerInit(delay, interval, looptimes); } private void InnerInit(int delay, int interval, int looptimes) { _delay = delay; _interval = interval; _loopTimes = looptimes; _passTimes = 0; State = TimerRunState.Running; } //校准时间 private float addingValue = 0; private int CorrectTime(int deltaTime) { float updateTime = (float)deltaTime * TimeScale; int elapse = (int)updateTime; float timeDecimals = updateTime - elapse; addingValue += timeDecimals; if (addingValue >= 1.0f) { elapse += 1; addingValue -= 1.0f; } return elapse; } internal bool Update(int deltaTime) { switch (State) { case TimerRunState.Stoped: case TimerRunState.Finished: case TimerRunState.Exception: return true; case TimerRunState.Paused: return false; } int correctedTime = CorrectTime(deltaTime); _timeAxis += correctedTime; var interval = _passTimes == 0 ? _delay : _interval; if (_timeAxis > interval) { _timeAxis -= interval; _passTimes += 1; try { _action?.Invoke(); _actionLoop?.Invoke(_passTimes); } catch (Exception e) { State = TimerRunState.Exception; Log.Exception($"定时器回调执行发生异常({_passTimes}/{_loopTimes})", e); //throw new Exception($"定时器回调执行发生异常({_passTimes}/{_loopTimes}):{e}"); } if (_passTimes == _loopTimes) { State = TimerRunState.Finished; return true; } } return false; } public void Cancel() { State = TimerRunState.Stoped; _action = null; _actionLoop = null; } public void Pause() { if (State == TimerRunState.Running) State = TimerRunState.Paused; } public void Resume() { if (State == TimerRunState.Paused) State = TimerRunState.Running; } public void Dispose() { _action = null; _actionLoop = null; Listener = null; } /// /// 只对Running状态的定时器有效 /// void IReset.Reset() { if (State != TimerRunState.Running) { return; } _timeAxis = 0; _passTimes = 0; } public int TimeAxis => _timeAxis; /// /// 下一次回调的剩余时间 /// public int RemainTime { get { var interval = _passTimes == 0 ? _delay : _interval; return interval - _timeAxis; } } /// /// 只对Running状态的定时器有效 /// /// public void ResetForAxis(int timeAsis) { if (State != TimerRunState.Running) { return; } _timeAxis = timeAsis; _passTimes = 0; } } }