unity简易计时器,延迟回调,循环

分享项目中的一个简单的计时器,在设定时间后回调函数。

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

namespace XRTool.Util
{
    public delegate void TimerHandler();

    public delegate void TimerArgsHandler(object[] args);

    public class Timer
    {
        public TimerHandler Handler;           //无参的委托
        public TimerArgsHandler ArgsHandler;   //带参数的委托
        public float Frequency;               //时间间隔
        public int Repeats;                   //重复次数
        public object[] Args;

        public float LastTickTime;

        public event Action OnComplete;        //计时器完成一次工作
        public event Action OnDestroy;        //计时器被销毁
        public event Action OnFinsh;        //计时器结束工作了
        public Timer() { }

        /// 
        /// 创建一个时间事件对象
        /// 
        /// 回调函数
        /// 带参数的回调函数
        /// 时间内执行
        /// 重复次数
        /// 参数  可以任意的传不定数量,类型的参数
        public Timer(TimerHandler Handler, TimerArgsHandler ArgsHandler, float frequency, int repeats, object[] Args)
        {
            this.Handler = Handler;
            this.ArgsHandler = ArgsHandler;
            this.Frequency = frequency;
            this.Repeats = repeats == 0 ? 1 : repeats;
            this.Args = Args;
            this.LastTickTime = Time.time;
        }

        public void Notify()
        {
            Handler?.Invoke();
            ArgsHandler?.Invoke(Args);
            OnComplete?.Invoke();
        }
        /// 
        /// 清理计时器,初始化参数  同时清理事件
        /// 
        public void CleanUp()
        {
            Handler = null;
            ArgsHandler = null;
            Repeats = 1;
            Frequency = 0;
            OnDestroy?.Invoke();
            OnFinsh?.Invoke();
            OnDestroy = null;
            OnComplete = null;
        }
        /// 
        /// 立即执行回调
        /// isBreak = false的时候需要根据是否继续执行,传time
        /// isBreak = true,可不传time
        /// 
        /// 当前的时间,Time.time
        /// 执行完之后是否销毁计时器
        public void AwakeNow(float time = 0, bool isBreak = true)
        {
            try
            {
                ///唤醒可能会有异常
                Notify();
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
                Debug.LogError(ex.ToString());
            }
            finally
            {
                if (isBreak)
                {
                    OnFinsh?.Invoke();
                    TimerMgr.Instance.DestroyTimer(this);
                }
                else
                {
                    if ((--Repeats) == 0)
                    {
                        OnFinsh?.Invoke();
                        TimerMgr.Instance.DestroyTimer(this);
                    }
                    else
                    {
                        LastTickTime = time;
                    }
                }
            }
        }
        /// 
        /// 根据当前时间判断是否要触发触发器
        /// 
        /// 
        public void Update(float time)
        {
            if (Frequency + LastTickTime <= time)
            {
                AwakeNow(time, false);
            }
        }
    }

    /// 
    /// 计时器
    /// 添加一个计时事件
    /// 删除一个计时事件
    /// 更新计时事件
    /// 
    public class TimerMgr : MonoBehaviour
    {
        private List _Timers;//时间管理器
        public static TimerMgr Instance;
        void Awake()
        {
            DontDestroyOnLoad(gameObject);
            if (_Timers == null)
            {
                _Timers = new List();
            }
            Instance = this;
        }
        /// 
        /// 创建一个简单的计时器
        /// 
        /// 回调函数
        /// 计时器时间
        /// 回调次数  小于0代表循环 大于0代表repeats次
        public Timer CreateTimer(TimerHandler callBack, float time, int repeats = 1)
        {
            return Create(callBack, null, time, repeats);
        }

        public Timer CreateTimer(TimerArgsHandler callBack, float time, int repeats, params object[] args)
        {
            return Create(null, callBack, time, repeats, args);
        }

        private Timer Create(TimerHandler callBack, TimerArgsHandler callBackArgs, float time, int repeats, params object[] args)
        {
            Timer timer = new Timer(callBack, callBackArgs, time, repeats, args);
            _Timers.Add(timer);
            return timer;
        }

        public Timer DestroyTimer(Timer timer)
        {
            if (timer != null)
            {
                _Timers.Remove(timer);
                timer.CleanUp();
                timer = null;
            }
            return timer;
        }
        /// 
        /// 禁止调用此函数
        /// 
        public void ClearAll()
        {
            if (_Timers != null)
            {
                for (int i = 0; i < _Timers.Count; i++)
                {
                    _Timers[i].CleanUp();
                }
                _Timers.Clear();
            }
        }
        /// 
        /// 固定更新检查更新的频率
        /// 
        private void Update()
        {
            if (_Timers.Count != 0)
            {
                for (int i = _Timers.Count - 1; i >= 0 && i < _Timers.Count; i--)
                {
                    _Timers[i].Update(Time.time);
                }
            }
        }
    }
}

代码使用也简单,计时器为单例模式,将代码挂载在场景中即可。
unity简易计时器,延迟回调,循环_第1张图片
我们新建一个test测试代码,用来展示如何使用计时器。
unity简易计时器,延迟回调,循环_第2张图片
unity简易计时器,延迟回调,循环_第3张图片

 TimerMgr.Instance.CreateTimer(() => { Debug.Log("zhixing1"); }, 1f);

上述代码就是在一秒以后执行一个debug输出“zhixing1”,我们在场景中运行后看看结果。
unity简易计时器,延迟回调,循环_第4张图片
显示一秒之后执行了我们的回调。在试试循环。

 TimerMgr.Instance.CreateTimer(() => { Debug.Log("zhixing2循环"); }, 3f, -1);

unity简易计时器,延迟回调,循环_第5张图片
看到结果3秒就循环执行一次我们的代码。
执行带参回调。
unity简易计时器,延迟回调,循环_第6张图片

 TimerMgr.Instance.CreateTimer(() => { Log(1); }, 1f, 1);

unity简易计时器,延迟回调,循环_第7张图片
正常执行。
分享到这。

你可能感兴趣的:(unity学习,unity,游戏引擎)