using System; namespace XGame.Framework.Time { public class Timer : ITimer { 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 float TimeScale { get; set; } = 1; private int _passTimes; private TimerRunState _runState; 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; _runState = 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) { if (_runState == TimerRunState.Stoped || _runState == TimerRunState.Finished || _runState == TimerRunState.Exception) { return true; } if (_runState == 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) { _runState = TimerRunState.Exception; Log.Exception($"定时器回调执行发生异常({_passTimes}/{_loopTimes})", e); //throw new Exception($"定时器回调执行发生异常({_passTimes}/{_loopTimes}):{e}"); } if (_passTimes == _loopTimes) { _runState = TimerRunState.Finished; return true; } } return false; } public void Cancel() { _runState = TimerRunState.Stoped; _action = null; _actionLoop = null; } public void Pause() { if (_runState == TimerRunState.Running) _runState = TimerRunState.Paused; } public void Resume() { if (_runState == TimerRunState.Paused) _runState = TimerRunState.Running; } public void Dispose() { _action = null; _actionLoop = null; } } }