using System; using System.Collections; using System.Collections.Generic; using UnityEngine; /// /// 每帧检查一次的 可作用于UI的Timer /// public class UITimer : MonoBehaviour { /// /// UI Timer 触发事件风格 /// public enum eTriggerStyle { Once, // 只触发一次事件 执行后自动失效 默认类型 Loop, // 循环触发事件 直到手动关闭 (实际作用次数20亿次) Count, // 指定次数触发事件 直到剩余次数为0自行关闭 } /// /// UI Timer Data /// public class Data { #region member private eTriggerStyle m_Type; // 事件触发风格 private int m_id; // 编号 private int m_space; // 事件触发间隔时长 单位:ms private int m_leftCount; // 时间 private UInt64 m_nextTime; // 下一次触发时间 private Action m_Callback; // 返回值int的类型的事件 #endregion #region property public eTriggerStyle Type { get { return m_Type; } set { m_Type = value; } } public int id { get { return m_id; } set { m_id = value; } } public int space { get { return m_space; } set { m_space = value; } } public int leftCount { get { return m_leftCount; } set { m_leftCount = value; } } public Action CallBack { get { return m_Callback; } set { m_Callback = value; } } public UInt64 nextTime { get { return m_nextTime; } set { m_nextTime = value; } } #endregion #region function public Data(eTriggerStyle _Type, int _id, int _space, int _leftCount, Action _Callback) { Type = _Type; id = _id; space = _space; CallBack += _Callback; if (Type == eTriggerStyle.Once) leftCount = 1; else if (Type == eTriggerStyle.Loop) leftCount = MAX_TRIGGER_COUNT; else leftCount = _leftCount; } public void InitNextTime(UInt64 _curTimerPassTime) { nextTime = _curTimerPassTime + (UInt64)space; } private void RefreshNextTime() { nextTime += (UInt64)space; } public void Run() { if(CallBack != null) CallBack(); leftCount--; if(leftCount > 0) RefreshNextTime(); } #endregion } /// /// 唯一实例 /// private static UITimer m_Instance; private UITimer() { } public static UITimer Instance { get { if (m_Instance == null) Debug.LogError("Error, m_Instance == null."); return m_Instance; } } public static readonly int MAX_TRIGGER_COUNT = 2000000000; private static int s_nextId = 0; #region member private List m_DataLst; private double m_time; // 运行时间 单位:s private List m_NeedRemoveList; #endregion #region property public List DataLst { get { if (m_DataLst == null) m_DataLst = new List(); return m_DataLst; } } public List NeedRemoveList { get { if (m_NeedRemoveList == null) m_NeedRemoveList = new List(); return m_NeedRemoveList; } } private static int NextId { get { return ++s_nextId; } } #endregion #region function void Awake() { m_Instance = this; } void Update() { if (!IsNeedRun()) return; Run(); } /// /// 创建一个Timer /// /// 触发间隔 单位:ms /// 触发回调事件 /// 触发风格 /// 触发次数 _TriggerStyle == eTriggerStyle.Count 有用 /// public Data Create(int _triggerSpace, Action _Callback, eTriggerStyle _TriggerStyle = eTriggerStyle.Once, int _count = 1) { Data vData = new Data(_TriggerStyle, UITimer.NextId, _triggerSpace, _count, _Callback); vData.InitNextTime(GetTimeMs()); InsertData(vData); return vData; } public void Remove(Data _Data) { for(int i = 0; i < DataLst.Count; i++) { if(DataLst[i].id == _Data.id) { DataLst.Remove(DataLst[i]); break; } } if (!IsNeedRun()) Reset(); } private UInt64 GetTimeMs() { UInt64 passMs = Convert.ToUInt64(m_time * 1000); return passMs; } private bool IsNeedRun() { return (DataLst.Count > 0); } void Reset() { m_time = 0.0f; } private void Run() { m_time += Time.deltaTime; NeedRemoveList.Clear(); Trigger(); if (NeedRemoveList.Count <= 0) return; RemoveStopData(); } // 是不是可以用2分插入法优化一下 private void InsertData(Data _Data) { DataLst.Add(_Data); } private void Trigger() { UInt64 curPassTime = GetTimeMs(); for (int i = 0; i < DataLst.Count; i++) { if (DataLst[i].nextTime <= curPassTime) { DataLst[i].Run(); if (DataLst[i].leftCount <= 0) NeedRemoveList.Add(DataLst[i]); } } } private void RemoveStopData() { for(int i = 0; i < NeedRemoveList.Count; i++) { this.Remove(NeedRemoveList[i]); } } #endregion }