1.代码结构图
2.SmartTimer 模块Entity:
1 using System; 2 3 namespace ETModel 4 { 5 [ObjectSystem] 6 public class SmartTimerAwakeSystem: AwakeSystem<SmartTimer, float, uint, Action> 7 { 8 public override void Awake(SmartTimer self, float a, uint b, Action c) 9 { 10 self.Awake(a, b, c); 11 } 12 } 13 14 public sealed class SmartTimer: Entity 15 { 16 public const uint INFINITE = uint.MaxValue; 17 18 private float m_Interval = 0; 19 private bool m_InfiniteLoops = false; 20 private uint m_LoopsCount = 1; 21 private Action m_Action = null; 22 private Action m_Delegate = null; 23 private bool m_bIsPaused = false; 24 private uint m_CurrentLoopsCount = 0; 25 private float m_ElapsedTime = 0; 26 private long m_TickedTime = 0; 27 private float m_CurrentCycleElapsedTime = 0; 28 29 public void Awake(float interval, uint loopsCount, Action action) 30 { 31 if (m_Interval < 0) 32 m_Interval = 0; 33 34 m_TickedTime = DateTime.Now.Ticks; 35 m_Interval = interval; 36 m_LoopsCount = Math.Max(loopsCount, 1); 37 m_Delegate = action; 38 } 39 40 public override void Dispose() 41 { 42 if (this.IsDisposed) return; 43 this.m_Delegate = null; 44 this.m_Action = null; 45 base.Dispose(); 46 } 47 48 internal void UpdateActionFromAction() 49 { 50 if (m_InfiniteLoops) 51 m_LoopsCount = INFINITE; 52 53 if (m_Action != null) 54 m_Delegate = delegate { m_Action.Invoke(); }; 55 } 56 57 internal void UpdateTimer() 58 { 59 if (m_bIsPaused) 60 return; 61 62 if (m_Delegate == null || m_Interval < 0) 63 { 64 m_Interval = 0; 65 return; 66 } 67 68 if (m_CurrentLoopsCount >= m_LoopsCount && m_LoopsCount != INFINITE) 69 { 70 m_ElapsedTime = m_Interval * m_LoopsCount; 71 m_CurrentCycleElapsedTime = m_Interval; 72 } 73 else 74 { 75 m_ElapsedTime += (DateTime.Now.Ticks - this.m_TickedTime) / 10000000f; 76 m_TickedTime = DateTime.Now.Ticks; 77 m_CurrentCycleElapsedTime = m_ElapsedTime - m_CurrentLoopsCount * m_Interval; 78 79 if (m_CurrentCycleElapsedTime > m_Interval) 80 { 81 m_CurrentCycleElapsedTime -= m_Interval; 82 m_CurrentLoopsCount++; 83 m_Delegate.Invoke(); 84 } 85 } 86 } 87 88 /// <summary> 89 /// Get interval 90 /// </summary> 91 public float Interval() { return m_Interval; } 92 93 /// <summary> 94 /// Get total loops count (INFINITE (which is uint.MaxValue) if is constantly looping) 95 /// </summary> 96 public uint LoopsCount() { return m_LoopsCount; } 97 98 /// <summary> 99 /// Get how many loops were completed 100 /// </summary> 101 public uint CurrentLoopsCount() { return m_CurrentLoopsCount; } 102 103 /// <summary> 104 /// Get how many loops remained to completion 105 /// </summary> 106 public uint RemainingLoopsCount() { return m_LoopsCount - m_CurrentLoopsCount; } 107 108 /// <summary> 109 /// Get total duration, (INFINITE if it's constantly looping) 110 /// </summary> 111 public float Duration() { return (m_LoopsCount == INFINITE) ? INFINITE : (m_LoopsCount * m_Interval); } 112 113 /// <summary> 114 /// Get the delegate to execute 115 /// </summary> 116 public Action Delegate() { return m_Delegate; } 117 118 /// <summary> 119 /// Get total remaining time 120 /// </summary> 121 public float RemainingTime() { return (m_LoopsCount == INFINITE && m_Interval > 0f) ? INFINITE : Math.Max(m_LoopsCount * m_Interval - m_ElapsedTime, 0f); } 122 123 /// <summary> 124 /// Get total elapsed time 125 /// </summary> 126 public float ElapsedTime() { return m_ElapsedTime; } 127 128 /// <summary> 129 /// Get elapsed time in current loop 130 /// </summary> 131 public float CurrentCycleElapsedTime() { return m_CurrentCycleElapsedTime; } 132 133 /// <summary> 134 /// Get remaining time in current loop 135 /// </summary> 136 public float CurrentCycleRemainingTime() { return Math.Max(m_Interval - m_CurrentCycleElapsedTime, 0); } 137 138 /// <summary> 139 /// Checks whether this timer is ok to be removed 140 /// </summary> 141 public bool ShouldClear() { return (m_Delegate == null || RemainingTime() == 0); } 142 143 /// <summary> 144 /// Checks if the timer is paused 145 /// </summary> 146 public bool IsPaused() { return m_bIsPaused; } 147 148 /// <summary> 149 /// Pause / Inpause timer 150 /// </summary> 151 public void SetPaused(bool bPause) { m_bIsPaused = bPause; } 152 153 /// <summary> 154 /// Compare frequency (calls per second) 155 /// </summary> 156 public static bool operator >(SmartTimer A, SmartTimer B) { return (A == null || B == null) || A.Interval() < B.Interval(); } 157 158 /// <summary> 159 /// Compare frequency (calls per second) 160 /// </summary> 161 public static bool operator <(SmartTimer A, SmartTimer B) { return (A == null || B == null) || A.Interval() > B.Interval(); } 162 163 /// <summary> 164 /// Compare frequency (calls per second) 165 /// </summary> 166 public static bool operator >=(SmartTimer A, SmartTimer B) { return (A == null || B == null) || A.Interval() <= B.Interval(); } 167 168 /// <summary> 169 /// Compare frequency (calls per second) 170 /// </summary> 171 public static bool operator <=(SmartTimer A, SmartTimer B) { return (A == null || B == null) || A.Interval() >= B.Interval(); } 172 } 173 }
3.SmartTimerComponent 模块Manager:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 5 namespace ETModel 6 { 7 [ObjectSystem] 8 public class SmartTimerComponentAwakeSystem: AwakeSystem<SmartTimerComponent> 9 { 10 public override void Awake(SmartTimerComponent self) 11 { 12 self.Awake(); 13 } 14 } 15 16 [ObjectSystem] 17 public class SmartTimerComponentUpdateSystem: UpdateSystem<SmartTimerComponent> 18 { 19 public override void Update(SmartTimerComponent self) 20 { 21 self.Update(); 22 } 23 } 24 25 public class SmartTimerComponent: Component 26 { 27 // Ensure we only have a single instance of the SmartTimerComponent loaded (singleton pattern). 28 public static SmartTimerComponent Instance = null; 29 private IList<SmartTimer> smartTimers = new List<SmartTimer>(); 30 31 // Whether the game is paused 32 public bool Paused { get; set; } = false; 33 34 public void Awake() 35 { 36 Instance = this; 37 } 38 39 public void Update() 40 { 41 if (this.Paused) 42 return; 43 44 foreach (SmartTimer smartTimer in this.smartTimers.ToArray()) 45 { 46 smartTimer.UpdateTimer(); 47 if (smartTimer.ShouldClear() || smartTimer.IsDisposed) 48 { 49 this.smartTimers.Remove(smartTimer); 50 } 51 } 52 } 53 54 public void Add(SmartTimer smartTimer) 55 { 56 this.smartTimers.Add(smartTimer); 57 } 58 59 public SmartTimer Get(Action action) 60 { 61 foreach (SmartTimer smartTimer in this.smartTimers) 62 { 63 if (smartTimer.Delegate() == action) return smartTimer; 64 } 65 66 return null; 67 } 68 69 public void Remove(SmartTimer smartTimer) 70 { 71 this.smartTimers.Remove(smartTimer); 72 smartTimer.Dispose(); 73 } 74 75 public void Remove(Action action) 76 { 77 foreach (SmartTimer smartTimer in this.smartTimers.ToArray()) 78 { 79 if (smartTimer.Delegate() == action) 80 { 81 Remove(smartTimer); 82 break; 83 } 84 } 85 } 86 87 public int Count => this.smartTimers.Count; 88 89 public override void Dispose() 90 { 91 if (this.IsDisposed) return; 92 base.Dispose(); 93 94 foreach (SmartTimer smartTimer in this.smartTimers) 95 { 96 smartTimer.Dispose(); 97 } 98 this.smartTimers.Clear(); 99 Instance = null; 100 } 101 102 /// <summary> 103 /// Get timer interval. Returns 0 if not found. 104 /// </summary> 105 /// <param name="action">Delegate name</param> 106 public float Interval(Action action) { SmartTimer timer = this.Get(action); return timer?.Interval() ?? 0f; } 107 108 /// <summary> 109 /// Get total loops count (INFINITE (which is uint.MaxValue) if is constantly looping) 110 /// </summary> 111 /// <param name="action">Delegate name</param> 112 public uint LoopsCount(Action action) { SmartTimer timer = this.Get(action); return timer?.LoopsCount() ?? 0; } 113 114 /// <summary> 115 /// Get how many loops were completed 116 /// </summary> 117 /// <param name="action">Delegate name</param> 118 public uint CurrentLoopsCount(Action action) { SmartTimer timer = this.Get(action); return timer?.CurrentLoopsCount() ?? 0; } 119 120 /// <summary> 121 /// Get how many loops remained to completion 122 /// </summary> 123 /// <param name="action">Delegate name</param> 124 public uint RemainingLoopsCount(Action action) { SmartTimer timer = this.Get(action); return timer?.RemainingLoopsCount() ?? 0; } 125 126 /// <summary> 127 /// Get total remaining time 128 /// </summary> 129 /// <param name="action">Delegate name</param> 130 public float RemainingTime(Action action) { SmartTimer timer = this.Get(action); return timer?.RemainingTime() ?? -1f; } 131 132 /// <summary> 133 /// Get total elapsed time 134 /// </summary> 135 /// <param name="action">Delegate name</param> 136 public float ElapsedTime(Action action) { SmartTimer timer = this.Get(action); return timer?.ElapsedTime() ?? -1f; } 137 138 /// <summary> 139 /// Get elapsed time in current loop 140 /// </summary> 141 /// <param name="action">Delegate name</param> 142 public float CurrentCycleElapsedTime(Action action) { SmartTimer timer = this.Get(action); return timer?.CurrentCycleElapsedTime() ?? -1f; } 143 144 /// <summary> 145 /// Get remaining time in current loop 146 /// </summary> 147 /// <param name="action">Delegate name</param> 148 public float CurrentCycleRemainingTime(Action action) { SmartTimer timer = this.Get(action); return timer?.CurrentCycleRemainingTime() ?? -1f; } 149 150 /// <summary> 151 /// Verifies whether the timer exits 152 /// </summary> 153 /// <param name="action">Delegate name</param> 154 public bool IsTimerActive(Action action) { SmartTimer timer = this.Get(action); return timer != null; } 155 156 /// <summary> 157 /// Checks if the timer is paused 158 /// </summary> 159 /// <param name="action">Delegate name</param> 160 public bool IsTimerPaused(Action action) { SmartTimer timer = this.Get(action); return timer?.IsPaused() ?? false; } 161 162 /// <summary> 163 /// Pause / Unpause timer 164 /// </summary> 165 /// <param name="action">Delegate name</param> 166 /// <param name="bPause">true - pause, false - unpause</param> 167 public void SetPaused(Action action, bool bPause) { SmartTimer timer = this.Get(action); if (timer != null) timer.SetPaused(bPause); } 168 169 /// <summary> 170 /// Get total duration, (INFINITE if it's constantly looping) 171 /// </summary> 172 /// <param name="action">Delegate name</param> 173 public float Duration(Action action) { SmartTimer timer = this.Get(action); return timer?.Duration() ?? 0f; } 174 } 175 }
4.SmartTimerFactory 模块工厂:
1 using System; 2 3 namespace ETModel 4 { 5 public static class SmartTimerFactory 6 { 7 public static SmartTimer Create(float interval, uint loopsCount, Action action) 8 { 9 SmartTimer smartTimer = ComponentFactory.Create<SmartTimer, float, uint, Action>(interval, loopsCount, action); 10 SmartTimerComponent smartTimerComponent = Game.Scene.GetComponent<SmartTimerComponent>(); 11 smartTimerComponent.Add(smartTimer); 12 return smartTimer; 13 } 14 } 15 }
5.Example: