using System; using System.Collections.Generic; using AlicizaX.Runtime; using UnityEngine; namespace AlicizaX.Timer.Runtime { public struct TimerInfo { public float Interval; public int Repeat; public float Elapsed; } /// /// 定时器管理器 /// [UnityEngine.Scripting.Preserve] internal sealed class TimerManager : ITimerManager { class TimerItem { public float Interval; public int Repeat; public Action Callback; public object Param; public float Elapsed; public bool Deleted; public void Set(float interval, int repeat, Action callback, object param) { this.Interval = interval; this.Repeat = repeat; this.Callback = callback; this.Param = param; } } private readonly Dictionary, TimerItem> _items = new Dictionary, TimerItem>(); private readonly Dictionary, TimerItem> _toAdd = new Dictionary, TimerItem>(); private readonly List _toRemove = new List(); private readonly List _pool = new List(100); private static readonly object Locker = new object(); /// /// 是否触发回调异常 /// public static bool CatchCallbackExceptions = false; void IModuleUpdate.Update(float elapseSeconds, float realElapseSeconds) { lock (Locker) { Dictionary, TimerItem>.Enumerator enumerator; if (_items.Count > 0) { enumerator = _items.GetEnumerator(); while (enumerator.MoveNext()) { TimerItem timerItem = enumerator.Current.Value; if (timerItem.Deleted) { _toRemove.Add(timerItem); continue; } timerItem.Elapsed += realElapseSeconds; if (timerItem.Elapsed < timerItem.Interval) { continue; } timerItem.Elapsed -= timerItem.Interval; if (timerItem.Elapsed < 0 || timerItem.Elapsed > 0.03f) timerItem.Elapsed = 0; if (timerItem.Repeat > 0) { timerItem.Repeat--; if (timerItem.Repeat == 0) { timerItem.Deleted = true; _toRemove.Add(timerItem); } } // var repeat = i.Repeat; if (timerItem.Callback != null) { if (CatchCallbackExceptions) { try { timerItem.Callback(timerItem.Param); } catch (Exception e) { timerItem.Deleted = true; Debug.LogWarning("Timer: timer(internal=" + timerItem.Interval + ", repeat=" + timerItem.Repeat + ") callback error > " + e.Message); } } else { timerItem.Callback(timerItem.Param); } } } enumerator.Dispose(); } int len = _toRemove.Count; if (len > 0) { for (int k = 0; k < len; k++) { TimerItem i = _toRemove[k]; if (i.Deleted && i.Callback != null) { _items.Remove(i.Callback); ReturnToPool(i); } } _toRemove.Clear(); } if (_toAdd.Count > 0) { enumerator = _toAdd.GetEnumerator(); while (enumerator.MoveNext()) { _items.Add(enumerator.Current.Key, enumerator.Current.Value); } enumerator.Dispose(); _toAdd.Clear(); } } } void IModule.Dispose() { lock (Locker) { this._toRemove.Clear(); this._toAdd.Clear(); this._items.Clear(); } } /// /// 添加一个定时调用的任务 /// /// 间隔时间(以秒为单位) /// 重复次数(0 表示无限重复) /// 要执行的回调函数 /// 回调函数的参数(可选) public void Add(float interval, int repeat, Action callback, object callbackParam = null) { lock (Locker) { if (callback == null) { Debug.LogWarning("timer callback is null, " + interval + "," + repeat); return; } if (_items.TryGetValue(callback, out var t)) { t.Set(interval, repeat, callback, callbackParam); t.Elapsed = 0; t.Deleted = false; return; } if (_toAdd.TryGetValue(callback, out t)) { t.Set(interval, repeat, callback, callbackParam); return; } t = GetFromPool(); t.Interval = interval; t.Repeat = repeat; t.Callback = callback; t.Param = callbackParam; _toAdd[callback] = t; } } /// /// 添加一个只执行一次的任务 /// /// 间隔时间(以秒为单位) /// 要执行的回调函数 /// 回调函数的参数(可选) public void AddOnce(float interval, Action callback, object callbackParam = null) { Add(interval, 1, callback, callbackParam); } /// /// 添加一个每帧更新执行的任务 /// /// 要执行的回调函数 public void AddUpdate(Action callback) { Add(0.001f, 0, callback); } /// /// 添加一个每帧更新执行的任务 /// /// 要执行的回调函数 /// 回调函数的参数 public void AddUpdate(Action callback, object callbackParam) { Add(0.001f, 0, callback, callbackParam); } /// /// 检查指定的任务是否存在 /// /// 要检查的回调函数 /// 存在返回 true,不存在返回 false public bool Exists(Action callback) { lock (Locker) { if (_toAdd.ContainsKey(callback)) { return true; } if (_items.TryGetValue(callback, out var at)) { return !at.Deleted; } return false; } } /// /// 移除指定的任务 /// /// 要移除的回调函数 public void Remove(Action callback) { lock (Locker) { if (_toAdd.TryGetValue(callback, out var t)) { _toAdd.Remove(callback); ReturnToPool(t); } if (_items.TryGetValue(callback, out t)) { t.Deleted = true; } } } private TimerItem GetFromPool() { TimerItem t; int cnt = _pool.Count; if (cnt > 0) { t = _pool[cnt - 1]; _pool.RemoveAt(cnt - 1); t.Deleted = false; t.Elapsed = 0; } else { t = new TimerItem(); } return t; } private void ReturnToPool(TimerItem t) { t.Callback = null; _pool.Add(t); } public int Priority { get => 0; } /// /// 获取所有正在运行的定时器的信息 /// /// 一个列表,其中包含每个定时器的信息 public List GetTimerInfos() { List timerInfos = new List(); lock (Locker) { foreach (var timerItem in _items.Values) { if (!timerItem.Deleted) // 确保定时器未被删除 { timerInfos.Add(new TimerInfo { Interval = timerItem.Interval, Repeat = timerItem.Repeat, Elapsed = timerItem.Elapsed, }); } } } return timerInfos; } } }