TimerUpdate 倒计时工具
TimerUpdate 倒计时工具

TimerUpdate 倒计时工具

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
[XLua.LuaCallCSharp]
public class TimerUpdate : MonoBehaviour
{
    /// <summary>
    /// 时间戳倒计时数据类
    /// </summary>
    private class TimeStampDecline
    {
        #region 变量域
        /// <summary>
        /// 计时器下标
        /// </summary>
        public int Index;
        /// <summary>
        /// 开始时间DT
        /// </summary>
        public DateTime StartTime;
        /// <summary>
        /// 停止时间DT
        /// </summary>
        public DateTime EndTime;
        /// <summary>
        /// 是否有起始
        /// </summary>
        public bool HasStart = false;
        /// <summary>
        /// 是否有结束
        /// </summary>
        public bool HasEnd = false;
        /// <summary>
        /// 刷新间隔
        /// </summary>
        public int TickTime;
        /// <summary>
        /// 是否为倒计时
        /// </summary>
        public bool IsDecline;
        /// <summary>
        /// 每次刷新回调
        /// </summary>
        public Action CallTick;
        /// <summary>
        /// 每次刷新回调(返回DateTime)
        /// </summary>
        public Action<TimeSpan> CallTickDT;
        /// <summary>
        /// 当前的已计时时间
        /// </summary>
        public float TickCount = 0;
        /// <summary>
        /// 当前从开始到现在已计时时间
        /// </summary>
        public float TickCountTotal = 0;
        #endregion
        #region 构造方法
        /// <summary>
        /// 时间戳构造
        /// </summary>
        /// <param name="pTimeStampStart">开始时间戳</param>
        /// <param name="pTimeStampEnd">结束时间戳</param>
        /// <param name="pTickTime">刷新间隔</param>
        /// <param name="pIsDecline">是否为倒计时</param>
        /// <param name="pIndex">计数器下标</param>
        /// <param name="pCallTick">刷新回调</param>
        /// <param name="pCallTickDT">刷新回调(带返回DateTime)</param>
        public TimeStampDecline(long pTimeStampStart, long pTimeStampEnd, int pTickTime, bool pIsDecline, int pIndex)
        {
            DateTime time = DateTime.MinValue;
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            StartTime = GameHelper.TimeHelper.StampToDateTime(pTimeStampStart);
            EndTime = GameHelper.TimeHelper.StampToDateTime(pTimeStampEnd);
            TickTime = pTickTime;
            IsDecline = pIsDecline;
            Index = pIndex;
            CallTick = null;
            CallTickDT = null;
            HasStart = pTimeStampStart == -1 ? false : true;
            HasEnd = pTimeStampEnd == -1 ? false : true;
        }
        public TimeStampDecline(long pTimeStampStart, long pTimeStampEnd, int pTickTime, bool pIsDecline, int pIndex, Action pCallTick)
        {
            DateTime time = DateTime.MinValue;
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            StartTime = GameHelper.TimeHelper.StampToDateTime(pTimeStampStart);
            EndTime = GameHelper.TimeHelper.StampToDateTime(pTimeStampEnd);
            TickTime = pTickTime;
            IsDecline = pIsDecline;
            Index = pIndex;
            CallTick = pCallTick;
            CallTickDT = null;
            HasStart = pTimeStampStart == -1 ? false : true;
            HasEnd = pTimeStampEnd == -1 ? false : true;
        }
        public TimeStampDecline(long pTimeStampStart, long pTimeStampEnd, int pTickTime, bool pIsDecline, int pIndex, Action<TimeSpan> pCallTickDT)
        {
            DateTime time = DateTime.MinValue;
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            StartTime = GameHelper.TimeHelper.StampToDateTime(pTimeStampStart);
            EndTime = GameHelper.TimeHelper.StampToDateTime(pTimeStampEnd);
            TickTime = pTickTime;
            IsDecline = pIsDecline;
            Index = pIndex;
            CallTick = null;
            CallTickDT = pCallTickDT;
            HasStart = pTimeStampStart == -1 ? false : true;
            HasEnd = pTimeStampEnd == -1 ? false : true;
        }
        #endregion
    }
    /// <summary>
    /// 当前计时器被添加下标(只增)
    /// </summary>
    private int curIndex = 0;
    /// <summary>
    /// 计时器字典
    /// </summary>
    private Dictionary<int, TimeStampDecline> MapIdToTSDeline = new Dictionary<int, TimeStampDecline>();
    void FixedUpdate()
    {
        if (MapIdToTSDeline != null)
        {
            foreach (var TIME in MapIdToTSDeline.Values.ToList())
            {
                TickHandler(TIME);
            }
        }
    }
    /// <summary>
    /// 帧回调
    /// </summary>
    /// <param name="timeData"></param>
    private void TickHandler(TimeStampDecline timeData)
    {
        if (MapIdToTSDeline == null)
        {
            //等待当前计时器队列初始化
            return;
        }
        if (DateTime.Now < timeData.StartTime & timeData.HasStart)
        {
            Debug.Log($"【TimerDeline】Error: {timeData},还未到开启时间");
            return;
        }
        if (DateTime.Now >= timeData.EndTime && timeData.HasEnd)
        {
            Debug.Log($"【TimerDeline】Error: {timeData},超出截止时间");
            //从计时器字典中移除
            if (MapIdToTSDeline.ContainsKey(timeData.Index))
            {
                OnTickTimeSpanHandle(timeData);
                MapIdToTSDeline.Remove(timeData.Index);
            }
            return;
        }
        //是否在时间段内
        timeData.TickCount += Time.fixedDeltaTime;
        timeData.TickCountTotal += Time.fixedDeltaTime;
        if (timeData.TickCount >= timeData.TickTime)
        {
            OnTickTimeSpanHandle(timeData);
            timeData.TickCount = 0;
        }
    }
    /// <summary>
    /// 每帧处理Timedata信息
    /// 执行对应回调并传回处理后的TimeSpan
    /// </summary>
    /// <param name="timeData">目标时间戳倒计时数据类</param>
    private void OnTickTimeSpanHandle(TimeStampDecline timeData)
    {
        timeData.CallTick?.Invoke();
        TimeSpan tsNow = new TimeSpan(DateTime.Now.Ticks);  //当前本地时间的TimeSpan
        TimeSpan tsEnd = timeData.HasEnd ? new TimeSpan(timeData.EndTime.Ticks) : tsNow;  //结束时间的TimeSpan
        TimeSpan tsStart = timeData.HasStart ? new TimeSpan(timeData.StartTime.Ticks) : tsNow;  //开始时间的TimeSpan
        tsNow = timeData.HasEnd && (tsNow <= tsEnd) ? tsNow : tsEnd;
        TimeSpan decline = tsNow.Subtract(tsEnd).Duration();  //距离结束时间倒计时的TimeSpan
        TimeSpan accumulate = tsStart.Subtract(tsNow).Duration();  //距离开始时间后的累积时间TimeSpan
        TimeSpan returnTs = timeData.IsDecline ? decline : accumulate;  //根据是否需要倒计时返回对应的TimeSpan
        timeData.CallTickDT?.Invoke(returnTs);
    }
    #region 添加/移除倒计时
    /// <summary>
    /// 添加一个倒计时
    /// </summary>
    /// <param name="pTimeStampStart">开始时间戳</param>
    /// <param name="pTimeStampEnd">结束时间戳</param>
    /// <param name="pTickTime">刷新间隔</param>
    /// <param name="pIsDecline">是否为倒计时</param>
    /// <param name="pIndex">计数器下标</param>
    /// <param name="pCallTick">刷新回调</param>
    /// <param name="pCallTickDT">刷新回调(带返回DateTime)</param>
    public int AddDecline(long pTimeStampStart, long pTimeStampEnd, int pTickTime, bool pIsDecline)
    {
        //每次新的下标加一
        TimeStampDecline tsDecline = new TimeStampDecline(pTimeStampStart, pTimeStampEnd, pTickTime, pIsDecline, curIndex++);
        MapIdToTSDeline.AddOrSet(tsDecline.Index, tsDecline);
        return curIndex;
    }
    public int AddDecline(long pTimeStampStart, long pTimeStampEnd, int pTickTime, bool pIsDecline, Action pCallTick)
    {
        //每次新的下标加一
        TimeStampDecline tsDecline = new TimeStampDecline(pTimeStampStart, pTimeStampEnd, pTickTime, pIsDecline, curIndex++, pCallTick);
        MapIdToTSDeline.AddOrSet(tsDecline.Index, tsDecline);
        return curIndex;
    }
    public int AddDecline(long pTimeStampStart, long pTimeStampEnd, int pTickTime, bool pIsDecline, Action<TimeSpan> pCallTickDT)
    {
        //每次新的下标加一
        TimeStampDecline tsDecline = new TimeStampDecline(pTimeStampStart, pTimeStampEnd, pTickTime, pIsDecline, curIndex, pCallTickDT);
        MapIdToTSDeline.AddOrSet(tsDecline.Index, tsDecline);
        return curIndex++;
    }
    /// <summary>
    /// 移除一个倒计时
    /// </summary>
    /// <param name="Index">计数器下标</param>
    /// <returns></returns>
    public bool RemoveDecline(int Index)
    {
        if (MapIdToTSDeline!=null&&MapIdToTSDeline.ContainsKey(Index))
        {
            MapIdToTSDeline.Remove(Index);
            return true;
        }
        else
        {
            return false;
        }
    }
    #endregion
}

一条评论

发表回复

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