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
}
UI倒计时文本的一个轮子,写的有点过于绕了,不过姑且存个档