Unity基于C#的时间管理类(TimerManager)

做Unity也有一年多了,但项目中总没有一个方便使用的时间管理类,前段时间抽空把以前AS项目中的一个时间管理类改了一下,用了段时间,感觉还不错,分享给大家



这是一个单例类,适合整个项目的时间管理,从此让我们摆脱MonoBehaviour.Update函数

另外,由统一管理调用的,大家可能会觉得耗性能,这只是调用委托函数,即使一次循环调用上千个空方法,都不会卡顿的,主要是看方法内部的实现,大家都知道不要在Update里写大量逻辑,这里也是一样的道理,特别是循环调用的回调,要注意代码逻辑

先贴用法,再贴代码

方法一、定时执行一次(基于毫秒)

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,T3在这里出现是因为项目中有些时候可能在我执行这个Handler回调时,想接收一些参数,这样就用到了。

无参用法

TimerManager.instance.doOnce(3000,method);  3000毫秒后执行method

有参用法,比如有两个参数

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

3000毫秒后执行method,并把go,tf传递给method

这种用法相信很多人都懂了,如果不懂可以留言给我。

下面的方法,都是一样,都有四种重载方法,我在这里就不一一贴出来了,大家可以看后面的代码。

方法二、定时重复执行(基于毫秒)

doLoop(int delay, Handler method)

方法三、定时执行一次(基于帧率)

doFrameOnce(int delay, Handler method)

方法四、定时重复执行(基于帧率)

doFrameLoop(int delay, Handler method)

方法五、清理定时器

clearTimer(Handler method)

定时执行一次:只会执行一次,执行完成后会自动调用clearTimer

定时重复执行:会重复调用method回调,直到程序主动调用clearTimer

基于毫秒:以毫秒为间隔调用method

基于帧率:以帧速来调用,假设传1,1帧执行一次,传2,2帧执行一次

这是一个管理类,需要有调用方法,那么我们需要调用他

我们每个项目中肯定有一个永远存在的继承自MonoBehaviour的类,在Update中写上:

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

接下来贴代码

用于方便写单例的基类

先贴继承类,这是一个用于方便写单例的基类

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

正类 TimerManager

这是正类 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();
}

/**时钟管理器[同一函数多次计时,默认会被后者覆盖,delay小于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>();
    /** 用数组保证按放入顺序执行*/
    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;
        }

        //如果执行时间小于1,直接执行
        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>
    /// 定时执行一次(基于毫秒)
    /// </summary>
    /// <param name="delay">延迟时间(单位毫秒)</param>
    /// <param name="method">结束时的回调方法</param>
    /// <param name="args">回调参数</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>
    /// 定时重复执行(基于毫秒)
    /// </summary>
    /// <param name="delay">延迟时间(单位毫秒)</param>
    /// <param name="method">结束时的回调方法</param>
    /// <param name="args">回调参数</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>
    /// 定时执行一次(基于帧率)
    /// </summary>
    /// <param name="delay">延迟时间(单位为帧)</param>
    /// <param name="method">结束时的回调方法</param>
    /// <param name="args">回调参数</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>
    /// 定时重复执行(基于帧率)
    /// </summary>
    /// <param name="delay">延迟时间(单位为帧)</param>
    /// <param name="method">结束时的回调方法</param>
    /// <param name="args">回调参数</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>
    /// 清理定时器
    /// </summary>
    /// <param name="method">method为回调函数本身</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>
    /// 清理所有定时器
    /// </summary>
    public void clearAllTimer()
    {
        foreach (TimerHandler handler in _handlers)
        {
            clear(handler.method);
            clearAllTimer();
            return;
        }
    }

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

    /// <summary>
    /// 游戏自启动运行时间,毫秒
    /// </summary>
    public long currentTime
    {
        get { return (long)(Time.time * 1000); }
    }

    /**定时处理器*/

    private class TimerHandler
    {
        /**执行间隔*/
        public int delay;
        /**是否重复执行*/
        public bool repeat;
        /**是否用帧率*/
        public bool userFrame;

        /**执行时间*/
        public long exeTime;

        /**处理方法*/
        public Delegate method;

        /**参数*/
        public object[] args;

        /**清理*/

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

大家如果觉得好,多给我回复一下,刷刷人气

转载于:https://www.cnblogs.com/Qi-Henry/p/5242852.html

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值