unity实现延迟回调工具

 更新时间:2021年09月26日 10:10:39   作者:骚年狠冲洞  
这篇文章主要为大家详细介绍了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;
    }
}

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

相关文章

  • C#序列化成XML注意细节

    C#序列化成XML注意细节

    最常用的序列化是把某个类序列化成二进制文件.但有时我们也会把类序列化成xml文件,需要的朋友可以参考下
    2012-11-11
  • C#异步的世界(上)

    C#异步的世界(上)

    这篇文章主要介绍了C#异步的世界,对异步感兴趣的同学,可以参考下
    2021-04-04
  • C#连接SQL Sever数据库与数据查询实例之数据仓库详解

    C#连接SQL Sever数据库与数据查询实例之数据仓库详解

    最近的工作遇到了连接查询,特在此记录,以免日后以往,下面这篇文章主要给大家介绍了关于C#连接SQL Sever数据库与数据查询实例之数据仓库的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • C#调用sql2000存储过程方法小结

    C#调用sql2000存储过程方法小结

    这篇文章主要介绍了C#调用sql2000存储过程的方法,以实例形式分别对调用带输入参数及输出参数的存储过程进行了详细分析,非常具有实用价值,需要的朋友可以参考下
    2014-10-10
  • C#实现动态生成静态页面的类详解

    C#实现动态生成静态页面的类详解

    这篇文章主要介绍了C#实现动态生成静态页面的类,结合实例形式详细分析了C#动态生成静态页面的原理与相关使用技巧,需要的朋友可以参考下
    2016-04-04
  • C#中静态构造函数的几点说明介绍

    C#中静态构造函数的几点说明介绍

    本篇文章主要是对C#中静态构造函数的几点说明进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-01-01
  • C# String Replace高效的实例方法

    C# String Replace高效的实例方法

    C# String Replace高效的实例方法,需要的朋友可以参考一下
    2013-05-05
  • DevExpress中GridControl列转义的实现方法

    DevExpress中GridControl列转义的实现方法

    这篇文章主要介绍了DevExpress中GridControl列转义的实现方法,在项目开发中有一定的实用价值,需要的朋友可以参考下
    2014-08-08
  • Unity使用LineRender实现绘画功能

    Unity使用LineRender实现绘画功能

    这篇文章主要为大家详细介绍了Unity使用LineRender实现绘画功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • 基于StreamRead和StreamWriter的使用(实例讲解)

    基于StreamRead和StreamWriter的使用(实例讲解)

    下面小编就为大家分享一篇基于StreamRead和StreamWriter的使用实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11

最新评论