TickTimer
TickTimer

TickTimer

using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using UnityEngine;
using System;

namespace GuiltyVoid.Lua.LuaFrameWork.Wrap
{
    /// <summary>
    /// Lua计时器
    /// </summary>
    public class TickTimer
    {
        /// <summary>
        /// 计时器下标
        /// </summary>
        public long Index = 0;
        /// <summary>
        /// 计时器停止回调
        /// </summary>
        private Action<TickTimer> Action_ShutDown;

        /// <summary>
        /// 延迟执行事件
        /// </summary>
        public event Action OnDelayAction;

        /// <summary>
        /// 每Tick执行事件
        /// </summary>
        public event Action OnTickActon;

        /// <summary>
        /// 当前已经响应过的Tick次数
        /// </summary>
        private int _TickActionCount = 0;

        /// <summary>
        /// 是否强制停止当前计时器
        /// </summary>
        private bool _IsFourceRemove = false;

        /// <summary>
        /// 持续时间
        /// </summary>
        private float _Duration = 0f;

        /// <summary>
        /// 剩余时间
        /// </summary>
        private float _RemainTime = 0f;

        /// <summary>
        /// 是否为永久持续
        /// </summary>
        private bool _IsPermanent = false;

        /// <summary>
        /// 当前总共持续时间
        /// </summary>
        private float _TimeCount = 0f;

        /// <summary>
        /// 延迟执行时间
        /// </summary>
        private float _Delay = 0f;

        /// <summary>
        /// 延迟执行后是否需要停止计时器
        /// </summary>
        private bool _IsNeedShutAfterDelay = true; 

        /// <summary>
        /// Tick间隔时间
        /// 默认为1s 1Tick
        /// </summary>
        private float _TickTime = 1f;
        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="Action_ShutDown">关闭回调方法</param>
        public TickTimer(Action<TickTimer> Action_ShutDown)
        {
            this.Action_ShutDown = Action_ShutDown;
        }

        /// <summary>
        /// 开始执行Tick
        /// </summary>
        private async void StartRunTick()
        {
            while (true)
            {
                if (_IsFourceRemove)
                {
                    ShutDownTick();
                    return;
                }
               OnTickRun();
               await Task.Delay(100);
            }
        }
        /// <summary>
        /// 每1ms响应一次函数体
        /// </summary>
        /// <returns></returns>
        private void OnTickRun()
        {
            if (_RemainTime <= 0 && !_IsPermanent)
            {
                //达到时间移除
                _IsFourceRemove = true;
            }
            _TimeCount += 100;
            if (!_IsPermanent)
            {
                _RemainTime -= 100;
            }
            //当前累积时间大于上一次进行Tick时间则执行一次TickAction(所以默认第一次Start后会立刻执行一次TickAction)
            if (_TimeCount > (_TickTime * 1000 * _TickActionCount))
            {
                _TickActionCount++;
                OnTickActon?.Invoke();
            }
            //当前累积时间到达了延迟时间响应一次延迟Action
            if (OnDelayAction != null && _TimeCount > _Delay * 1000)
            {
                OnDelayAction?.Invoke();
                OnDelayAction = null;
                if (_IsNeedShutAfterDelay)
                {
                    //停止计时器
                    ShutDownTick();
                }
            }
            //await Task.Delay(100);
        }

        /// <summary>
        /// 开启一个计时器
        /// </summary>
        /// <param name="pDuration">计时器总时间</param>
        /// <param name="pTickTime">每Tick间隔时间</param>
        /// <param name="pTickAction">每Tick回调方法</param>
        /// <param name="pDelay">延迟执行时间</param>
        /// <param name="pIsNeedShutAfterDelay">延迟执行后是否需要停止计时器</param>
        /// <param name="pDelayAction">延迟执行事件</param>
        public void StartTickTimer(float pDuration = 0f,
            float pTickTime = 1f,
            Action pTickAction = null,
            float pDelay = 0f,
            bool pIsNeedShutAfterDelay = true,
            Action pDelayAction = null)
        {
            OnDelayAction = pDelayAction;
            OnTickActon = pTickAction;
            _TickActionCount = 0;
            _IsFourceRemove = false;
            _Duration = pDuration;
            _RemainTime = _Duration;
            _IsPermanent = _Duration <= 0;
            _TimeCount = 0f;
            _Delay = pDelay;
            _IsNeedShutAfterDelay = pIsNeedShutAfterDelay;
            _TickTime = pTickTime;
            StartRunTick();
        }

