unity 定时器

我们都知道可以使用协程这样制作定时器

using System.Collections;
using UnityEngine;
using System;

public class QWidget : MonoBehaviour
{
    private void Awake()
    {
        StartCoroutine(UpdateTimer(1.5f,()=> {
            Debug.Log(123);
        }));
    }

    IEnumerator UpdateTimer(float timer, Action callBack)
    {
        var wait = new WaitForSeconds(timer);
        while (true)
        {
            yield return wait;
            callBack();
        }
    }
}

但是,如果使用上面的代码,场景内协程多了将会出现明显的卡顿

所以有了下面的这个定时器:

如果场景内存在定时器时,仅开启一个协程。通过计算增量时间执行对应的事件

如果没有定时器在运行就关闭协程!


栗子:

using UnityEngine;

public class QWidget : MonoBehaviour
{
    private void Awake()
    {
        QTimer timer = new QTimer();
        timer.timerout = () => { Debug.Log("ee"); };
        timer.Start(1);

        QTimer timer2 = new QTimer();
        timer2.timerout = () => { Debug.Log("qq"); };
        timer2.Start(1);


        QTimer.SingleShot(3, () =>
        {
            timer.Stop();
            timer2.Stop();
            Debug.Log(222222);
        });
    }
}


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

public class QTimer
{
    private static int coroutineID;
    private static int idCount = 0;
    private static Stack<int> removeStack = new Stack<int>();
    private static IDictionary<int, TimerModel> timerEventDic = new Dictionary<int, TimerModel>();

    private int id;
    private bool isNotify = false;

    public Action timerout;
    
    /// <summary>
    /// 定时器开始
    /// </summary>
    /// <param name="timer"></param>
    /// <param name="isDisposable">是否一次性</param>
    public void Start(float timer, bool isDisposable=false)
    {
        id = idCount++;
        timerEventDic.Add(id, new TimerModel(timer,timerout, isDisposable));
        if (!isNotify)
        {
            isNotify = true;
            coroutineID = QCoroutine.Start(Notify);
        }
    }

    /// <summary>
    /// 一次性定时器
    /// </summary>
    /// <param name="timer"></param>
    /// <param name="callBack"></param>
    public static void SingleShot(float timer, Action callBack)
    {
        QTimer qTimer = new QTimer();
        qTimer.timerout = callBack;
        qTimer.Start(timer, true);
    }

    public void Stop()
    {
        removeStack.Push(id);
    }
    
    IEnumerator Notify()
    {
        int i, count;
        while (true)
        {
            foreach (var timerEvent in timerEventDic)
            {
                if (timerEvent.Value.Update())
                {
                    removeStack.Push(timerEvent.Key);
                }
            }
            if (removeStack.Count > 0)
            {
                count = removeStack.Count;
                for (i = 0; i < count; i++)
                {
                    timerEventDic.Remove(removeStack.Pop());
                }

                if (timerEventDic.Count <= 0)
                {
                    isNotify = false;
                    QCoroutine.Stop(coroutineID);
                }
            }
            yield return null;
        }
    }

    private class TimerModel
    {
        private bool isDisposable;
        private Action timerout;

        public float time;
        public float timer;
        
        public TimerModel(float timer, Action function, bool isDisposable=false)
        {
            time = timer;
            this.timer = timer;
            timerout = function;
            this.isDisposable = isDisposable;
        }

        ~TimerModel()
        {
            timerout = null;
        }

        public bool Update()
        {
            if (timerout == null) return true;
            time -= Time.deltaTime;
            if (time <= 0)
            {
                time = timer;
                timerout(); 
                if (isDisposable) return true;
            }
            return false;
        }
    }
}


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

public class QCoroutine : MonoBehaviour 
{
    private static int idCount = 0;
    private static QCoroutine instance;
    private static QCoroutine Instance { get { return instance ?? (instance=new GameObject("Coroutine").AddComponent<QCoroutine>()); } }
    private static IDictionary<int, Coroutine> dic = new Dictionary<int,Coroutine>();
    
    public static int Start(Func<IEnumerator> callBack)
    {
        var id = idCount++;
        dic.Add(id, Instance.StartCoroutine(callBack()));
        return id;
    }

    public static void Stop(int coroutineId)
    {
        Instance.StopCoroutine(dic[coroutineId]);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼游戏开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值