Unity 模拟协程实现计时器功能

时间:2019-01-23
本文章向大家介绍Unity 模拟协程实现计时器功能,主要包括Unity 模拟协程实现计时器功能使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

众所周知,在Unity里面开启协程会有消耗,有时候就算我们只需要用到一个简单的计时器,必须开一个协程或者自己写一个计时器。这里提供了一个通用的计时器类,里面还实现了内存池管理,使用完的计时器回收备用。

使用方法:只需负责调用即可,内部会自动回收。

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

public class GlobalTimer : MonoBehaviour
{
    private static GlobalTimer instance;
    public static GlobalTimer Instance
    {
        get
        {
            if (!instance)
            {
                instance = GameObject.FindObjectOfType();
            }
            if (!instance)
            {
                GameObject obj = new GameObject(typeof(GlobalTimer).ToString());
                instance = obj.AddComponent();
            }
            return instance;
        }
    }

    //正在使用的TimerData
    private List mUseTimerDatas = new List();
    //空闲的TimerData
    private List mNotUseTimerDatas = new List();

    //尝试从空闲池中取一个TimerData
    private TimerData GetTimerData(bool isAdd = true)
    {
        TimerData data = null;
        if (mNotUseTimerDatas.Count <= 0)
        {
            data = new TimerData();
        }
        else
        {
            data = mNotUseTimerDatas[0];
            mNotUseTimerDatas.RemoveAt(0);
        }

        mUseTimerDatas.Add(data);

        return data;
    }

    //创建一个计时器
    public TimerData AddTimer(float _duration, Action endCallBack, bool _isIgnoreTime = false)
    {
        TimerData data = GetTimerData();
        data.Init(_duration, endCallBack, _isIgnoreTime);

        return data;
    }

    //创建一个重复型计时器
    public TimerData AddIntervalTimer(float _duration, float _interval, Action _endCallBack, Action _intervalCallBack, bool _isIgnoreTime = false)
    {
        TimerData data = GetTimerData();
        data.Init(_duration, _endCallBack, _isIgnoreTime, _interval, _intervalCallBack);

        return data;
    }

    protected void Clear(TimerData data)
    {
        if (mUseTimerDatas.Remove(data))
        {
            mNotUseTimerDatas.Add(data);
        }
        else
        {
            Debug.LogWarning("GlobalTimer not find TimerData");
        }
    }

    #region 测试代码
    void Start()
    {
        TimerData td1 = GlobalTimer.Instance.AddTimer(5,
        () =>
        {
            Debug.Log("5秒后调用该方法1");
        });

        TimerData td2 = GlobalTimer.Instance.AddIntervalTimer(5, 1,
        () =>
        {
            Debug.Log("5秒后调用该方法2");
        },
        (float remainTime) =>
        {
            Debug.Log("每一秒调用执行此处:剩余时间" + remainTime);
        }
        );
    }
    #endregion

    void Update()
    {
        for (int i = 0; i < mUseTimerDatas.Count; ++i)
        {
            if (!mUseTimerDatas[i].Update())
            {
                //没更新成功,mUseTimerDatas长度减1,所以需要--i
                --i;
            }
        }
    }

    public class TimerData
    {
        //持续时间
        private float mDuration;
        //重复间隔
        private float mInterval;
        //结束回调
        private Action mEndCallBack;
        //每次重复回调
        private Action mIntervalCallBack;
        //是否忽略时间
        private bool isIgnoreTime;
        //计时器
        private float mRunTime;
        //间隔计时器
        private float mRunIntervalTime;

        //初始化
        public void Init(float _duration, Action _endCallBack, bool _isIgnoreTime = false, float _interval = -1f, Action _intervalCallBack = null)
        {
            mDuration = _duration;
            mInterval = _interval;
            mEndCallBack = _endCallBack;
            mIntervalCallBack = _intervalCallBack;
            isIgnoreTime = _isIgnoreTime;
            mRunTime = 0;
            mRunIntervalTime = 0;
        }

        //更新
        public bool Update()
        {
            float deltaTime = isIgnoreTime ? Time.unscaledDeltaTime : Time.deltaTime;
            mRunTime += deltaTime;
            mRunIntervalTime += deltaTime;

            if (mIntervalCallBack != null)
            {
                if (mRunIntervalTime >= mInterval)
                {
                    mRunIntervalTime -= mInterval;
                    mIntervalCallBack(mDuration - mRunTime);
                }
            }

            if (mRunTime >= mDuration)
            {
                if (mEndCallBack != null)
                {
                    mEndCallBack();
                }
                Clear();
                return false;
            }

            return true;
        }

        public void Clear()
        {
            instance.Clear(this);
        }

        public void AddEndCallBack(Action _endCallBack)
        {
            mEndCallBack += _endCallBack;
        }
    }
}
--------------------- 
作者:大城市下的蚂蚁 
来源:CSDN 
原文:https://blog.csdn.net/z625309640/article/details/78105626 
版权声明:本文为博主原创文章,转载请附上博文链接!