最近,整理项目框架逻辑时,无意中翻到n年前封装的延迟回调管理器,就拎出来说道说道:

  先说一下系统提供的几种常用的延迟回调方式:

1)Invoke(Invoke、CancelInvoke):首先需要继承自MonoBehaviour,其次使用的是函数名作为参数调用,比较麻烦,容易出错(运行时才会审查,编译检查不到);
2)Coroutine(StartCoroutine、StopCoroutine):仍然继承自MonoBehaviour,调用时可以使用函数名,也可以直接传入委托,效率上不高,每次调用都会牵扯到额外的堆内存分配,并且所挂载的游戏对象状态不能被打断,否则执行也会被打断;
3、Update:依赖MonoBehaviour,每次调用需要单独申请变量,重写逻辑,也会因状态打断而停止执行;
在不使用插件的情况下,索性进行一些封装,综合各自的优点,去其糟粕:

public class InvokeManager
{
private InvokeManager() //泛型单件
{
timeDelayLst = new List<float>();
timeStateLst = new List<bool>();
callbackDelayLst = new List<System.Action>();
} private IList<float> timeDelayLst;
private IList<bool> timeStateLst;
private IList<System.Action> callbackDelayLst; public void Invoke(float _timeDelay, System.Action _callback)
{
timeDelayLst.Add(_timeDelay);
timeStateLst.Add(false);
callbackDelayLst.Add(_callback);
}
public int CancelInvoke(System.Action _callback, bool _cancelAll = false) //false:仅取消最后注册的(和延迟时间无关);返回int型,可以根据剩余的次数立即执行未执行的回调函数
{
int tCount = ;
for(int i = callbackDelayLst.Count - ; i >= ; i--)
{
if(callbackDelayLst[i].Equals(_callback))
{
tCount++;
timeDelayLst.RemoveAt(i);
timeStateLst.RemoveAt(i);
callbackDelayLst.RemoveAt(i);
if(!_cancelAll)
{
return tCount;
}
}
}
return tCount;
}
public void ClearInvoke()
{
timeDelayLst.Clear();
timeStateLst.Clear();
callbackDelayLst.Clear();
}
public void TickUpdate(float _deltaTime)
{
filtTick(_deltaTime);
for(int i = timeStateLst.Count - ; i >= ; i--)
{
timeStateLst[i] = false;
}
}
  private void filtTick(float _deltaTime)
  {
    for(int i = timeDelayLst.Count - ; i >= ; i--)
    {
      if(timeStateLst.Count > i && !timeStateLst[i])
      {
        timeDelayLst[i] -= _deltaTime;
        timeStateLst[i] = true;
        if(timeDelayLst[i] <= )
        {
          var tCallback = callbackDelayLst[i];//从后向前遍历:删除最后注册(和延迟时间无关)的事件回调(可以自行扩展根据延迟时间进行删除)
          timeDelayLst.RemoveAt(i);
          timeStateLst.RemoveAt(i);
          callbackDelayLst.RemoveAt(i);           tCallback();
          filtTick(_deltaTime);
        }
      }
    }
  }
}

封装之后仅需要在主函数逻辑中进行驱动计时,之后就可以根据需要方便的延迟及取消延迟了。(PS:因为只是简单的封装,因此还有以下缺点:1)递归回调的问题;2)无法取消匿名的回调函数。)
当然,也有一些比较方便使用的插件,这个可以根据需要自行研究了,eg:Vision Timer等,DoTween等也有提供接口功能。

