AkiraPixelWind/Assets/Scripts/Main/UI/UIYYControl/UITimer.cs
2022-12-29 18:20:40 +08:00

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
}