简单的时间管理器

    最近在做一个小Demo,发现有很多地方需要延时调用一个方法,或者是一段逻辑才能实现功能。总结起来我感觉最常用的有以下几个。


1.定义 timeCounter 最简单的一种

float timeCounter = 0;  //定义一个时间计时器

private void Update()
{
    timeCounter += Time.deltaTime;   //在update中调用 加上帧间隔时间
    if(timeCounter > 10)
    {
        //TODO;                      //在这里写上需要在 10 秒之后执行的逻辑
    }
}

 这种写法虽然最为方便,但却要一直在update中实时调用,当然你也可以加一个bool,控制流程,但仍需要时时刻刻去做判断。不是一种好的写法。如果只是为了实现一些简单的功能,这种写法还是挺好用的,简单粗暴。

2.Invoke 延时调用

private void Start()
{
    Invoke("ToDo",10);
}

private void ToDo()
{
   //Do Something
}

这种写法也挺简单的,直接定义好逻辑然后在你想要调用的地方,直接 Invoke 就行了,但是有个问题,逻辑必须要额外的封装到一个方法中,且调用的时候需要通过方法的 字符串名称调用的。

3. Coroutines 协程  

//假如在游戏开始时,我需要延时10s做一件事情
private void Start()
{
    StartCoroutine("ToDo");
}


IEnumerator ToDo()
{
    yield return new waitForSecond(10);
    //Do Something;
}

StartCoroutine用来开启协程,StopCoroutine用来终止协程,注意参数必须是1⃣️ IEnumerator 类型的 方法字符串名称 ,如上代码所示。2⃣️还可以这样写 StartCoroutine(ToDo());  但是这种方式 终止协程StopCoroutine(ToDo());有点不太好使,停不下来 ,原因还在寻找中。

这种写法很实用,而且随时开启并随时终止它,易于控制使用灵活。但是逻辑仍然需要额外封装,方法多了略微会降低代码的可读性。而且不停的 new waitForScond ,在优化时也是一个需要处理的很大的消耗项。

4.TimeManager 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;


//创建时间 Timer 类
public class Timer
{
    Action action;               //需要执行的事件
    public bool isEnd = false;   //时间计时结束标志
    float timeCounter = 0;       //时间计时器
    float endTime;               //终止时间

    private Timer() { }

    public Timer(float time, Action action) //构造方法赋值
    {
        timeCounter = 0;
        endTime = time;
        this.action = action;
    }

    public void Update(float dt)       //提供一个公开的 Update 方法 用来计时
    {
        timeCounter += dt;
        if (timeCounter >= endTime)    //当时间计时器 加到 终止时间 的大小时,执行事件
        {
            action();
            isEnd = true;              //标记isEnd = true;
        }
    }
}



//时间管理器。用来管理 Timer 类实例化出来的对象
public class TimeManager
{
     //单例
    private static TimeManager instance;

    public static TimeManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new TimeManager();
            }
            return instance;
        }
    }
     
    List<Timer> timeList = new List<Timer>(); // 创建一个链表 用来存储 Timer 对象

    //Invoke 公开方法  当外界调用时 传入 timer:需要延时的时间。 action:需要执行的事件
    public void Invoke(float timer, Action action) 
    {
        Timer time = new Timer(timer, action); //调用构造时,传入参数
        timeList.Add(time); //将这个 Timer 对象添加进链表中
    }
    
    //提供给外界一个 Update 方法需要实时调用 
    public void Update(float dt)
    {
         //for 循环遍历 字典,执行 链表成员 的update 方法
        for (int i = 0; i < timeList.Count; i++)
        {
            timeList[i].Update(dt);
             //当成员的某一个对象延时调用结束,则将此对象从链表中移除
            if (timeList[i].isEnd)。 
            {
                timeList.Remove(timeList[i]);
            }
        }
    }
   //提供给外界一个清空 链表的 方法
    public void Clear()
    {
        timeList.Clear();
    }

}

自己实现一个TimeManager类来管理Timer对象,当事件执行结束后,该事件所对应的Timer对象也被移除很方便。在使用时需要在一个游戏管理器中的update方法中调用一下 TimeManager.Instance.Update(Time.deltaTime);然后当需要延时调用时,可以像方法2那样将方法封装起来然后 Invoke(10,ToDo); 也可以使用Lambda表达式 Invoke(10,()=>{   //Do Someting  });   的方式来实现。

还可以进一步实现 延时重复调用方法 InvokeRepeat() ,持续时间调用方法 ContinueExecute()  ,等;还可以进一步扩展Timer 对象的类型,使之在不同的游戏状态下,执行不同的延时事件。可扩展性很高,配合游戏管理器来使用很方便。

 

个人见解,如有错误,敬请指正。

 

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ThursdayGame

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值