unity实现延迟回调工具

一个实用的计时器,可以计时延迟调用和延迟重复次数调用。

可以自己封装成单例模式挂在GameObject上使用,或者在另一个behavior的Update里执行这个类的OnUpdate()方法再使用。

为了更加安全的使用,建议在销毁MonoBehaviour时清理一下对应的所有计时器。

或者调用时可选择传入回调所在的MonoBehaviour,这样就可以自动清理了。

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

public static class DelayCall
{

    private static List<CallTimeObj> calltimes = new List<CallTimeObj>();
    private static Dictionary<int, CallObj> callsort = new Dictionary<int, CallObj>();
    private static int countid = 0;
    /// <summary>
    /// 生成id
    /// </summary>
    /// <returns>The new identifier.</returns>
    /// <param name="call">Call.</param>
    private static int getNewId(CallObj call)
    {
        countid++;
        if (countid >= int.MaxValue)
        {
            countid = 1;
        }
        while (callsort.ContainsKey(countid)) countid++;
        call.callid = countid;
        callsort.Add(countid, call);
        return countid;

    }
    public static void ClearAll()
    {

        calltimes.Clear();
        callsort.Clear();
    }
    /// <summary>
    /// 删除延迟执行.
    /// </summary>
    /// <param name='call'>
    /// Call.
    /// </param>
    public static void remove(int callid)
    {
        if (callid > 0 && callsort.ContainsKey(callid))
        {
            CallObj call = callsort[callid];
            callsort.Remove(callid);
            if (call != null)
            {
                calltimes.Remove((CallTimeObj)call);
            }
        }

    }

    public static int AddTime(float delayTime, object arg, int repeat = 1,Action<object> call)
    {
        var callobj = new CallTimeObj();
        callobj.argsCall = call;
        callobj.arg = arg;
        callobj.repeat = repeat;
        callobj.time = Time.realtimeSinceStartup + delayTime;
        callobj.delayTime = delayTime;
        if (repeat == 0)
        {
            callobj.isloop = true;
        }
        calltimes.Add(callobj);
        getNewId(callobj);
        return callobj.callid;

    }

    /// <summary>
    /// 添加延迟执行
    /// </summary>
    /// <param name="call">回调方法</param>
    /// <param name="delayTime">延迟时间</param>
    /// <param name="repeat">重复回调次数</param>
    /// <param name="mn">承载回掉函数的实例是否存在的判断</param>
    /// <param name="isUnique">是否是唯一的方法</param>
    /// <param name="isReplace">如果重复是否覆盖</param>
    /// <returns></returns>
    public static int AddTime(float delayTime, int repeat = 1, MonoBehaviour mn = null, bool isUnique = false, bool isReplace = false,Action call)
    {
        if (isUnique)
        {
            for (int i = 0; i < calltimes.Count; i++)
            {
                CallTimeObj call2 = calltimes[i];
                if (call2.mn == mn && call2.call == call)
                {
                    if (isReplace)
                    {
                        call2.time = Time.realtimeSinceStartup + delayTime;

                    }
                    return call2.callid;
                }
            }
        }

        var callobj = new CallTimeObj();
        callobj.call = call;
        callobj.isMN = (mn != null);
        callobj.mn = mn;
        callobj.repeat = repeat;
        callobj.time = Time.realtimeSinceStartup + delayTime;
        callobj.delayTime = delayTime;
        if (repeat == 0)
        {
            callobj.isloop = true;
        }
        calltimes.Add(callobj);
        getNewId(callobj);
        return callobj.callid;
    }

    public static void OnUpdate()
    {

        //time call
        if (calltimes.Count != 0) for (int i = 0; i < calltimes.Count; ++i)
            {
                CallTimeObj call = calltimes[i];
                if (call.time <= Time.realtimeSinceStartup)
                {
                    if (call.isloop == false)
                    {
                        call.repeat--;
                        if (call.repeat <= 0)
                        {
                            calltimes.RemoveAt(i);
                            callsort.Remove(call.callid);
                            --i;
                        }
                        else
                        {
                            //重新累加时间
                            call.time += call.delayTime;

                        }
                    }
                    else
                    {
                        call.time += call.delayTime;
                    }

                    if (!call.isMN || call.mn != null)
                    {
                        try
                        {
                            if (call.argsCall != null)
                            {
                                call.argsCall.Invoke(call.arg);
                                if (call.isloop == false)
                                {
                                    if (call.repeat <= 0)
                                    {
                                        call.arg = null;
                                        call.argsCall = null;
                                        call.mn = null;
                                    }
                                }
                            }
                            else
                            {
                                call.call();
                            }
                        }
                        catch (Exception e)
                        {
                            Debug.LogException(e);
                        }
                    }
                }
            }

    }
    private class CallObj
    {
        public Action call = null;
        public int frame;
        public bool isMN;
        public MonoBehaviour mn;
        public int callid = 0;
    }
    private class CallTimeObj : CallObj
    {
        public Action<object> argsCall = null;
        public float time;
        public int repeat = 1;
        public float delayTime = 0;
        public object arg;
        public bool isloop = false;
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Unity封装延时调用定时器