        /// <summary>
        /// 停止计时器
        /// </summary>
        public void ShutDownTick()
        {
            _IsPermanent = true;
            Action_ShutDown?.Invoke(this);
        }
    }

    /// <summary>
    /// 计时器工具
    /// </summary>
    public class TimerUtilities
    {
        
        /// <summary>
        /// 计时器实例下标计数器(用于保证每个计时器的Key唯一)
        /// </summary>
        private long _TickIndexr = 1;

        /// <summary>
        /// 计时器实例Map
        /// </summary>
        private ConcurrentDictionary<long, TickTimer> _MapTickTimer;

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            //Debug.Log("[LuaFrameWork] ---------------INIT UTILITIES");
            _MapTickTimer = new ConcurrentDictionary<long, TickTimer>();
            _TickIndexr = 1;
        }

        /// <summary>
        /// 延迟执行
        /// </summary>
        /// <param name="pDelay"></param>
        /// <param name="pDelayAction"></param>
        public void Delay(float pDelay, Action pDelayAction)
        {
            TickTimer timer = AddTickTimer();
            if (timer != null)
            {
                //成功添加一个TickTimer到缓存Map中,执行对应延迟方法
                timer.StartTickTimer(pDelay: pDelay, pDelayAction: pDelayAction);
            }
           
        }

        /// <summary>
        /// 开启一个帧回调计时器
        /// </summary>
        /// <param name="pDuration">计时器总时间</param>
        /// <param name="pTickTime">每Tick间隔时间</param>
        /// <param name="pTickAction">每Tick回调方法</param>
        public TickTimer Tick(float pDuration = 0f, float pTickTime = 1f, Action pTickAction = null)
        {
            TickTimer timer = AddTickTimer();
            if (timer != null)
            {
                //成功添加一个TickTimer到缓存Map中,执行对应延迟方法
                timer.StartTickTimer(pDuration, pTickTime, pTickAction);
            }
            return timer;
        }

        /// <summary>
        /// 开启一个帧回调计时器并且在指定延迟后响应一个事件
        /// </summary>
        /// <param name="pDuration">计时器总时间</param>
        /// <param name="pTickTime">每Tick间隔时间</param>
        /// <param name="pTickAction">每Tick回调方法</param>
        /// <param name="pDelay">延迟执行时间</param>
        /// <param name="pIsNeedShutAfterDelay">延迟执行后是否需要停止计时器</param>
        /// <param name="pDelayAction">延迟执行事件</param>
        public TickTimer TickDelay(float pDuration = 0f,
            float pTickTime = 1f, 
            Action pTickAction = null,
            float pDelay = 0f,
            bool pIsNeedShutAfterDelay = true,
            Action pDelayAction = null)
        {
            TickTimer timer = AddTickTimer();
            if (timer != null)
            {
                //成功添加一个TickTimer到缓存Map中,执行对应延迟方法
                timer.StartTickTimer(pDuration, pTickTime, pTickAction,pDelay,pIsNeedShutAfterDelay,pDelayAction);
            }
            return timer;
        }


        /// <summary>
        /// 获取一个计时器
        /// </summary>
        /// <returns></returns>
        private TickTimer AddTickTimer()
        {
            TickTimer timer = new TickTimer(RemoveTickTimer);
            bool isSuccess = _MapTickTimer.TryAdd(_TickIndexr++, timer);
            if (!isSuccess)
            {
                Debug.LogWarning($"[TimerUtilities] Error: Fail to Add a Timer to Map!");
                timer = null; //字典添加失败,释放当前Timer实例
                return null;
            }
            return timer;
        }

        /// <summary>
        /// 移除一个计时器
        /// </summary>
        /// <param name="timer"></param>
        private void RemoveTickTimer(TickTimer timer)
        {
            TickTimer outTimer;
            if (_MapTickTimer != null && timer != null && _MapTickTimer.ContainsKey(timer.Index))
            {
               var Succeed =  _MapTickTimer.TryRemove(timer.Index,out outTimer);
                if (Succeed)
                {
                    outTimer = null; //释放当前类
                }
            }
        }
    }
}

2条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注