初始化

This commit is contained in:
come
2025-07-26 16:56:42 +08:00
parent 8291dbb91c
commit fa81439a8c
2574 changed files with 328492 additions and 2170 deletions

View File

@@ -0,0 +1,300 @@
//------------------------------------------------------------
// Author: 亦亦
// Mail: 379338943@qq.com
// Data: 2023年2月12日
//------------------------------------------------------------
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 倒计时管理器
/// 区别于Times
/// Times CountDown
/// 回调频率 不可改 可改 (虽然中途改频率这个事情很少)
/// 如果暂停 中间丢失的时间就没了 中途丢失的时间会快速倒计时 (万一有需求 中间的各种计算就丢掉了)
/// 添加时可立即调用一次 否(还需要自己调一次) 可传参数控制 (很多时候倒计时都需要第一时间刷新一次的)
/// 一对多 否 是 (因为用Callback做K 就没办法在同一个Callback下 被别人倒计时)
/// 可提前结束 否 是 (针对于 比如 匿名函数 等特殊情况)
/// 回调参数 obj 但是麻烦 而且不可变 已过去时间/总时间 (更适合于UI上的一些数字倒计时)
/// 可循环 否 是 (虽然0 都可以无限 但是万一要的是不是0的情况下循环呢 就得递归调自己吗)
/// 多重载 否 是 (满足各种需求)
/// 匿名函数 否 是 (匿名函数也可以被暂停 移除等操作)
/// ......
/// </summary>
public partial class CountDownMgr : MgrSingleton<CountDownMgr>
{
/// <summary>
/// 回调方法
/// </summary>
/// <param name="residueTime">剩余时间</param>
/// <param name="elapseTime">已过去时间</param>
/// <param name="totalTime">总时间</param>
public delegate void TimerCallback(double residueTime, double elapseTime, double totalTime);
/// <summary>
/// 所有需要被倒计时的目标
/// 这个可以一对多
/// </summary>
private Dictionary<int, CountDownData> m_AllCountDown = new Dictionary<int, CountDownData>();
/// <summary>
/// 临时存储
/// 下一帧添加的倒计时
/// </summary>
private Dictionary<int, CountDownData> m_ToAddCountDown = new Dictionary<int, CountDownData>();
/// <summary>
/// 所有需要被倒计时的目标
/// 这个只能一对一
/// </summary>
private Dictionary<TimerCallback, int> m_CallbackGuidDic = new Dictionary<TimerCallback, int>();
/// <summary>
/// 临时存储
/// 下一帧移除的倒计时
/// </summary>
private List<int> m_RemoveGuid = new List<int>();
/// <summary>
/// 可容纳的最大倒计时
/// </summary>
private int m_MaxCount = 1000;
/// <summary>
/// 当然已经存在的倒计时数量
/// </summary>
private int m_AtCount = 0;
protected override UniTask<bool> MgrAsyncInit()
{
Initialize();
return base.MgrAsyncInit();
}
//初始化
private void Initialize()
{
m_AllCountDown.Clear();
m_RemoveGuid.Clear();
m_ToAddCountDown.Clear();
m_CallbackGuidDic.Clear();
UpdateAsync().Forget();
}
//摧毁
protected override void OnDispose()
{
}
//统一所有取时间都用这个 且方便修改
private static float GetTime()
{
//这是一个倒计时时间不受暂停影响的
return Time.realtimeSinceStartup;
}
//更新频率毫秒
private int m_UpdataAsyncDelay = (int)(1000f / 30f);
//使用异步控制频率更新 并没有使用调度器
//调度器是mono update 不需要这么高的频率
private async UniTaskVoid UpdateAsync()
{
while (true)
{
if (Disposed) return;
ManagerUpdate();
await UniTask.Delay(m_UpdataAsyncDelay);
}
}
//为了不受mono暂停影响 所以使用异步调用
public void ManagerUpdate()
{
var time = GetTime();
//需要被添加的
if (m_ToAddCountDown.Count >= 1)
{
foreach (var countDown in m_ToAddCountDown.Values)
{
ToAddCountDownTimer(countDown);
}
m_ToAddCountDown.Clear();
}
//需要被移除的
if (m_RemoveGuid.Count >= 1)
{
foreach (var guid in m_RemoveGuid)
{
RemoveCountDownTimer(guid);
}
m_RemoveGuid.Clear();
}
//倒计时
foreach (var data in m_AllCountDown.Values)
{
data.ElapseTime = time - data.StartTime;
//已经用完时间
if (data.TotalTime != 0 && data.ElapseTime >= data.TotalTime)
{
data.ElapseTime = data.TotalTime;
Callback(data);
if (data.Forver)
{
Restart(data);
}
else
{
m_RemoveGuid.Add(data.Guid);
}
}
else if (time - data.LastCallBackTime >= data.Interval)
{
//这样才可以确保如果卡了很久 该间隔回调的还是会回 不会遗漏
//但是如果一瞬间就到最后了 中途的还是会没有 因为这个倒计时类的需求就是这样的
data.LastCallBackTime += data.Interval;
Callback(data);
}
}
}
#region
/// <summary>
/// 是否可添加倒计时 有同时倒计时上限限制
/// </summary>
/// <returns></returns>
private bool TryAdd()
{
return !(m_AtCount >= m_MaxCount);
}
/// <summary>
/// 获取当前索引
/// </summary>
/// <returns></returns>
private int GetGuid()
{
return IDHelper.GetGuid();
}
//从缓存列表添加到运行列表
private void ToAddCountDownTimer(CountDownData countDownData)
{
if (m_AllCountDown.ContainsKey(countDownData.Guid))
{
Logger.LogError($"<color=red> 添加的这个已经存在 :{countDownData.Guid}</color>");
return;
}
m_AllCountDown.Add(countDownData.Guid, countDownData);
m_AtCount++;
}
/// <summary>
/// 添加一个到字典中
/// </summary>
private int AddCountDownTimer(CountDownData countDownData)
{
int guid = GetGuid();
countDownData.Guid = guid;
m_ToAddCountDown.Add(guid, countDownData);
return guid;
}
private bool RemoveCountDownTimer(int guid)
{
if (guid == 0)
{
return true;
}
if (!m_AllCountDown.ContainsKey(guid))
{
return false;
}
var data = m_AllCountDown[guid];
m_AllCountDown.Remove(guid);
RefPool.Put(data);
m_AtCount--;
return true;
}
/// <summary>
/// 移除一个回调
/// 根据需求也可使用 Remove(ref int guid)
/// </summary>
public bool Remove(int guid)
{
if (guid == 0)
{
return true;
}
//如果对方还在添加列表中 在移除列表中添加
//在下一次update的时候 添加列表还是会先添加到all中
//然后就会被移除 所以并不会被执行
//最终所有移除的都是从all中移除的
if (m_ToAddCountDown.ContainsKey(guid))
{
m_RemoveGuid.Add(guid);
return true;
}
//如果正在执行中 则添加到移除中
//下一次循环移除
if (m_AllCountDown.ContainsKey(guid))
{
m_RemoveGuid.Add(guid);
return true;
}
return false;
}
/// <summary>
/// 让倒计时重新开始
/// </summary>
private bool Restart(CountDownData data)
{
data.ElapseTime = 0;
data.LastCallBackTime = GetTime();
data.StartTime = data.LastCallBackTime;
data.EndTime = data.LastCallBackTime + data.TotalTime;
return true;
}
private void Callback(int guid)
{
var exist = m_AllCountDown.TryGetValue(guid, out CountDownData data);
if (exist)
Callback(data);
}
private void Callback(CountDownData data)
{
data.TimerCallback?.Invoke(data.TotalTime - data.ElapseTime, data.ElapseTime, data.TotalTime);
}
private void Callback(CountDownData data, double elapseTime)
{
data.TimerCallback?.Invoke(data.TotalTime - elapseTime, elapseTime, data.TotalTime);
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7045ee664f984ccb8b76aa81dd7e747b
timeCreated: 1689076290

View File

@@ -0,0 +1,168 @@
//------------------------------------------------------------
// Author: 亦亦
// Mail: 379338943@qq.com
// Data: 2023年2月12日
//------------------------------------------------------------
using UnityEngine;
namespace YIUIFramework
{
//ref回调索引 这个回调就可以一对多
public partial class CountDownMgr
{
/// <summary>
/// ref传递 成功移除 则会吧这个值改为 0
/// 省去自己修改
/// </summary>
/// <param name="guid"></param>
/// <returns></returns>
public bool Remove(ref int guid)
{
var result = Remove(guid);
if (result)
guid = 0;
return result;
}
/// <summary>
/// 添加一个回调 (之所以没有用callback 做K 因为我可以对一个回调做不同的间隔调用 才可以一对多)
/// 这个倒计时如果到最后一次回调 会自动回收 不必手动回收 除非提前移除
/// 注意 这个最后0秒肯定会回调一次 这个时候会无视间隔 如果你要确保间隔回调 请 总时间/间隔 = 整数
/// </summary>
/// <param name="guid">返回索引</param>
/// <param name="totalTime">总时间 0 =无限</param>
/// <param name="interval">间隔</param>
/// <param name="timerCallback">回调</param>
/// <param name="startCallback">开始的时候马上回调一次</param>
/// <returns></returns>
public bool Add(ref int guid,
double totalTime,
double interval,
TimerCallback timerCallback,
bool startCallback = false)
{
if (!TryAdd())
{
Debug.LogError("已经达到可同时倒计时上限 请确认");
guid = 0;
return false;
}
var newCountDownData = RefPool.Get<CountDownData>();
newCountDownData.Reset(totalTime, interval, timerCallback);
guid = AddCountDownTimer(newCountDownData);
if (startCallback)
Callback(newCountDownData);
return true;
}
/// <summary>
/// 不要索引的
/// </summary>
public bool Add(double totalTime, double interval, TimerCallback timerCallback, bool startCallback = false)
{
var guid = 0;
return Add(ref guid, totalTime, interval, timerCallback, startCallback);
}
/// <summary>
/// 添加一个只有一次的回调
/// </summary>
public bool Add(ref int guid, double totalTime, TimerCallback timerCallback, bool startCallback = false)
{
return Add(ref guid, totalTime, totalTime, timerCallback, startCallback);
}
/// <summary>
/// 不要索引的 一次回调
/// </summary>
public bool Add(double totalTime, TimerCallback timerCallback, bool startCallback = false)
{
var guid = 0;
return Add(ref guid, totalTime, totalTime, timerCallback, startCallback);
}
/// <summary>
/// 有设置是否循环的
/// </summary>
public bool Add(ref int guid,
double totalTime,
double interval,
TimerCallback timerCallback,
bool forever,
bool startCallback = false)
{
if (!TryAdd())
{
Debug.LogError("已经达到可同时倒计时上限 请确认");
guid = 0;
return false;
}
var newCountDownData = RefPool.Get<CountDownData>();
newCountDownData.Reset(totalTime, interval, timerCallback, forever);
guid = AddCountDownTimer(newCountDownData);
if (startCallback)
Callback(newCountDownData);
return true;
}
/// <summary>
/// 重新设置这个倒计时的已过去时间
/// </summary>
public bool SetElapseTime(int guid, double elapseTime)
{
var exist = m_AllCountDown.TryGetValue(guid, out CountDownData data);
if (!exist)
return false;
data.ElapseTime = elapseTime;
data.LastCallBackTime = GetTime();
return true;
}
/// <summary>
/// 获取一个倒计时剩余的倒计时时间
/// </summary>
public double GetRemainTime(int guid)
{
var exist = m_AllCountDown.TryGetValue(guid, out CountDownData data);
if (!exist)
return 0;
return data.TotalTime - data.ElapseTime;
}
/// <summary>
/// 强制执行 一个倒计时到最后时间
/// </summary>
public bool ForceToEndTime(int guid)
{
var exist = m_AllCountDown.TryGetValue(guid, out CountDownData data);
if (!exist)
return false;
data.ElapseTime = data.TotalTime;
Callback(data);
return Remove(guid);
}
/// <summary>
/// 让倒计时重新开始
/// </summary>
public bool Restart(int guid)
{
var exist = m_AllCountDown.TryGetValue(guid, out CountDownData data);
if (!exist)
return false;
return Restart(data);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0a67886df00749f2929ec23be33e9fb4
timeCreated: 1689076631

View File

@@ -0,0 +1,189 @@
//------------------------------------------------------------
// Author: 亦亦
// Mail: 379338943@qq.com
// Data: 2023年2月12日
//------------------------------------------------------------
using UnityEngine;
namespace YIUIFramework
{
public partial class CountDownMgr
{
private bool TryAddCallback(TimerCallback timerCallback)
{
if (m_CallbackGuidDic.ContainsKey(timerCallback))
{
Debug.LogError($"当前回调已存在 不能重复添加 如果想重复添加请使用另外一个API 使用GUID");
return false;
}
return true;
}
/// <summary>
/// 移除一个回调
/// </summary>
public bool Remove(TimerCallback timerCallback)
{
if (!m_CallbackGuidDic.ContainsKey(timerCallback))
{
return false;
}
Remove(m_CallbackGuidDic[timerCallback]);
m_CallbackGuidDic.Remove(timerCallback);
return true;
}
/// <summary>
/// 添加一个回调
/// </summary>
/// <param name="timerCallback">回调方法</param>
/// <param name="totalTime">总时间</param>
/// <param name="interval">间隔</param>
/// <param name="startCallback">是否立即回调一次</param>
/// <returns>是否添加成功</returns>
public bool Add(TimerCallback timerCallback, double totalTime, double interval, bool startCallback = false)
{
if (timerCallback == null)
{
Logger.LogError($"<color=red> 必须有callback </color>");
return false;
}
if (!TryAddCallback(timerCallback))
{
return false;
}
var callbackGuid = 0;
var result = Add(ref callbackGuid, totalTime, interval, timerCallback, startCallback);
if (result)
{
m_CallbackGuidDic.Add(timerCallback, callbackGuid);
}
return result;
}
/// <summary>
/// 添加一个只有一次的回调
/// </summary>
public bool Add(TimerCallback timerCallback, double totalTime, bool startCallback = false)
{
if (timerCallback == null)
{
Logger.LogError($"<color=red> 必须有callback </color>");
return false;
}
if (!TryAddCallback(timerCallback))
{
return false;
}
var callbackGuid = 0;
var result = Add(ref callbackGuid, totalTime, timerCallback, startCallback);
if (result)
{
m_CallbackGuidDic.Add(timerCallback, callbackGuid);
}
return result;
}
/// <summary>
/// 有设置是否循环的
/// </summary>
public bool Add(TimerCallback timerCallback,
double totalTime,
double interval,
bool forever,
bool startCallback)
{
if (timerCallback == null)
{
Logger.LogError($"<color=red> 必须有callback </color>");
return false;
}
if (!TryAddCallback(timerCallback))
{
return false;
}
var callbackGuid = 0;
var result = Add(ref callbackGuid, totalTime, interval, timerCallback, forever, startCallback);
if (result)
{
m_CallbackGuidDic.Add(timerCallback, callbackGuid);
}
return result;
}
/// <summary>
/// 判断这个倒计时是否存在
/// </summary>
public bool ExistTimerCallback(TimerCallback timerCallback)
{
return m_CallbackGuidDic.ContainsKey(timerCallback);
}
/// <summary>
/// 获取一个倒计时的GUID 如果存在则有
/// </summary>
public int GetTimerCallbackGuid(TimerCallback timerCallback)
{
if (!m_CallbackGuidDic.TryGetValue(timerCallback, out int guid))
return 0;
return guid;
}
/// <summary>
/// 重新设置这个倒计时的已过去时间
/// </summary>
public bool SetElapseTime(TimerCallback timerCallback, double elapseTime)
{
if (!m_CallbackGuidDic.TryGetValue(timerCallback, out int guid))
return false;
return SetElapseTime(guid, elapseTime);
}
/// <summary>
/// 获取一个倒计时剩余的倒计时时间
/// </summary>
public double GetRemainTime(TimerCallback timerCallback)
{
if (!m_CallbackGuidDic.TryGetValue(timerCallback, out int guid))
return 0;
return GetRemainTime(guid);
}
/// <summary>
/// 强制执行 一个倒计时到最后时间
/// </summary>
public bool ForceToEndTime(TimerCallback timerCallback)
{
if (!m_CallbackGuidDic.TryGetValue(timerCallback, out int guid))
return false;
return ForceToEndTime(guid);
}
/// <summary>
/// 让倒计时重新开始
/// </summary>
public bool Restart(TimerCallback timerCallback)
{
if (!m_CallbackGuidDic.TryGetValue(timerCallback, out int guid))
return false;
return Restart(guid);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 48b772ef1bef4f178dc06194122f33d1
timeCreated: 1689077347

View File

@@ -0,0 +1,88 @@
using UnityEngine;
namespace YIUIFramework
{
public partial class CountDownMgr
{
/// <summary>
/// 倒计时数据
/// </summary>
private class CountDownData : IRefPool
{
/// <summary>
/// 在倒计时管理器中的GUID
/// </summary>
public int Guid = 0;
/// <summary>
/// 总时间 0 = 无限回调 也可以有时间 forver = true 也可以无限回调
/// </summary>
public double TotalTime = 0;
/// <summary>
/// 间隔时间
/// </summary>
public double Interval = 0;
/// <summary>
/// 已经过去的时间
/// </summary>
public double ElapseTime = 0;
/// <summary>
/// 开始时间
/// </summary>
public double StartTime = 0;
/// <summary>
/// 最后一次回调时间
/// </summary>
public double LastCallBackTime = 0;
/// <summary>
/// 结束时间
/// </summary>
public double EndTime = 0;
/// <summary>
/// 永久执行 总时间到过后会重置
/// </summary>
public bool Forver = false;
/// <summary>
/// 回调方法
/// </summary>
public TimerCallback TimerCallback;
public CountDownData()
{
}
public void Reset(double totalTime, double interval, TimerCallback timerCallback, bool forver = false)
{
var time = GetTime();
TotalTime = totalTime;
Interval = interval;
ElapseTime = 0;
StartTime = time;
LastCallBackTime = time;
EndTime = time + totalTime;
Forver = forver;
TimerCallback = timerCallback;
}
public void Recycle()
{
Guid = 0;
TotalTime = 0;
Interval = 0;
ElapseTime = 0;
StartTime = 0;
LastCallBackTime = 0;
EndTime = 0;
Forver = false;
TimerCallback = null;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 08d7cb7788d444769ac9d358c88e49b6
timeCreated: 1689076379