    本文实例为大家分享了Unity封装延时调用定时器的具体代码,供大家参考,具体内容如下 封装一个延时调用定时器类 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; public class WaitTimeManager { private static TaskBehaviour m_Task; static WaitTimeManage

  • Unity实现毫秒延时回调功能

    简介 在项目的框架中看到了这个延迟回调的函数,一直以为是通过Unity协程实现的,最后看了源码后才发现是自己实现的.也是,如果用了协程成千上百个回调不得卡死.自己实现了一下核心的脚本,但是他的精华在于数据结构,把每个回调任务都做了很好的处理. API 1: Time.deltaTime 实际上就是每帧所执行的时间 功能实现 简单的说一下功能的实现,下面会直接贴出源码. 每一个新增的任务(回调)都会记录创建任务的时间以及延迟的时间,以及自己的事件回调.通过每帧判断当前帧的时间是否大于创建的(任务的

  • unity实现延迟回调工具

    一个实用的计时器,可以计时延迟调用和延迟重复次数调用. 可以自己封装成单例模式挂在GameObject上使用,或者在另一个behavior的Update里执行这个类的OnUpdate()方法再使用. 为了更加安全的使用,建议在销毁MonoBehaviour时清理一下对应的所有计时器. 或者调用时可选择传入回调所在的MonoBehaviour,这样就可以自动清理了. using System.Collections; using System; using System.Collections.G

  • Unity多语言转换工具的实现

    本文实例为大家分享了Unity多语言转换工具的具体代码,供大家参考,具体内容如下 说明 遍历Unity场景和Prefab,提取Text组件文字,并导出Json表.可将Json文本进行多语言翻译后,利用工具将内容替换回原场景或Prefab. 代码 using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor

  • Unity实现切割图集工具

    本文实例为大家分享了Unity实现切割图集工具的具体代码,供大家参考,具体内容如下 操作步骤 先将脚本拖入Editor 1.选中要切割的图片,texture type 选为default,并勾选Advanced下的read/Write Enabled 2.texture type改为sprite(2D and UI),Sprite mode 选为Multiple,apply一下 3.Sprite Editor 先选其他的切一下,在选第一个切一下,切割成小图,apply 4.选中图集右键,imag

  • Vue nextTick延迟回调获取更新后DOM机制详解

    目录 简述 事件循环机制 vue数据驱动视图的处理(异步变化DOM) Vue.nextTick原理 Vue.nextTick的应用 created生命周期中操作DOM 修改数据,获取DOM值 简述 相信大家在写vue项目的时候,一定会发现一个神奇的api,Vue.nextTick.为什么说它神奇呢,那是因为在你做某些操作不生效时,将操作写在Vue.nextTick内,就神奇的生效了.那这是什么原因呢? 让我们一起来研究一下. vue 实现响应式并不是数据发生变化后 DOM 立即变化,而是按照一定

  • SpringBoot集成Redisson实现延迟队列的场景分析

    使用场景 1.下单成功,30分钟未支付.支付超时,自动取消订单 2.订单签收,签收后7天未进行评价.订单超时未评价,系统默认好评 3.下单成功,商家5分钟未接单,订单取消 4.配送超时,推送短信提醒 ...... 对于延时比较长的场景.实时性不高的场景,我们可以采用任务调度的方式定时轮询处理.如:xxl-job 今天我们采用一种比较简单.轻量级的方式,使用 Redis 的延迟队列来进行处理.当然有更好的解决方案,可根据公司的技术选型和业务体系选择最优方案.如:使用消息中间件Kafka.Rabbi

  • MySQL DDL 引发的同步延迟该如何解决

    前言 写作案例分析,主要是工具介绍&推荐.MySQL 的同步机制比较单纯,主库上执行过的 DML 和 DDL 会在从库上再执行一次,那么主库上需要 10min 才能执行完的 DDL 理论上在从库至少也要花费 10min 才能执行完,这意味着从库的同步会延迟 10min 以上,等 DDL 执行完之后才会继续追同步. 解决方案 从 MySQL 的同步原理来看,主要是 DDL 这个单独的操作会花费太久的时间,导致从库也会被卡主.那么解决这个问题的办法就很容易想到:"拆解" DDL 的

  • Java 异步线程监听与结果回调及异常捕获总结分析

    前言 工作中是否遇到这样的场景? 1.需要异步线程执行,而且需要获取到线程执行返回的结果. 2.如果执行过程异常,可以按照自定义方式消费异常信息. 如果只是单纯的使用Callable可以实现,本文提供更加优雅的工具类. Maven依赖 <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.15</ver

  • 基于rabbitmq延迟插件实现分布式延迟任务

    目录 一.延迟任务的使用场景 二.组件安装 三.RabbitMQ延迟队列插件的延迟队列实现 1.基本原理 2.核心组件开发走起 之前给大家介绍过SpringBoot集成Redisson实现延迟队列的场景分析,今天介绍下基于rabbitmq延迟插件rabbitmq_delayed_message_exchange实现延迟任务. 一.延迟任务的使用场景 1.下单成功,30分钟未支付.支付超时,自动取消订单 2.订单签收,签收后7天未进行评价.订单超时未评价,系统默认好评 3.下单成功,商家5分钟未接

  • 利用Tkinter(python3.6)实现一个简单计算器

    前言 上机实践课程开始了,嗯,老师来了之后念了下PPT,然后说:开始做吧......... 然后就开始了Python的GUI之路,以前没接触过PYthon的可视化界面(虽然这样很不明智) 但是现在做起来感觉写小工具还挺方便的,当时搜到的第一个库便是Tkinter就直接开始写了 后来发现QT很不错的样子,下个实验就用QT吧.然后关于Tkinter(python3.6) 计算器源码 ennn.....有的命名不规范....... 首先对于python中栈的实现是通过list的方式模拟 pop()出栈

随机推荐