首先来尝试MonoBehaviour类
首先新建一个PERrame 和PETime 按时间和按帧统计类
using System;
using UnityEngine;
public class PEFrameTask
{
public int tid;//全局唯一的ID
public Action callBack;//执行方法
public int dastFrame; //目标帧
public int delay; //延迟时间
public int count;//执行次数 0 是死循环
public PEFrameTask(int tid, Action callBack, int dastFrame, int delay, int count)
{
this.tid = tid;
this.callBack = callBack;
this.dastFrame = dastFrame;
this.delay = delay;
this.count = count;
}
}public class PETimeTask
{
public int tid;//全局唯一的ID
public Action callBack;//执行方法
public double dastTime; //单位是毫秒
public float delay; //延迟时间
public int count;//执行次数 0 是死循环
public PETimeTask(int tid, Action callBack, double dastTime, float delay, int count)
{
this.tid = tid;
this.callBack = callBack;
this.dastTime = dastTime;
this.delay = delay;
this.count = count;
}
}
public enum PETimeUnit
{
Millisecond, //毫秒
Second,//秒
Minute,//分钟
Hour,//小时
Day,//天
}
然后新建PETimer核心类
using System;
using System.Collections.Generic;
public class PETimer
{
private DateTime startDateTime = new DateTime(1070, 1, 1, 0, 0, 0);
private Action<string> taskLog;
private static readonly string obj = "lock";
private double nowTime;
private int tid;
private List<PETimeTask> tempTimeList = new List<PETimeTask>();
private List<PETimeTask> taskTimeList = new List<PETimeTask>();
private List<int> recTidList = new List<int>();
private List<int> tidList = new List<int>();
private List<PEFrameTask> tempFrameList = new List<PEFrameTask>();
private List<PEFrameTask> taskFrameList = new List<PEFrameTask>();
private int frameCounter; //当前帧
public PETimer()
{
taskFrameList.Clear();
tempFrameList.Clear();
tidList.Clear();
recTidList.Clear();
taskTimeList.Clear();
tempTimeList.Clear();
}
public void SetLog(Action<string> log)
{
taskLog = log;
}
public void LogInfo(string info)
{
if (taskLog != null)
{
taskLog(info);
}
}
public void Update()
{
CheckTimeTask();
CheckFrameTask();
if (recTidList.Count > 0)
{
RecycleTid();
}
}
#region TimeTask
public void CheckTimeTask()
{
//加入缓存区中的定时任务
for (int i = 0; i < tempTimeList.Count; i++)
{
taskTimeList.Add(tempTimeList[i]);
}
tempTimeList.Clear();
nowTime = GetUTCMillisecoonds();
for (int index = 0; index < taskTimeList.Count; index++)
{
PETimeTask task = taskTimeList[index];
if (nowTime.CompareTo(task.dastTime)< 0)
{
continue;
}
else
{
Action cb = task.callBack;
try
{
if (cb != null)
{
cb();
}
}
catch (Exception e)
{
LogInfo(e.ToString());
}
if (task.count == 1)
{
//移除已完成的任务
taskTimeList.RemoveAt(index);
//移除以后 索引向下移动一位
index--;
recTidList.Add(task.tid);
}
else
{
if (task.count != 0)
{
task.count -= 1;
}
task.dastTime += task.delay;
}
}
}
}
public int AddTimeTask(Action callBack, float delay, PETimeUnit timeUnit = PETimeUnit.Millisecond, int count = 1)
{
if (timeUnit != PETimeUnit.Millisecond)
{
switch (timeUnit)
{
case PETimeUnit.Day:
delay = delay * 1000 * 60 * 60 * 24;
break;
case PETimeUnit.Hour:
delay = delay * 1000 * 60 * 60;
break;
case PETimeUnit.Minute:
delay = delay * 1000;
break;
case PETimeUnit.Second:
delay = delay * 1000 * 60;
break;
default:
LogInfo("Add task TimeUnit Type Error... ");
break;
}
}
//从启动游戏的时间 + 延迟时间
double destTime = GetUTCMillisecoonds() + delay;
int tid = GetTid();
tempTimeList.Add(new PETimeTask(tid, callBack, destTime, delay, count));
tidList.Add(tid);
LogInfo("Add Time Task");
return tid;
}
public bool DelTimeTask(int tid)
{
bool exist = false;
for (int i = 0; i < taskTimeList.Count; i++)
{
PETimeTask task = taskTimeList[i];
if (task.tid == tid)
{
taskTimeList.RemoveAt(i);
for (int j = 0; j < tidList.Count; j++)
{
if (tidList[i] == tid)
{
tidList.RemoveAt(j);
break;
}
}
exist = true;
break;
}
}
if (!exist)
{
for (int i = 0; i < tempTimeList.Count; i++)
{
PETimeTask task = tempTimeList[i];
if (task.tid == tid)
{
tempTimeList.RemoveAt(i);
for (int j = 0; j < tidList.Count; j++)
{
if (tidList[i] == tid)
{
tidList.RemoveAt(j);
break;
}
}
exist = true;
break;
}
}
}
return exist;
}
public bool ReplaceTimeTask(int tid, Action callBack, float delay, PETimeUnit timeUnit = PETimeUnit.Millisecond, int count = 1)
{
if (timeUnit != PETimeUnit.Millisecond)
{
switch (timeUnit)
{
case PETimeUnit.Day:
delay = delay * 1000 * 60 * 60 * 24;
break;
case PETimeUnit.Hour:
delay = delay * 1000 * 60 * 60;
break;
case PETimeUnit.Minute:
delay = delay * 1000;
break;
case PETimeUnit.Second:
delay = delay * 1000 * 60;
break;
default:
LogInfo("Add task TimeUnit Type Error... ");
break;
}
}
//从启动游戏的时间 + 延迟时间
double destTime = GetUTCMillisecoonds() + delay;
PETimeTask newTask = new PETimeTask(tid, callBack, destTime, delay, count);
bool exist = false;
for (int i = 0; i < taskTimeList.Count; i++)
{
PETimeTask task = taskTimeList[i];
if (task.tid == tid)
{
taskTimeList[i] = newTask;
exist = true;
break;
}
}
if (!exist)
{
for (int i = 0; i < tempTimeList.Count; i++)
{
PETimeTask task = tempTimeList[i];
if (task.tid == tid)
{
tempTimeList[i] = newTask;
exist = true;
break;
}
}
}
return exist;
}
#endregion
#region FrameTask
public void CheckFrameTask()
{
//加入缓存区中的定时任务
for (int i = 0; i < tempFrameList.Count; i++)
{
taskFrameList.Add(tempFrameList[i]);
}
tempFrameList.Clear();
frameCounter += 1;
for (int index = 0; index < taskFrameList.Count; index++)
{
PEFrameTask task = taskFrameList[index];
if (frameCounter < task.dastFrame)
{
continue;
}
else
{
Action cb = task.callBack;
try
{
if (cb != null)
{
cb();
}
}
catch (Exception e)
{
LogInfo(e.ToString());
}
if (task.count == 1)
{
//移除已完成的任务
taskFrameList.RemoveAt(index);
//移除以后 索引向下移动一位
index--;
recTidList.Add(task.tid);
}
else
{
if (task.count != 0)
{
task.count -= 1;
}
task.dastFrame += task.delay;
}
}
}
}
public int AddFrameTask(Action callBack, int delay, int count = 1)
{
int tid = GetTid();
tempFrameList.Add(new PEFrameTask(tid, callBack, frameCounter + delay, delay, count));
tidList.Add(tid);
LogInfo("Add Time Task");
return tid;
}
public bool DelFrameTask(int tid)
{
bool exist = false;
for (int i = 0; i < taskFrameList.Count; i++)
{
PEFrameTask task = taskFrameList[i];
if (task.tid == tid)
{
taskFrameList.RemoveAt(i);
for (int j = 0; j < tidList.Count; j++)
{
if (tidList[i] == tid)
{
tidList.RemoveAt(j);
break;
}
}
exist = true;
break;
}
}
if (!exist)
{
for (int i = 0; i < tempFrameList.Count; i++)
{
PEFrameTask task = tempFrameList[i];
if (task.tid == tid)
{
tempFrameList.RemoveAt(i);
for (int j = 0; j < tidList.Count; j++)
{
if (tidList[i] == tid)
{
tidList.RemoveAt(j);
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 exist = false;
for (int i = 0; i < taskFrameList.Count; i++)
{
PEFrameTask task = taskFrameList[i];
if (task.tid == tid)
{
taskFrameList[i] = newTask;
exist = true;
break;
}
}
if (!exist)
{
for (int i = 0; i < tempTimeList.Count; i++)
{
PETimeTask task = tempTimeList[i];
if (task.tid == tid)
{
tempFrameList[i] = newTask;
exist = true;
break;
}
}
}
return exist;
}
#endregion
#region Tool Methonds
//回收ID
public void RecycleTid()
{
for (int i = 0; i < recTidList.Count; i++)
{
int tid = recTidList[i];
for (int j = 0; j < tidList.Count; j++)
{
if (tidList[j] == tid)
{
//删除tidList中的数据
tidList.RemoveAt(j);
break;
}
}
}
recTidList.Clear();
}
private int GetTid()
{
lock (obj)
{
tid += 1;
while (true)
{
//安全代码以防万一
if (tid == int.MaxValue)
{
tid = 0;
}
bool used = false;
for (int i = 0; i < tidList.Count; i++)
{
if (tid == tidList[i])
{
used = true;
break;
}
}
if (!used)
{
break;
}
else
{
tid += 1;
}
}
}
return tid;
}
private double GetUTCMillisecoonds()
{
// DateTime.UtcNow 世界标准时间
TimeSpan ts = DateTime.UtcNow - startDateTime;
//计算元年 到现在的毫秒数?
return ts.TotalMilliseconds;
}
#endregion
}
添加扩展类 添加计时器和方法
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///计时器系统
//开发目标
//支持时间的定时,帧定时
//定时任务可循环,可取消 可替换
//使用简单 调用方便
public class TimerSystem : MonoBehaviour
{
public static TimerSystem Instance;
public PETimer pt;
public void InitSystem()
{
Instance = this;
pt = new PETimer();
pt.SetLog((string info) =>
{
Debug.Log("PETimerLog:" + info);
});
Debug.Log("TimerSys Init Done.");
}
void Update()
{
pt.Update();
}
#region TimeTask
private void CheckTimeTask()
{
pt.CheckTimeTask();
}
public int AddTimeTask(Action callBack, float delay, PETimeUnit timeUnit = PETimeUnit.Millisecond, int count = 1)
{
return pt.AddTimeTask(callBack, delay, timeUnit, count);
}
public bool DelTimeTask(int tid)
{
return pt.DelTimeTask(tid);
}
public bool ReplaceTimeTask(int tid, Action callBack, float delay, PETimeUnit timeUnit = PETimeUnit.Millisecond, int count = 1)
{
return pt.ReplaceTimeTask(tid, callBack, delay, timeUnit, count);
}
#endregion
#region FrameTask
public void CheckFrameTask()
{
pt.CheckFrameTask();
}
public int AddFrameTask(Action callBack, int delay, int count = 1)
{
return pt.AddFrameTask(callBack, delay, count);
}
public bool DelFrameTask(int tid)
{
return pt.DelFrameTask(tid);
}
public bool ReplaceFrameTask(int tid, Action callBack, int delay, int count = 1)
{
return pt.ReplaceFrameTask(tid, callBack, delay, count);
}
#endregion
}
Test演示类 添加删除替换计时器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameRoot : MonoBehaviour
{
TimerSystem timerSystem;
private void Start()
{
timerSystem = GetComponent<TimerSystem>();
timerSystem.InitSystem();
}
private int tid;
public void ClickAddButton()
{
tid = TimerSystem.Instance.AddTimeTask(() =>
{
Debug.Log(" debug " + " log A " + " Id : " + tid + "Now " + System.DateTime.Now);
}, 500, PETimeUnit.Millisecond, 0);
}
public void ClickDelButton()
{
bool IsDelete = TimerSystem.Instance.DelTimeTask(tid);
Debug.Log("删除" + IsDelete + " 删除的ID为: " + tid);
}
public void ClickRepButton()
{
bool IsDelete = TimerSystem.Instance.ReplaceTimeTask(tid, FuncB, 2000, PETimeUnit.Millisecond, 0);
Debug.Log("替换任务" + IsDelete + " 替换的ID为: " + tid);
}
void FuncA()
{
Debug.Log(" debug " + " log A " + " Id : " + tid);
}
void FuncB()
{
Debug.Log(" debug " + " log B " + " Id : " + tid);
}
public void ClickAddFrameButton()
{
tid = TimerSystem.Instance.AddFrameTask(() =>
{
Debug.Log(" debug " + " log A " + " Id : " + tid + "Now " + System.DateTime.Now);
}, 60, 0);
}
public void ClickDelFrameButton()
{
bool IsDelete = TimerSystem.Instance.DelFrameTask(tid);
Debug.Log("删除" + IsDelete + " 删除的ID为: " + tid);
}
public void ClickRepReameButton()
{
bool IsDelete = TimerSystem.Instance.ReplaceFrameTask(tid, FuncB, 100, 0);
Debug.Log("替换任务" + IsDelete + " 替换的ID为: " + tid);
}
}
如果是脱离MonoBehaviour的话 可以开启线程然后死循环 自己可以修改 并不复杂哦