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;
  }
}

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

一、EF的创建第一步: 创建一个类库第二步: 选择类库第三步:选择ADO.NET 实体数据模型,名称和你数据库名字对应,我的叫LetDB第四步:出现了窗体先解释一下这些EF模型:1.来自 ...