Unity delay management class

This is a singleton class, which is suitable for the time management of the whole project. From then on, let's get rid of monobehavior Update function

In addition, people may feel that calling by unified management consumes performance. This is just calling delegate functions. Even if thousands of empty methods are called in a loop, they will not get stuck. It mainly depends on the internal implementation of the method. We all know that we should not write a lot of logic in Update. This is the same truth, especially for the callback of circular call. Pay attention to the code logic.

Usage:

Method 1: execute once regularly (based on milliseconds)

doOnce(int delay, Handler method);

doOnce<T1>(int delay, Handler<T1> method, params object[] args);

doOnce<T1, T2>(int delay, Handler<T1, T2> method, params object[] args);

doOnce<T1, T2, T3>(int delay, Handler<T1, T2, T3> method, params object[] args);

T1, T2 and T3 appear here because sometimes in the project, when I execute this Handler callback, I want to receive some parameters, which is used.

Nonparametric usage:

TimerManager.instance.doOnce(3000,method);  

Execute method after 3000 milliseconds
Parametric usage, such as two parameters

TimerManager.instance.doOnce<GameObject,Transform>(3000,method,go,tf); 

Execute method after 3000 milliseconds and pass go and TF to method

I believe many people understand this usage. If you don't understand it, you can leave a message to me.

The following methods are the same. There are four overload methods. I won't post them here one by one. You can see the code behind.

Method 2. Timed repeated execution (based on milliseconds)

doLoop(int delay, Handler method)

Method 3: execute it regularly (based on frame rate)

doFrameOnce(int delay, Handler method)

Method 4. Timed repeated execution (based on frame rate)

doFrameLoop(int delay, Handler method)

Method 5: clean the timer

clearTimer(Handler method)

Scheduled execution once: it will be executed only once, and clearTimer will be called automatically after execution

Regular repeated execution: the method callback will be called repeatedly until the program actively calls clearTimer

Based on milliseconds: method is called in milliseconds

Based on frame rate: it is called at frame rate. It is assumed that 1 and 1 frames are transmitted once, and 2 and 2 frames are transmitted once

This is a management class. There needs to be a caller, so we need to call him

There must be an eternal class inherited from monobehavior in each of our projects. Write in Update:

foreach(IAnimatable animatable in TimerManager.timerList) {
  animatable.AdvanceTime();
}

code
1. Inheritance class, which is a base class used to facilitate writing singletons

public abstract class PureSingleton<T> where T : new()
{
    private static T _instance;
    public static T instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new T();
            }
            return _instance;
        }
    }
}

2. Positive TimerManager

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

public delegate void Handler();
public delegate void Handler<T1>(T1 param1);
public delegate void Handler<T1, T2>(T1 param1, T2 param2);
public delegate void Handler<T1, T2, T3>(T1 param1, T2 param2, T3 param3);

public interface IAnimatable
{
    void AdvanceTime();
}

/**
 * It needs to be initialized in a long-standing Update
 * foreach (IAnimatable animatable in TimerManager.timerList)
        {
            animatable.AdvanceTime();
        }
*/

/**Clock manager [if the same function is timed multiple times, it will be overwritten by the latter by default, and the delay will be executed immediately if it is less than 1]*/
public class TimerManager : PureSingleton<TimerManager>, IAnimatable
{

    public static List<IAnimatable> timerList = new List<IAnimatable>();

    public TimerManager()
    {
        timerList.Add(this);
    }

    private List<TimerHandler> _pool = new List<TimerHandler>();
    /** Use the array to ensure that it is executed in the order in which it is put*/
    private List<TimerHandler> _handlers = new List<TimerHandler>();
    private int _currFrame = 0;
    private uint _index = 0;

    public void AdvanceTime()
    {
        _currFrame++;
        for (int i = 0; i < _handlers.Count; i++)
        {
            TimerHandler handler = _handlers[i];
            long t = handler.userFrame ? _currFrame : currentTime;
            if (t >= handler.exeTime)
            {
                Delegate method = handler.method;
                object[] args = handler.args;
                if (handler.repeat)
                {
                    while (t >= handler.exeTime)
                    {
                        handler.exeTime += handler.delay;
                        method.DynamicInvoke(args);
                    }
                }
                else
                {
                    clear(handler.method);
                    method.DynamicInvoke(args);
                }
            }
        }
    }

    private object create(bool useFrame, bool repeat, int delay, Delegate method, params object[] args)
    {
        if (method == null)
        {
            return null;
        }

        //If the execution time is less than 1, execute directly
        if (delay < 1)
        {
            method.DynamicInvoke(args);
            return -1;
        }
        TimerHandler handler;
        if (_pool.Count > 0)
        {
            handler = _pool[_pool.Count - 1];
            _pool.Remove(handler);
        }
        else
        {
            handler = new TimerHandler();
        }
        handler.userFrame = useFrame;
        handler.repeat = repeat;
        handler.delay = delay;
        handler.method = method;
        handler.args = args;
        handler.exeTime = delay + (useFrame ? _currFrame : currentTime);
        _handlers.Add(handler);
        return method;
    }

