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);
        });
    }
}
unity 定时器_第1张图片


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 removeStack = new Stack();
    private static IDictionary timerEventDic = new Dictionary();

    private int id;
    private bool isNotify = false;

    public Action timerout;
    
    /// 
    /// 定时器开始
    /// 
    /// 
    /// 是否一次性
    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);
        }
    }

    /// 
    /// 一次性定时器
    /// 
    /// 
    /// 
    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()); } }
    private static IDictionary dic = new Dictionary();
    
    public static int Start(Func callBack)
    {
        var id = idCount++;
        dic.Add(id, Instance.StartCoroutine(callBack()));
        return id;
    }

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

你可能感兴趣的:(unity3d,unity,定时器,协程)