Unity3D延迟回调的封装的更多相关文章

  1. Vue.nextTick DOM 更新循环结束之后执行延迟回调

    在下次 DOM 更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法,获取更新后的 DOM. 简单来说,Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统 ...

  2. C#将C++动态库的回调函数封装成事件

    关于C#调用C++动态库的文章很多,调用动态库中回调函数的方法也不在少数.但大多数调用回调函数的方法依然保留了C++的语法特点. 比如有一段C++的回调函数代码,为了表达它的意思,我把注释也粘贴了进来 ...

  3. c++ 回调函数封装

    std::function<void(int a,int b)> ha; //函数封装  当成参数用callback  std::bind(&fun1,this,std::plac ...

  4. unity3d 延迟运行脚本语句

    在Unity3D中.有yield语句它负责延迟操作,yield return WaitForSeconds(3.0); //等待 3 秒 查看unity3d脚本手冊,使用方法须要在对应的格式. 以下代 ...

  5. Unity3D 动画回调方法

    最近发现很多coder.在用Unity开发游戏的时候都需要一个需求就是..动画播到某一帧就要干什么事情.而且希望能得到回调. 在unity里面的window菜单有个.Animation工具.打开它.然 ...

  6. PCL中将回调函数封装到类中

    这是类中的声明 private://点云回调函数 NuClearTask_MyPointCloudHandle //点云选择 static void ps_callback(const pcl::vi ...

  7. unity3d 延迟处理方法

    Invoke("方法名", 多少秒后执行); InvokeRepeating("方法名", 多少秒后执行,开始执行后隔多长时间再次执行一次); CancelIn ...

  8. Unity3D手游开发实践

    <腾讯桌球:客户端总结> 本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目本身.虽然基于Unity3D,很多东西同样适用于Cocos.本文从以下10大点进行阐述: 架构设计 原生插件/ ...

  9. Unity3d 与 Objective-C 数据交互,持续更新中

    Unity 3D是用于3D游戏编程的语言,它是一个用C\C++编写的强大的库.而在游戏中经常要接入用OC编写的SDK,这就涉及到了Unity3d 和 OC之间的数据交互.XCode是完成兼容C语言的. ...

随机推荐

  1. 粘滞位(sticky bit)

    linux特殊权限:setUid, setGid, 粘着位(sticky) (1)目录的X权限(执行) 文件的可执行权限很简单,也就是可否执行它的意思,但目录的执行权限又代表什么意思呢? 当然不可能是 ...

  2. POJ 1716 Integer Intervals 差分约束

    题目:http://poj.org/problem?id=1716 #include <stdio.h> #include <string.h> #include <ve ...

  3. c# gzip解压缩

                , bytes.Length)) > )             {                line =  System.Text.Encoding.Defaul ...

  4. python邮件收发SAMPLE

    #!/usr/bin/env python # -*- encoding: utf-8 -*- import os, socket from time import localtime, strfti ...

  5. 【poj3070】矩阵乘法求斐波那契数列

    [题目描述] 我们知道斐波那契数列0 1 1 2 3 5 8 13…… 数列中的第i位为第i-1位和第i-2位的和(规定第0位为0,第一位为1). 求斐波那契数列中的第n位mod 10000的值. [ ...

  6. ASP.NET多用户操作相同互斥的对象

    [一篮饭特稀原创,转载请注明出自http://www.cnblogs.com/wanghafan/p/3574154.html ] 现象:公有静态变量不可用于ASP.NET多用户操作,否则该变量会被多 ...

  7. Multi-bit per cell storage

    Memories Scaling      其他的的半导体存储器的制程一般2年为一个升级周期,但是nand flash 存储器的制程升级周期和他们比起来只有1年.这种更快的制程升级导致SLC NAND ...

  8. Android ContentProvider和getContentResolver

    安卓系统中的数据库SqlLite操作和java中mysql的数据库操作很不一样,造成这样的原因是因为在安卓中数据库是属于进程的不存在数据库客户端,也不存在数据库服务器. 关于SqlLite数据库的文章 ...

  9. winRAR将单独文件分别压缩打包

    2014-4-7 首先选中多个需要打包的文件,右键-->添加到压缩文件-->选中"文件"选项卡-->勾选下面的"把每个文件压缩到单独文件中. 如下图所示

  10. 数据挖掘十大经典算法(5) 最大期望(EM)算法

    在统计计算中,最大期望(EM,Expectation–Maximization)算法是在概率(probabilistic)模型中寻找参数最大似然估计的算法,其中概率模型依赖于无法观测的隐藏变量(Lat ...