    /// /// <summary>
    ///Timed execution once (based on milliseconds)
    /// </summary>
    ///< param name = "delay" > delay time (unit: ms) < / param >
    ///< param name = "method" > callback method at the end < / param >
    ///< param name = "args" > callback parameter < / param >
    public void doOnce(int delay, Handler method)
    {
        create(false, false, delay, method);
    }
    public void doOnce<T1>(int delay, Handler<T1> method, params object[] args)
    {
        create(false, false, delay, method, args);
    }
    public void doOnce<T1, T2>(int delay, Handler<T1, T2> method, params object[] args)
    {
        create(false, false, delay, method, args);
    }
    public void doOnce<T1, T2, T3>(int delay, Handler<T1, T2, T3> method, params object[] args)
    {
        create(false, false, delay, method, args);
    }

    /// /// <summary>
    ///Timed repeat (based on milliseconds)
    /// </summary>
    ///< param name = "delay" > delay time (unit: ms) < / param >
    ///< param name = "method" > callback method at the end < / param >
    ///< param name = "args" > callback parameter < / param >
    public void doLoop(int delay, Handler method)
    {
        create(false, true, delay, method);
    }
    public void doLoop<T1>(int delay, Handler<T1> method, params object[] args)
    {
        create(false, true, delay, method, args);
    }
    public void doLoop<T1, T2>(int delay, Handler<T1, T2> method, params object[] args)
    {
        create(false, true, delay, method, args);
    }
    public void doLoop<T1, T2, T3>(int delay, Handler<T1, T2, T3> method, params object[] args)
    {
        create(false, true, delay, method, args);
    }


    /// <summary>
    ///Execute once regularly (based on frame rate)
    /// </summary>
    ///< param name = "delay" > delay time (in frames) < / param >
    ///< param name = "method" > callback method at the end < / param >
    ///< param name = "args" > callback parameter < / param >
    public void doFrameOnce(int delay, Handler method)
    {
        create(true, false, delay, method);
    }
    public void doFrameOnce<T1>(int delay, Handler<T1> method, params object[] args)
    {
        create(true, false, delay, method, args);
    }
    public void doFrameOnce<T1, T2>(int delay, Handler<T1, T2> method, params object[] args)
    {
        create(true, false, delay, method, args);
    }
    public void doFrameOnce<T1, T2, T3>(int delay, Handler<T1, T2, T3> method, params object[] args)
    {
        create(true, false, delay, method, args);
    }

    /// <summary>
    ///Timed repeat execution (based on frame rate)
    /// </summary>
    ///< param name = "delay" > delay time (in frames) < / param >
    ///< param name = "method" > callback method at the end < / param >
    ///< param name = "args" > callback parameter < / param >
    public void doFrameLoop(int delay, Handler method)
    {
        create(true, true, delay, method);
    }
    public void doFrameLoop<T1>(int delay, Handler<T1> method, params object[] args)
    {
        create(true, true, delay, method, args);
    }
    public void doFrameLoop<T1, T2>(int delay, Handler<T1, T2> method, params object[] args)
    {
        create(true, true, delay, method, args);
    }
    public void doFrameLoop<T1, T2, T3>(int delay, Handler<T1, T2, T3> method, params object[] args)
    {
        create(true, true, delay, method, args);
    }

    /// <summary>
    ///Cleaning timer
    /// </summary>
    ///< param name = "method" > method is the callback function itself < / param >
    public void clearTimer(Handler method)
    {
        clear(method);
    }
    public void clearTimer<T1>(Handler<T1> method)
    {
        clear(method);
    }
    public void clearTimer<T1, T2>(Handler<T1, T2> method)
    {
        clear(method);
    }
    public void clearTimer<T1, T2, T3>(Handler<T1, T2, T3> method)
    {
        clear(method);
    }

    private void clear(Delegate method)
    {
        TimerHandler handler = _handlers.FirstOrDefault(t => t.method == method);
        if (handler != null)
        {
            _handlers.Remove(handler);
            handler.clear();
            _pool.Add(handler);
        }
    }

    /// <summary>
    ///Clear all timers
    /// </summary>
    public void clearAllTimer()
    {
        foreach (TimerHandler handler in _handlers)
        {
            clear(handler.method);
            clearAllTimer();
            return;
        }
    }

    public static void RemoveTimerMgr(TimerManager timerMgr)
    {
        timerList.Remove(timerMgr);
    }

    /// <summary>
    ///Game self start running time, MS
    /// </summary>
    public long currentTime
    {
        get { return (long)(Time.time * 1000); }
    }

    /**Timing processor*/

    private class TimerHandler
    {
        /**Execution interval*/
        public int delay;
        /**Repeat*/
        public bool repeat;
        /**Whether to use frame rate*/
        public bool userFrame;

        /**execution time*/
        public long exeTime;

        /**processing method*/
        public Delegate method;

        /**parameter*/
        public object[] args;

        /**clear*/

        public void clear()
        {
            method = null;
            args = null;
        }
    }
}

Reproduced in: https://blog.csdn.net/adf26645/article/details/102085215

Keywords: Unity3d

Added by kpzani on Wed, 02 Feb 2022 18:24:54 +0200