/* author: YKMoon * 计时器 */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; namespace YKMoon { internal abstract class ABaseTimer { protected float time; protected bool unscaled = false; public ABaseTimer(float time, bool unscaled = false) { this.time = time; this.unscaled = unscaled; } public virtual void Update(float deltaTime, float unscaledDeltaTime) { if(time > 0) { time -= unscaled ? unscaledDeltaTime : deltaTime; } } public abstract void OnTimeUp(); public virtual bool IsTimeUp() { return time <= 0; } } internal class UTimerEvent : ABaseTimer { private System.Action timeupEvent; public UTimerEvent(System.Action timeupEvent, float time, bool unscaled = false) : base(time, unscaled) { this.timeupEvent = timeupEvent; } public override void OnTimeUp() { timeupEvent?.Invoke(); } } internal class UTimerEvent : ABaseTimer { private System.Action timeupEvent; private T parameter; public UTimerEvent(System.Action timeupEvent, T parameter, float time, bool unscaled = false) : base(time, unscaled) { this.timeupEvent = timeupEvent; this.parameter = parameter; } public override void OnTimeUp() { timeupEvent?.Invoke(parameter); } } internal class UTimerEvent : ABaseTimer { public System.Action timeupEvent; public T parameter1; public V parameter2; public UTimerEvent(System.Action timeupEvent, T parameter1, V parameter2, float time, bool unscaled = false) : base(time, unscaled) { this.timeupEvent = timeupEvent; this.parameter1 = parameter1; this.parameter2 = parameter2; } public override void OnTimeUp() { timeupEvent?.Invoke(parameter1, parameter2); } } internal class UTimerEvent : ABaseTimer { public System.Action timeupEvent; public T parameter1; public V parameter2; public K parameter3; public UTimerEvent(System.Action timeupEvent, T parameter1, V parameter2, K parameter3, float time, bool unscaled = false) : base(time, unscaled) { this.timeupEvent = timeupEvent; this.parameter1 = parameter1; this.parameter2 = parameter2; this.parameter3 = parameter3; } public override void OnTimeUp() { timeupEvent?.Invoke(parameter1, parameter2, parameter3); } } /// /// 延迟事件管理 /// public class YKTimerManager : USingletonMono, IUSingletonEventHandler { private Dictionary delayEvents = new Dictionary(); private IDGenerator iDGeneratorDelay = new IDGenerator(200000); public void OnCreateSingleton() { Init(); } public void Init() { delayEvents.Clear(); iDGeneratorDelay.Clear(); } private void Update() { var dict = DictPool.Get(); foreach(var pair in delayEvents) { dict.Add(pair.Key, pair.Value); } var removeList = QueuePool.Get(); foreach(var e in dict) { if(!e.Value.IsTimeUp()) { e.Value.Update(Time.deltaTime, Time.unscaledDeltaTime); } else { removeList.Enqueue(e.Key); } } while(removeList.Count > 0) { RemoveDelayEvent(removeList.Dequeue(), true); } QueuePool.Release(removeList); DictPool.Release(dict); } private int AddNewTimer(ABaseTimer newEvent) { int id = iDGeneratorDelay.GetNextUIId(); delayEvents.Add(id, newEvent); return id; } #region DelayEvent /// /// 添加延迟事件 /// /// 延迟事件 /// 延迟时间 /// 是否忽略TimeScale /// 延迟事件ID,可用这个ID注销事件 public int AddDelayEvent(System.Action delayEvent, float delay, bool isUnScaled = false) { var newEvent = new UTimerEvent(delayEvent, delay, isUnScaled); return AddNewTimer(newEvent); } /// /// 添加延迟事件 /// /// 参数类型 /// 延迟事件 /// 事件参数 /// 延迟时间 /// 是否忽略TimeScale /// 延迟事件ID,可用这个ID注销事件 public int AddDelayEvent(System.Action delayEvent, T param, float delay, bool isUnScaled = false) { var newEvent = new UTimerEvent(delayEvent, param, delay, isUnScaled); return AddNewTimer(newEvent); } /// /// 添加延迟事件 /// /// 参数类型1 /// 参数类型2 /// 延迟事件 /// 事件参数1 /// 事件参数2 /// 延迟时间 /// 是否忽略TimeScale /// 延迟事件ID,可用这个ID注销事件 public int AddDelayEvent(System.Action delayEvent, T param1, V param2, float delay, bool isUnScaled = false) { var newEvent = new UTimerEvent(delayEvent, param1, param2, delay, isUnScaled); return AddNewTimer(newEvent); } /// /// 添加延迟事件 /// /// 参数类型1 /// 参数类型2 /// 参数类型3 /// 延迟事件 /// 事件参数1 /// 事件参数2 /// 事件参数3 /// 延迟时间 /// 是否忽略TimeScale /// 延迟事件ID,可用这个ID注销事件 public int AddDelayEvent(System.Action delayEvent, T param1, V param2, K param3, float delay, bool isUnScaled = false) { var newEvent = new UTimerEvent(delayEvent, param1, param2, param3, delay, isUnScaled); return AddNewTimer(newEvent); } /// /// 删除延迟事件 /// /// 事件ID /// 是否在删除过程中调用事件 public void RemoveDelayEvent(int id, bool callEvent = false) { if(delayEvents.ContainsKey(id)) { if(callEvent) { delayEvents[id].OnTimeUp(); } delayEvents.Remove(id); iDGeneratorDelay.RemoveId(id); } } #endregion } }