TimerComponent.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Fort23.Core
  4. {
  5. public enum TimerType
  6. {
  7. None,
  8. Wait, // 等待
  9. Count, // 次数
  10. }
  11. public class TimerEntity : Entity
  12. {
  13. public TimerType timerType;
  14. /// <summary>
  15. /// 计时时间,毫秒
  16. /// </summary>
  17. public long time;
  18. /// <summary>
  19. /// 完成回调
  20. /// </summary>
  21. public object callback1;
  22. /// <summary>
  23. /// 次数
  24. /// </summary>
  25. public int count;
  26. /// <summary>
  27. /// 针对多次的,每次Hit回调
  28. /// </summary>
  29. public object callback2;
  30. [CustomMethod(CustomMethodType.Awake)]
  31. public void Awake(TimerType timerType, long time, object callback1, int count, object callback2)
  32. {
  33. this.timerType = timerType;
  34. this.time = time;
  35. this.callback1 = callback1;
  36. this.count = count;
  37. this.callback2 = callback2;
  38. }
  39. [CustomMethod(CustomMethodType.Destroy)]
  40. public void Destroy()
  41. {
  42. this.timerType = TimerType.None;
  43. this.time = 0;
  44. this.callback1 = null;
  45. this.count = 0;
  46. this.callback2 = null;
  47. }
  48. }
  49. public class TimerComponent : Entity
  50. {
  51. public static TimerComponent Instance { get; set; }
  52. /// <summary>
  53. /// key: time, value: timer id
  54. /// </summary>
  55. private readonly MultiMap<long, long> _timeID = new MultiMap<long, long>();
  56. private readonly Queue<long> _timeOutTime = new Queue<long>();
  57. private readonly Queue<long> _timeOutTimerIds = new Queue<long>();
  58. // 记录最小时间,不用每次都去MultiMap取第一个值
  59. private long _minTime;
  60. [CustomMethod(CustomMethodType.Awake)]
  61. public void Awake()
  62. {
  63. Instance = this;
  64. }
  65. [CustomMethod(CustomMethodType.Update)]
  66. public void Update()
  67. {
  68. if (this._timeID.Count == 0)
  69. {
  70. return;
  71. }
  72. long timeNow = TimeHelper.ServerNow();
  73. if (timeNow < this._minTime)
  74. {
  75. return;
  76. }
  77. foreach (KeyValuePair<long, List<long>> kv in this._timeID)
  78. {
  79. long k = kv.Key;
  80. if (k > timeNow)
  81. {
  82. _minTime = k;
  83. break;
  84. }
  85. this._timeOutTime.Enqueue(k);
  86. }
  87. // 2.找出失效时间对应的ID
  88. while (this._timeOutTime.Count > 0)
  89. {
  90. long time = this._timeOutTime.Dequeue();
  91. // 3.取出对应的TimerEntity执行逻辑
  92. for (int i = 0; i < this._timeID[time].Count; i++)
  93. {
  94. TimerEntity timerEntity = this.GetChild<TimerEntity>(_timeID[time][i]);
  95. if (timerEntity != null)
  96. {
  97. Run(timerEntity, time);
  98. }
  99. }
  100. // foreach (long timerId in this._timeID[time])
  101. // {
  102. // TimerEntity timerEntity = this.GetChild<TimerEntity>(timerId);
  103. // if (timerEntity != null)
  104. // {
  105. // Run(timerEntity, time);
  106. // }
  107. // }
  108. this._timeID.Remove(time);
  109. }
  110. }
  111. private void Run(TimerEntity timerEntity, long timestamp)
  112. {
  113. switch (timerEntity.timerType)
  114. {
  115. case TimerType.Wait:
  116. {
  117. CTask<bool> tcs = timerEntity.callback1 as CTask<bool>;
  118. this.Remove(timerEntity.ID);
  119. tcs.SetResult(true);
  120. break;
  121. }
  122. case TimerType.Count:
  123. {
  124. if (timerEntity.count <= 1)
  125. {
  126. Action action = timerEntity.callback1 as Action;
  127. this.Remove(timerEntity.ID);
  128. action?.Invoke();
  129. break;
  130. }
  131. else
  132. {
  133. long currTime = TimeHelper.ServerNow();
  134. long tillTime = currTime - currTime % timestamp + timerEntity.time;
  135. this.AddTimer(tillTime, timerEntity);
  136. Action action = timerEntity.callback2 as Action;
  137. action?.Invoke();
  138. timerEntity.count--;
  139. break;
  140. }
  141. }
  142. }
  143. }
  144. private void AddTimer(long untillTime, TimerEntity timerEntity)
  145. {
  146. this._timeID.Add(untillTime, timerEntity.ID);
  147. if (untillTime < this._minTime)
  148. {
  149. this._minTime = untillTime;
  150. }
  151. }
  152. /// <summary>
  153. /// 等待1帧(因为实在下一次Update里面刷新,所以WaitAsync传的值小于一帧的间隔就可以)
  154. /// </summary>
  155. /// <returns></returns>
  156. public async CTask<bool> WaitFrameAsync()
  157. {
  158. return await WaitAsync(1);
  159. }
  160. /// <summary>
  161. /// 等待time毫秒
  162. /// </summary>
  163. /// <param name="time">毫秒</param>
  164. /// <returns></returns>
  165. public async CTask<bool> WaitAsync(long time)
  166. {
  167. if (time == 0)
  168. {
  169. return true;
  170. }
  171. long tillTime = TimeHelper.ServerNow() + time;
  172. CTask<bool> tcs = CTask<bool>.Create(false);
  173. TimerEntity timerEntity = this.AddChild<TimerEntity, TimerType, long, object, int, object>(TimerType.Wait, 0, tcs, 1, null, true);
  174. this.AddTimer(tillTime, timerEntity);
  175. return await tcs;
  176. }
  177. /// <summary>
  178. /// 等待到指定毫秒的时间戳
  179. /// </summary>
  180. /// <param name="untillTime">毫秒</param>
  181. /// <returns></returns>
  182. public async CTask<bool> WaitTillAsync(long untillTime)
  183. {
  184. if (TimeHelper.ServerNow() >= untillTime)
  185. {
  186. return true;
  187. }
  188. CTask<bool> tcs = CTask<bool>.Create();
  189. TimerEntity timerEntity = this.AddChild<TimerEntity, TimerType, long, object, int, object>(TimerType.Wait, 0, tcs, 1, null, true);
  190. this.AddTimer(untillTime, timerEntity);
  191. return await tcs;
  192. }
  193. /// <summary>
  194. ///
  195. /// </summary>
  196. /// <param name="time">计时器Hit一次的时间(毫秒)</param>
  197. /// <param name="action1">全部count完成时候回调</param>
  198. /// <param name="count">次数</param>
  199. /// <param name="action2">针对多次执行的Timer,每一次Hit时候的回调</param>
  200. /// <returns>ID, 可以通过Remove来手动中止Timer</returns>
  201. public TimerEntity AddTimer(long time, Action action1, int count = 1, Action action2 = null)
  202. {
  203. TimerEntity timerEntity = this.AddChild<TimerEntity, TimerType, long, object, int, object>(TimerType.Count, time, action1, count, action2, true);
  204. this.AddTimer(TimeHelper.ServerNow() + time, timerEntity);
  205. return timerEntity;
  206. }
  207. public void Remove(ref long id)
  208. {
  209. this.Remove(id);
  210. id = 0;
  211. }
  212. public bool Remove(TimerEntity timerEntity)
  213. {
  214. if (timerEntity == null)
  215. {
  216. return false;
  217. }
  218. timerEntity.Dispose();
  219. return true;
  220. }
  221. public bool Remove(long id)
  222. {
  223. if (id == 0)
  224. {
  225. return false;
  226. }
  227. TimerEntity timerEntity = this.GetChild<TimerEntity>(id);
  228. return Remove(timerEntity);
  229. }
  230. }
  231. }