292 lines
6.4 KiB
C#
292 lines
6.4 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
|
|
/// <summary>
|
|
/// 每帧检查一次的 可作用于UI的Timer
|
|
/// </summary>
|
|
public class UITimer : MonoBehaviour {
|
|
|
|
/// <summary>
|
|
/// UI Timer 触发事件风格
|
|
/// </summary>
|
|
public enum eTriggerStyle
|
|
{
|
|
Once, // 只触发一次事件 执行后自动失效 默认类型
|
|
Loop, // 循环触发事件 直到手动关闭 (实际作用次数20亿次)
|
|
Count, // 指定次数触发事件 直到剩余次数为0自行关闭
|
|
}
|
|
|
|
/// <summary>
|
|
/// UI Timer Data
|
|
/// </summary>
|
|
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
|
|
}
|
|
|
|
/// <summary>
|
|
/// 唯一实例
|
|
/// </summary>
|
|
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<Data> m_DataLst;
|
|
|
|
private double m_time; // 运行时间 单位:s
|
|
|
|
private List<Data> m_NeedRemoveList;
|
|
|
|
#endregion
|
|
|
|
#region property
|
|
|
|
public List<Data> DataLst {
|
|
|
|
get
|
|
{
|
|
if (m_DataLst == null)
|
|
m_DataLst = new List<Data>();
|
|
return m_DataLst;
|
|
}
|
|
|
|
}
|
|
|
|
public List<Data> NeedRemoveList
|
|
{
|
|
get
|
|
{
|
|
if (m_NeedRemoveList == null)
|
|
m_NeedRemoveList = new List<Data>();
|
|
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建一个Timer
|
|
/// </summary>
|
|
/// <param name="_triggerSpace">触发间隔 单位:ms</param>
|
|
/// <param name="_Callback">触发回调事件</param>
|
|
/// <param name="_TriggerStyle">触发风格</param>
|
|
/// <param name="_count">触发次数 _TriggerStyle == eTriggerStyle.Count 有用</param>
|
|
/// <returns></returns>
|
|
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
|
|
}
|
|
|
|
|