Unity中计时器管理类
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
该文中的计时器是基于Unity的生命周期中Update的实现通过Time.deltaTime的累加作为计数器将需要定时的对象类根据延长的时间排序不用每一次Update时都对列表进行操作。
代码记录留做之后扩展使用
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestTimeManger : MonoBehaviour
{
protected static List<TimerComponent> componentsList = new List<TimerComponent>();
protected static int _tagCount = 1000; //标签的初始值
private bool isBackground = false; //是否可以在后台运行
private float initTime = 0f; //初始时间
float dt = 0; //刷新时间
private static TestTimeManger _instance;
public static TestTimeManger Instance
{
get
{
return _instance;
}
}
private void Awake()
{
if (_instance == null)
{
_instance = this;
}
}
void Start()
{
dt = Time.deltaTime;
}
private void Update()
{
initTime += dt;
if (componentsList.Count > 0)
{
if (componentsList[0].life <= initTime)
{
for (int i = 0; i < componentsList.Count; i++)
{
if (componentsList[i].life <= initTime)
{
componentsList[i].func();
if (componentsList[i].count == -1)
{
componentsList[i].life += componentsList[i].interval;
}
else if (componentsList[i].count == 1)
{
componentsList.Remove(componentsList[i]);
}
else
{
componentsList[i].count -= 1;
componentsList[i].life += componentsList[i].interval;
}
}
}
HeapSortFunction();
}
}
}
/// <summary>
/// 注册一个定时器
/// </summary>
/// <param name="interval">间隔 单位秒</param>
/// <param name="func">调度方法</param>
/// <param name="times">循环次数 times{ 0 | < 1 }:一直循环</param>
/// <returns></returns>
public int SetInterval(float interval, Action func, int times = 1)
{
var scheduler = new TimerComponent();
scheduler.life = initTime + interval;
scheduler.interval = interval;
scheduler.func = func;
scheduler.count = times;
scheduler.tag = ++_tagCount;
componentsList.Add(scheduler);
HeapSortFunction();
return _tagCount;
}
/// <summary>
/// 通过tag获取定时器的对象
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public TimerComponent GetTimer(int tag)
{
for (int i = 0; i < componentsList.Count; i++)
{
if (tag == componentsList[i].tag)
{
return componentsList[i];
}
}
return null;
}
/// <summary>
/// 清空计时器
/// </summary>
/// <param name="tag"></param>
public void ClearTime(int tag)
{
for (int i = 0; i < componentsList.Count; i++)
{
if (tag == componentsList[i].tag)
{
componentsList.Remove(componentsList[i]);
Debug.LogError("ClearTimer " + tag + " " + componentsList.Count);
return;
}
}
}
/// <summary>
/// 清空所有计时器
/// </summary>
public void ClearTimers()
{
componentsList.Clear();
}
/// <summary>
/// 堆排序
/// </summary>
public void HeapSortFunction()
{
BuildMaxHeap();
for (int i = componentsList.Count - 1; i > 0; i--)
{
Tuple<TimerComponent, TimerComponent> tuple = Swap(componentsList[0], componentsList[i]); //将堆顶元素依次与无序区的最后一位交换使堆顶元素进入有序区
componentsList[0] = tuple.Item1;
componentsList[i] = tuple.Item2;
MaxHeapify(0, i); //重新将无序区调整为大顶堆
}
}
///<summary>
/// 创建大顶推根节点大于左右子节点
///</summary>
///<param name="array">待排数组</param>
private void BuildMaxHeap()
{
//根据大顶堆的性质可知数组的前半段的元素为根节点其余元素都为叶节点
for (int i = componentsList.Count / 2 - 1; i >= 0; i--) //从最底层的最后一个根节点开始进行大顶推的调整
{
MaxHeapify(i, componentsList.Count); //调整大顶堆
}
}
/// <summary>
/// 进行堆排序
/// </summary>
private void MaxHeapify(int currentIndex, int heapSize)
{
int left = 2 * currentIndex + 1; //左子节点在数组中的位置
int right = 2 * currentIndex + 2; //右子节点在数组中的位置
int large = currentIndex; //记录此根节点、左子节点、右子节点 三者中最大值的位置
if (left < heapSize && componentsList[left].life > componentsList[large].life) //与左子节点进行比较
{
large = left;
}
if (right < heapSize && componentsList[right].life > componentsList[large].life) //与右子节点进行比较
{
large = right;
}
if (currentIndex != large) //如果 currentIndex != large 则表明 large 发生变化即左右子节点中有大于根节点的情况
{
Tuple<TimerComponent, TimerComponent> tuple = Swap(componentsList[currentIndex], componentsList[large]); //将堆顶元素依次与无序区的最后一位交换使堆顶元素进入有序区
componentsList[currentIndex] = tuple.Item1;
componentsList[large] = tuple.Item2;
MaxHeapify(large, heapSize); //以上次调整动作的large位置为此次调整的根节点位置进行递归调整
}
}
/// <summary>
/// 交换位置
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
private Tuple<TimerComponent, TimerComponent> Swap(TimerComponent a, TimerComponent b)
{
TimerComponent temp = null;
temp = a;
a = b;
b = temp;
return Tuple.Create(a, b);
}
}
public class TimerComponent
{
public int tag; //自生的唯一标识
public float life; //生命周期时长
public float interval; //间隔时长
public int count; //调用次数
public Action func; //回调方法
}
测试代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
int ab1 = TestTimeManger.Instance.SetInterval(5, () =>
{
Debug.LogError("1111111111111");
}, 1);
int ab2 = TestTimeManger.Instance.SetInterval(4f, () =>
{
TestTimeManger.Instance.ClearTime(ab1);
Debug.LogError("222222222");
}, 2);
int ab3 = TestTimeManger.Instance.SetInterval(3f, () =>
{
Debug.LogError("333333");
}, -1);
}
// Update is called once per frame
void Update()
{
}
}