using System;
using System.Collections.Generic;
using UnityEngine;
//开发目标:
//支持时间定时,帧定时
//定时任务可循环,可取消,可替换
//使用简单,调用方便
public class TimerSys : MonoBehaviour
{
public static TimerSys Instance;
private static readonly string obj = “lock”;
private int tid;
private List tidLst = new List(); //保存住所有任务的tid
private List recTidLst = new List(); //清除 tid
private List tempTimeLst = new List(); //缓存
private List taskTimeLst = new List();
///
/// 下面是帧定时
///
private int frameCounter;
private List tempFrameLst = new List(); //缓存
private List taskFrameLst = new List();
// Use this for initialization
public void Init()
{
Instance = this;
Debug.Log("TimeSys Init Done");
}
private void Update()
{
CheckTimeTask();
CheckFrameTask();
if (recTidLst.Count > 0)
{
RecycleTid();
}
}
private void CheckTimeTask()
{
//加入缓存区中的定时任务
for (int tmpIndex = 0; tmpIndex < tempTimeLst.Count; tmpIndex++)
{
taskTimeLst.Add(tempTimeLst[tmpIndex]);
}
tempTimeLst.Clear();
//遍历检测任务是否到达条件 TODO
for (int index = 0; index < taskTimeLst.Count; index++)
{
PETimeTask task = taskTimeLst[index];
if (Time.realtimeSinceStartup * 1000 < task.destTime)
{
continue;
}
else
{
Action cb = task.callback;
try
{
if (cb != null)
{
cb();
}
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
//移除已经完成的任务
if (task.count == 1)
{
taskTimeLst.RemoveAt(index);
index--;
recTidLst.Add(task.tid);
}
else
{
if (task.count != 0)
{
task.count -= 1;
}
task.destTime += task.delay;
}
}
}
}
private void CheckFrameTask()
{
//加入缓存区中的定时任务
for (int tmpIndex = 0; tmpIndex < tempFrameLst.Count; tmpIndex++)
{
taskFrameLst.Add(tempFrameLst[tmpIndex]);
}
tempFrameLst.Clear();
frameCounter += 1;
//遍历检测任务是否到达条件 TODO
for (int index = 0; index < taskFrameLst.Count; index++)
{
PEFrameTask task = taskFrameLst[index];
if (frameCounter < task.destFrame)
{
continue;
}
else
{
Action cb = task.callback;
try
{
if (cb != null)
{
cb();
}
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
//移除已经完成的任务
if (task.count == 1)
{
taskFrameLst.RemoveAt(index);
index--;
recTidLst.Add(task.tid);
}
else
{
if (task.count != 0)
{
task.count -= 1;
}
task.destFrame += task.delay;
}
}
}
}
#region TimeTask
///
/// 添加
///
///
///
///
///
///
public int AddTimeTask(Action callback, float delay, PETimeUnit timeUniy = PETimeUnit.Millisecond,int count=1)
{
if (timeUniy != PETimeUnit.Millisecond)
{
switch (timeUniy)
{
case PETimeUnit.Second:
delay = delay * 1000;
break;
case PETimeUnit.Minute:
delay = delay * 1000 * 60;
break;
case PETimeUnit.Hour:
delay = delay * 1000 * 60 * 60;
break;
case PETimeUnit.Day:
delay = delay * 1000 * 60 * 60 * 24;
break;
default:
Debug.Log("Add Task TimeUnity Type Error...");
break;
}
}
int tid=GetTid();
float destTime = Time.realtimeSinceStartup * 1000 + delay;
tempTimeLst.Add(new PETimeTask(tid,callback, destTime, delay, count));
tidLst.Add(tid);
return tid;
}
///
/// 删除
///
///
///
public bool DelelteTimeTask(int tid)
{
bool exist = false;
for (int i = 0; i < taskTimeLst.Count; i++)
{
PETimeTask task = taskTimeLst[i];
if (task.tid == tid)
{
taskTimeLst.RemoveAt(i);
for (int j = 0; j < tidLst.Count; j++)
{
if (tidLst[j] == tid)
{
tidLst.RemoveAt(i);
break;
}
}
exist = true;
break;
}
}
if (!exist)
{
for (int i = 0; i < tempTimeLst.Count; i++)
{
PETimeTask task = tempTimeLst[i];
if (task.tid == tid)
{
tempTimeLst.RemoveAt(i);
for (int j = 0; j < tidLst.Count; j++)
{
if (tidLst[j] == tid)
{
tidLst.RemoveAt(i);
break;
}
}
exist = true;
break;
}
}
}
return exist;
}
///
/// 替换
///
///
///
///
///
///
///
public bool ReplaceTimeTask(int tid, Action callback, float delay, PETimeUnit timeUniy = PETimeUnit.Millisecond, int count = 1)
{
if (timeUniy != PETimeUnit.Millisecond)
{
switch (timeUniy)
{
case PETimeUnit.Second:
delay = delay * 1000;
break;
case PETimeUnit.Minute:
delay = delay * 1000 * 60;
break;
case PETimeUnit.Hour:
delay = delay * 1000 * 60 * 60;
break;
case PETimeUnit.Day:
delay = delay * 1000 * 60 * 60 * 24;
break;
default:
Debug.Log("Add Task TimeUnity Type Error...");
break;
}
}
float destTime = Time.realtimeSinceStartup * 1000 + delay;
PETimeTask newTask = new PETimeTask(tid, callback, destTime, delay, count);
bool isRep = false;
for (int i = 0; i < taskTimeLst.Count; i++)
{
if (taskTimeLst[i].tid == tid)
{
taskTimeLst[i] = newTask;
isRep = true;
break;
}
}
if (!isRep)
{
for (int i = 0; i < tempTimeLst.Count; i++)
{
if (tempTimeLst[i].tid == tid)
{
tempTimeLst[i] = newTask;
isRep = true;
break;
}
}
}
return isRep;
}
#endregion
#region FrameTask
///
/// 添加
///
///
///
///
///
///
public int AddFrameTask(Action callback, int delay, int count = 1)
{
int tid = GetTid();
tempFrameLst.Add(new PEFrameTask(tid, callback, frameCounter+delay, delay, count));
tidLst.Add(tid);
return tid;
}
///
/// 删除
///
///
///
public bool DelelteFrameTask(int tid)
{
bool exist = false;
for (int i = 0; i < taskFrameLst.Count; i++)
{
PEFrameTask task = taskFrameLst[i];
if (task.tid == tid)
{
taskFrameLst.RemoveAt(i);
for (int j = 0; j < tidLst.Count; j++)
{
if (tidLst[j] == tid)
{
tidLst.RemoveAt(i);
break;
}
}
exist = true;
break;
}
}
if (!exist)
{
for (int i = 0; i < tempFrameLst.Count; i++)
{
PEFrameTask task = tempFrameLst[i];
if (task.tid == tid)
{
tempFrameLst.RemoveAt(i);
for (int j = 0; j < tidLst.Count; j++)
{
if (tidLst[j] == tid)
{
tidLst.RemoveAt(i);
break;
}
}
exist = true;
break;
}
}
}
return exist;
}
///
/// 替换
///
///
///
///
///
///
///
public bool ReplaceFrameTask(int tid, Action callback, int delay, int count = 1)
{
PEFrameTask newTask = new PEFrameTask(tid, callback, frameCounter+ delay, delay, count);
bool isRep = false;
for (int i = 0; i < taskFrameLst.Count; i++)
{
if (taskFrameLst[i].tid == tid)
{
taskFrameLst[i] = newTask;
isRep = true;
break;
}
}
if (!isRep)
{
for (int i = 0; i < tempFrameLst.Count; i++)
{
if (tempFrameLst[i].tid == tid)
{
tempFrameLst[i] = newTask;
isRep = true;
break;
}
}
}
return isRep;
}
#endregion
#region Tool Methonds
private int GetTid()
{
lock (obj)
{
tid += 1;
//安全代码,以防万一
while (true)
{
if (tid == int.MaxValue)
{
tid = 0;
}
bool used = false;
for (int i = 0; i < tidLst.Count; i++)
{
if (tid == tidLst[i])
{
used = true;
break;
}
}
if (!used)
{
break;
}
else
{
tid += 1;
}
}
}
return tid;
}
private void RecycleTid()
{
for (int i = 0; i < recTidLst.Count; i++)
{
int tid = recTidLst[i];
for (int j = 0; j < tidLst.Count; j++)
{
if (tidLst[j] == tid)
{
tidLst.RemoveAt(j);
break;
}
}
}
recTidLst.Clear();
}
#endregion
}
public class PETimeTask
{
public int tid;
public Action callback; //执行什么
public float destTime;//目标执行时间
public float delay; //这个是再次加上时间
public int count;//执行次数
public PETimeTask(int tid, Action callback, float destTime, float delay, int count)
{
this.callback = callback;
this.destTime = destTime;
this.delay = delay;
this.count = count;
this.tid = tid;
}
}
public class PEFrameTask
{
public int tid;
public Action callback; //执行什么
public int destFrame;//目标执行时间
public int delay; //这个是再次加上时间
public int count;//执行次数
public PEFrameTask(int tid, Action callback, int destFrame, int delay, int count)
{
this.callback = callback;
this.destFrame = destFrame;
this.delay = delay;
this.count = count;
this.tid = tid;
}
}
public enum PETimeUnit
{
Millisecond,
Second,
Minute,
Hour,
Day
}
///////////////////////////////////////////////////////////////////////////////////
在使用的脚本初始化里面加上
TimerSys timer = GetComponent();
timer.Init();
下面是这个脚本里的一些方法
第一个参数:传过来的函数
第二个参数:每隔多少时间执行一次
第三个参数:是个时间枚举
第四个参数:是执行几次,默认参数是1, 写0表示一直执行
返回值:是任务的ID
TimerSys.Instance.AddTimeTask();//添加定时任务
第一个参数:是任务的ID
TimerSys.Instance.DelelteTimeTask();//删除定时任务
第一个参数:是任务的ID
第二个参数:传过来的函数
第三个参数:每隔多少时间执行一次
第四个参数:是个时间枚举
第五个参数:是执行几次,默认参数是1, 写0表示一直执行
TimerSys.Instance.ReplaceTimeTask();//替换定时任务
第一个参数:传过来的函数
第二个参数:每隔多少时间执行一次
第三个参数:是执行几次,默认参数是1, 写0表示一直执行
TimerSys.Instance.AddFrameTask();//添加帧定时任务
第一个参数:是任务的ID
TimerSys.Instance.DelelteFrameTask();//删除帧定时任务
第一个参数:是任务的ID
第二个参数:传过来的函数
第三个参数:每隔多少时间执行一次
第四个参数:是执行几次,默认参数是1, 写0表示一直执行
TimerSys.Instance.ReplaceFrameTask();//替换帧定时任务
感谢Plane老师