Timer.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System;
  2. using XGame.Framework.Interfaces;
  3. namespace XGame.Framework.Time
  4. {
  5. public class Timer : ITimer, IReset
  6. {
  7. public enum TimerRunState : sbyte
  8. {
  9. None,
  10. Running,
  11. Paused,
  12. Stoped,
  13. Finished,
  14. Exception,
  15. }
  16. private int _delay;
  17. /// <summary>
  18. /// 间隔
  19. /// </summary>
  20. private int _interval;
  21. /// <summary>
  22. /// 时间轴
  23. /// </summary>
  24. private int _timeAxis;
  25. /// <summary>
  26. /// 循环次数上限
  27. /// </summary>
  28. private int _loopTimes;
  29. private Action _action;
  30. private Action<int> _actionLoop;
  31. public ITimeListener<ITimer> Listener { get; set; }
  32. public float TimeScale { get; set; } = 1;
  33. private int _passTimes;
  34. private TimerRunState _runState;
  35. public TimerRunState State
  36. {
  37. get => _runState;
  38. private set
  39. {
  40. _runState = value;
  41. if (value is TimerRunState.Stoped or TimerRunState.Finished or TimerRunState.Exception)
  42. {
  43. try
  44. {
  45. Listener?.OnCompleted(this);
  46. }
  47. catch (Exception ex)
  48. {
  49. Log.Exception($"定时器事件监听执行异常.", ex);
  50. }
  51. Listener = null;
  52. }
  53. }
  54. }
  55. internal Timer(int delay, int interval, int looptimes, Action action)
  56. {
  57. #if UNITY_EDITOR
  58. UnityEngine.Assertions.Assert.IsTrue(delay >= 0, "延迟不能<0");
  59. UnityEngine.Assertions.Assert.IsTrue(!(delay == 0 && looptimes == 1), "立即执行的延迟定时器次数不能小于2");
  60. UnityEngine.Assertions.Assert.IsTrue(interval > 0, "定时器间隔不能<=0");
  61. UnityEngine.Assertions.Assert.IsTrue(looptimes != 0, "定时器执行次数不能为0,如果要无限循环请设置为-1");
  62. UnityEngine.Assertions.Assert.IsNotNull(action, "定时器回调不能为null");
  63. #endif
  64. _action = action;
  65. InnerInit(delay, interval, looptimes);
  66. }
  67. internal Timer(int delay, int interval, int looptimes, Action<int> action)
  68. {
  69. #if UNITY_EDITOR
  70. UnityEngine.Assertions.Assert.IsTrue(delay >= 0, "延迟不能<0");
  71. UnityEngine.Assertions.Assert.IsTrue(!(delay == 0 && looptimes == 1), "立即执行的延迟定时器次数不能小于2");
  72. UnityEngine.Assertions.Assert.IsTrue(interval > 0, "定时器间隔不能<=0");
  73. UnityEngine.Assertions.Assert.IsTrue(looptimes != 0, "定时器执行次数不能为0,如果要无限循环请设置为-1");
  74. UnityEngine.Assertions.Assert.IsNotNull(action, "定时器回调不能为null");
  75. #endif
  76. _actionLoop = action;
  77. InnerInit(delay, interval, looptimes);
  78. }
  79. private void InnerInit(int delay, int interval, int looptimes)
  80. {
  81. _delay = delay;
  82. _interval = interval;
  83. _loopTimes = looptimes;
  84. _passTimes = 0;
  85. State = TimerRunState.Running;
  86. }
  87. //校准时间
  88. private float addingValue = 0;
  89. private int CorrectTime(int deltaTime)
  90. {
  91. float updateTime = (float)deltaTime * TimeScale;
  92. int elapse = (int)updateTime;
  93. float timeDecimals = updateTime - elapse;
  94. addingValue += timeDecimals;
  95. if (addingValue >= 1.0f)
  96. {
  97. elapse += 1;
  98. addingValue -= 1.0f;
  99. }
  100. return elapse;
  101. }
  102. internal bool Update(int deltaTime)
  103. {
  104. switch (State)
  105. {
  106. case TimerRunState.Stoped:
  107. case TimerRunState.Finished:
  108. case TimerRunState.Exception:
  109. return true;
  110. case TimerRunState.Paused:
  111. return false;
  112. }
  113. int correctedTime = CorrectTime(deltaTime);
  114. _timeAxis += correctedTime;
  115. var interval = _passTimes == 0 ? _delay : _interval;
  116. if (_timeAxis > interval)
  117. {
  118. _timeAxis -= interval;
  119. _passTimes += 1;
  120. try
  121. {
  122. _action?.Invoke();
  123. _actionLoop?.Invoke(_passTimes);
  124. }
  125. catch (Exception e)
  126. {
  127. State = TimerRunState.Exception;
  128. Log.Exception($"定时器回调执行发生异常({_passTimes}/{_loopTimes})", e);
  129. //throw new Exception($"定时器回调执行发生异常({_passTimes}/{_loopTimes}):{e}");
  130. }
  131. if (_passTimes == _loopTimes)
  132. {
  133. State = TimerRunState.Finished;
  134. return true;
  135. }
  136. }
  137. return false;
  138. }
  139. public void Cancel()
  140. {
  141. State = TimerRunState.Stoped;
  142. _action = null;
  143. _actionLoop = null;
  144. }
  145. public void Pause()
  146. {
  147. if (State == TimerRunState.Running)
  148. State = TimerRunState.Paused;
  149. }
  150. public void Resume()
  151. {
  152. if (State == TimerRunState.Paused)
  153. State = TimerRunState.Running;
  154. }
  155. public void Dispose()
  156. {
  157. _action = null;
  158. _actionLoop = null;
  159. Listener = null;
  160. }
  161. /// <summary>
  162. /// 只对Running状态的定时器有效
  163. /// </summary>
  164. void IReset.Reset()
  165. {
  166. if (State != TimerRunState.Running)
  167. {
  168. return;
  169. }
  170. _timeAxis = 0;
  171. _passTimes = 0;
  172. }
  173. public int TimeAxis => _timeAxis;
  174. /// <summary>
  175. /// 只对Running状态的定时器有效
  176. /// </summary>
  177. /// <param name="delay"></param>
  178. public void ResetForAxis(int timeAsis)
  179. {
  180. if (State != TimerRunState.Running)
  181. {
  182. return;
  183. }
  184. _timeAxis = timeAsis;
  185. _passTimes = 0;
  186. }
  187. }
  188. }