首次提交
This commit is contained in:
22
Assets/Scripts/NBC/Core/Runtime/Services/ISingletonAwake.cs
Normal file
22
Assets/Scripts/NBC/Core/Runtime/Services/ISingletonAwake.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace NBC
|
||||
{
|
||||
public interface ISingletonAwake
|
||||
{
|
||||
void Awake();
|
||||
}
|
||||
|
||||
public interface ISingletonAwake<A>
|
||||
{
|
||||
void Awake(A a);
|
||||
}
|
||||
|
||||
public interface ISingletonAwake<A, B>
|
||||
{
|
||||
void Awake(A a, B b);
|
||||
}
|
||||
|
||||
public interface ISingletonAwake<A, B, C>
|
||||
{
|
||||
void Awake(A a, B b, C c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5543bf08377d4c0289f50e9b465963b6
|
||||
timeCreated: 1733994653
|
||||
135
Assets/Scripts/NBC/Core/Runtime/Services/IdGenerater.cs
Normal file
135
Assets/Scripts/NBC/Core/Runtime/Services/IdGenerater.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct IdStruct
|
||||
{
|
||||
public short Process; // 14bit
|
||||
public uint Time; // 30bit
|
||||
public uint Value; // 20bit
|
||||
|
||||
public long ToLong()
|
||||
{
|
||||
ulong result = 0;
|
||||
result |= (ushort)this.Process;
|
||||
result <<= 30;
|
||||
result |= this.Time;
|
||||
result <<= 20;
|
||||
result |= this.Value;
|
||||
return (long)result;
|
||||
}
|
||||
|
||||
public IdStruct(uint time, short process, uint value)
|
||||
{
|
||||
this.Process = process;
|
||||
this.Time = time;
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
public IdStruct(long id)
|
||||
{
|
||||
ulong result = (ulong)id;
|
||||
this.Value = (uint)(result & IdGenerater.Mask20bit);
|
||||
result >>= 20;
|
||||
this.Time = (uint)result & IdGenerater.Mask30bit;
|
||||
result >>= 30;
|
||||
this.Process = (short)(result & IdGenerater.Mask14bit);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"process: {this.Process}, time: {this.Time}, value: {this.Value}";
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct InstanceIdStruct
|
||||
{
|
||||
public uint Time; // 32bit
|
||||
public uint Value; // 32bit
|
||||
|
||||
public long ToLong()
|
||||
{
|
||||
ulong result = 0;
|
||||
result |= this.Time;
|
||||
result <<= 32;
|
||||
result |= this.Value;
|
||||
return (long)result;
|
||||
}
|
||||
|
||||
public InstanceIdStruct(uint time, uint value)
|
||||
{
|
||||
this.Time = time;
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
public InstanceIdStruct(long id)
|
||||
{
|
||||
ulong result = (ulong)id;
|
||||
this.Value = (uint)(result & uint.MaxValue);
|
||||
result >>= 32;
|
||||
this.Time = (uint)(result & uint.MaxValue);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"time: {this.Time}, value: {this.Value}";
|
||||
}
|
||||
}
|
||||
|
||||
public class IdGenerater : Singleton<IdGenerater>, ISingletonAwake
|
||||
{
|
||||
public const int MaxZone = 1024;
|
||||
|
||||
public const int Mask14bit = 0x3fff;
|
||||
public const int Mask30bit = 0x3fffffff;
|
||||
public const int Mask20bit = 0xfffff;
|
||||
|
||||
private long epoch2022;
|
||||
|
||||
private int value;
|
||||
private int instanceIdValue;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
long epoch1970tick = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000;
|
||||
this.epoch2022 = new DateTime(2022, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks / 10000 - epoch1970tick;
|
||||
}
|
||||
|
||||
private uint TimeSince2022()
|
||||
{
|
||||
uint a = (uint)((TimeInfo.Instance.FrameTime - this.epoch2022) / 1000);
|
||||
return a;
|
||||
}
|
||||
|
||||
public long GenerateId()
|
||||
{
|
||||
uint time = TimeSince2022();
|
||||
int v = 0;
|
||||
// 这里必须加锁
|
||||
lock (this)
|
||||
{
|
||||
if (++this.value > Mask20bit - 1)
|
||||
{
|
||||
this.value = 0;
|
||||
}
|
||||
|
||||
v = this.value;
|
||||
}
|
||||
|
||||
IdStruct idStruct = new(time, 3, (uint)v);
|
||||
return idStruct.ToLong();
|
||||
}
|
||||
|
||||
public long GenerateInstanceId()
|
||||
{
|
||||
uint time = this.TimeSince2022();
|
||||
uint v = (uint)Interlocked.Add(ref this.instanceIdValue, 1);
|
||||
InstanceIdStruct instanceIdStruct = new(time, v);
|
||||
return instanceIdStruct.ToLong();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be7c9a4c9ef34fadae987d40419f7509
|
||||
timeCreated: 1733994882
|
||||
85
Assets/Scripts/NBC/Core/Runtime/Services/MonoManager.cs
Normal file
85
Assets/Scripts/NBC/Core/Runtime/Services/MonoManager.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public class MonoManager : MonoBehaviour
|
||||
{
|
||||
public event Action OnUpdate;
|
||||
public event Action OnLateUpdate;
|
||||
public event Action OnFixedUpdate;
|
||||
public event Action OnApplicationQuitAction;
|
||||
public event Action<bool> OnApplicationPauseAction;
|
||||
|
||||
private static bool IsQuiting { get; set; }
|
||||
|
||||
private static MonoManager _inst;
|
||||
|
||||
public static MonoManager Inst
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_inst != null || IsQuiting) return _inst;
|
||||
_inst = FindObjectOfType<MonoManager>();
|
||||
if (_inst == null)
|
||||
{
|
||||
_inst = new GameObject("_MonoTimer").AddComponent<MonoManager>();
|
||||
}
|
||||
|
||||
return _inst;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///Creates the MonoManager singleton
|
||||
public static void Create()
|
||||
{
|
||||
_inst = Inst;
|
||||
}
|
||||
|
||||
protected void OnApplicationQuit()
|
||||
{
|
||||
IsQuiting = true;
|
||||
OnApplicationQuitAction?.Invoke();
|
||||
}
|
||||
|
||||
protected void OnApplicationPause(bool isPause)
|
||||
{
|
||||
OnApplicationPauseAction?.Invoke(isPause);
|
||||
}
|
||||
|
||||
protected void Awake()
|
||||
{
|
||||
if (_inst != null && _inst != this)
|
||||
{
|
||||
DestroyImmediate(this.gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
DontDestroyOnLoad(gameObject);
|
||||
_inst = this;
|
||||
}
|
||||
|
||||
protected void Update()
|
||||
{
|
||||
try
|
||||
{
|
||||
OnUpdate?.Invoke();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void LateUpdate()
|
||||
{
|
||||
OnLateUpdate?.Invoke();
|
||||
}
|
||||
|
||||
protected void FixedUpdate()
|
||||
{
|
||||
OnFixedUpdate?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 869c4449527c495c833b9d848ce61968
|
||||
timeCreated: 1614234084
|
||||
82
Assets/Scripts/NBC/Core/Runtime/Services/Singleton.cs
Normal file
82
Assets/Scripts/NBC/Core/Runtime/Services/Singleton.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public interface ISingletonReverseDispose
|
||||
{
|
||||
}
|
||||
|
||||
public abstract class DisposeObject : IDisposable, ISupportInitialize
|
||||
{
|
||||
public virtual void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void BeginInit()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void EndInit()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ASingleton : DisposeObject
|
||||
{
|
||||
internal abstract void Register();
|
||||
}
|
||||
|
||||
public abstract class Singleton<T> : ASingleton where T : Singleton<T>
|
||||
{
|
||||
private bool _isDisposed;
|
||||
|
||||
|
||||
public static T Instance { get; private set; }
|
||||
|
||||
internal override void Register()
|
||||
{
|
||||
Instance = (T)this;
|
||||
}
|
||||
|
||||
public bool IsDisposed()
|
||||
{
|
||||
return this._isDisposed;
|
||||
}
|
||||
|
||||
protected virtual void Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (this._isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this._isDisposed = true;
|
||||
|
||||
this.Destroy();
|
||||
|
||||
Instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
|
||||
{
|
||||
public static T Instance { get; private set; }
|
||||
|
||||
protected void Awake()
|
||||
{
|
||||
Instance = this as T;
|
||||
OnAwake();
|
||||
}
|
||||
|
||||
protected virtual void OnAwake()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42905ef6b2464dbd92290701d39348a5
|
||||
timeCreated: 1715240819
|
||||
77
Assets/Scripts/NBC/Core/Runtime/Services/TimeInfo.cs
Normal file
77
Assets/Scripts/NBC/Core/Runtime/Services/TimeInfo.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public class TimeInfo: Singleton<TimeInfo>, ISingletonAwake
|
||||
{
|
||||
private int timeZone;
|
||||
|
||||
public int TimeZone
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.timeZone;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.timeZone = value;
|
||||
dt = dt1970.AddHours(TimeZone);
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime dt1970;
|
||||
private DateTime dt;
|
||||
|
||||
// ping消息会设置该值,原子操作
|
||||
public long ServerMinusClientTime { private get; set; }
|
||||
|
||||
public long FrameTime { get; private set; }
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
this.dt1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
this.dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
this.FrameTime = this.ClientNow();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// 赋值long型是原子操作,线程安全
|
||||
this.FrameTime = this.ClientNow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据时间戳获取时间
|
||||
/// </summary>
|
||||
public DateTime ToDateTime(long timeStamp)
|
||||
{
|
||||
return dt.AddTicks(timeStamp * 10000);
|
||||
}
|
||||
|
||||
// 线程安全
|
||||
public long ClientNow()
|
||||
{
|
||||
return (DateTime.UtcNow.Ticks - this.dt1970.Ticks) / 10000;
|
||||
}
|
||||
|
||||
public long ServerNow()
|
||||
{
|
||||
return ClientNow() + this.ServerMinusClientTime;
|
||||
}
|
||||
|
||||
public long ClientFrameTime()
|
||||
{
|
||||
return this.FrameTime;
|
||||
}
|
||||
|
||||
public long ServerFrameTime()
|
||||
{
|
||||
return this.FrameTime + this.ServerMinusClientTime;
|
||||
}
|
||||
|
||||
public long Transition(DateTime d)
|
||||
{
|
||||
return (d.Ticks - dt.Ticks) / 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd695c053e2b4ac9b51cf819f764543f
|
||||
timeCreated: 1733994392
|
||||
411
Assets/Scripts/NBC/Core/Runtime/Services/Timer.cs
Normal file
411
Assets/Scripts/NBC/Core/Runtime/Services/Timer.cs
Normal file
@@ -0,0 +1,411 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
class TimerHandler
|
||||
{
|
||||
public string key;
|
||||
public bool repeat;
|
||||
public float delay;
|
||||
public bool userFrame;
|
||||
public float exeTime;
|
||||
public object caller;
|
||||
public Action<object> methodWithArgs; // 带参数的回调
|
||||
public Action methodWithoutArgs; // 不带参数的回调
|
||||
public object args;
|
||||
public bool jumpFrame;
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
caller = null;
|
||||
methodWithArgs = null;
|
||||
methodWithoutArgs = null;
|
||||
args = null;
|
||||
}
|
||||
|
||||
public void Run(bool withClear)
|
||||
{
|
||||
if (caller == null)
|
||||
{
|
||||
Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// 优先执行无参数回调
|
||||
methodWithoutArgs?.Invoke();
|
||||
// 如果没有无参数回调,则执行带参数回调
|
||||
methodWithArgs?.Invoke(args);
|
||||
|
||||
if (withClear) Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Timer
|
||||
{
|
||||
static Timer()
|
||||
{
|
||||
MonoManager.Inst.OnUpdate += Update;
|
||||
}
|
||||
|
||||
private static void Update()
|
||||
{
|
||||
_timer.Update();
|
||||
}
|
||||
|
||||
private static readonly TimerData _timer = new TimerData();
|
||||
|
||||
#region 无参数回调版本
|
||||
|
||||
/// <summary>
|
||||
/// 定时执行一次(无参数)
|
||||
/// </summary>
|
||||
public static void Once(float delay, object caller, Action method, bool coverBefore = true)
|
||||
{
|
||||
_timer.Once(delay, caller, method, coverBefore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时重复执行(无参数)
|
||||
/// </summary>
|
||||
public static void Loop(float delay, object caller, Action method, bool coverBefore = true,
|
||||
bool jumpFrame = false)
|
||||
{
|
||||
_timer.Loop(delay, caller, method, coverBefore, jumpFrame);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时执行一次(基于帧率,无参数)
|
||||
/// </summary>
|
||||
public static void FrameOnce(int delay, object caller, Action method, bool coverBefore = true)
|
||||
{
|
||||
_timer.FrameOnce(delay, caller, method, coverBefore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时重复执行(基于帧率,无参数)
|
||||
/// </summary>
|
||||
public static void FrameLoop(int delay, object caller, Action method, bool coverBefore = true)
|
||||
{
|
||||
_timer.FrameLoop(delay, caller, method, coverBefore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理定时器(无参数版本)
|
||||
/// </summary>
|
||||
public static void Clear(object caller, Action method)
|
||||
{
|
||||
_timer.Clear(caller, method);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 带参数回调版本
|
||||
|
||||
/// <summary>
|
||||
/// 定时执行一次(带参数)
|
||||
/// </summary>
|
||||
public static void Once(float delay, object caller, Action<object> method, object args = null,
|
||||
bool coverBefore = true)
|
||||
{
|
||||
_timer.Once(delay, caller, method, args, coverBefore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时重复执行(带参数)
|
||||
/// </summary>
|
||||
public static void Loop(float delay, object caller, Action<object> method, object args = null,
|
||||
bool coverBefore = true, bool jumpFrame = false)
|
||||
{
|
||||
_timer.Loop(delay, caller, method, args, coverBefore, jumpFrame);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时执行一次(基于帧率,带参数)
|
||||
/// </summary>
|
||||
public static void FrameOnce(int delay, object caller, Action<object> method, object args = null,
|
||||
bool coverBefore = true)
|
||||
{
|
||||
_timer.FrameOnce(delay, caller, method, args, coverBefore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时重复执行(基于帧率,带参数)
|
||||
/// </summary>
|
||||
public static void FrameLoop(int delay, object caller, Action<object> method, object args = null,
|
||||
bool coverBefore = true)
|
||||
{
|
||||
_timer.FrameLoop(delay, caller, method, args, coverBefore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理定时器(带参数版本)
|
||||
/// </summary>
|
||||
public static void Clear(object caller, Action<object> method)
|
||||
{
|
||||
_timer.Clear(caller, method);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 清理对象身上的所有定时器
|
||||
/// </summary>
|
||||
public static void ClearAll(object caller)
|
||||
{
|
||||
_timer.ClearAll(caller);
|
||||
}
|
||||
}
|
||||
|
||||
public class TimerData
|
||||
{
|
||||
private static readonly Queue<TimerHandler> _pool = new Queue<TimerHandler>();
|
||||
private static int _mid = 1;
|
||||
|
||||
public float CurrTimer = Time.time;
|
||||
public int CurrFrame = 0;
|
||||
private float _delta = 0;
|
||||
private float _lastTimer = Time.time;
|
||||
|
||||
private Dictionary<string, TimerHandler> _map = new Dictionary<string, TimerHandler>();
|
||||
private List<TimerHandler> _handlers = new List<TimerHandler>();
|
||||
private List<TimerHandler> _temp = new List<TimerHandler>();
|
||||
private int _count = 0;
|
||||
|
||||
public float delta => _delta;
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
var frame = CurrFrame += 1;
|
||||
var now = Time.time;
|
||||
var awake = (now - _lastTimer) > 30000;
|
||||
|
||||
_delta = (now - _lastTimer);
|
||||
var timer = CurrTimer += _delta;
|
||||
_lastTimer = now;
|
||||
|
||||
_count = 0;
|
||||
for (int i = 0, n = _handlers.Count; i < n; i++)
|
||||
{
|
||||
var handler = _handlers[i];
|
||||
if (handler.methodWithArgs != null || handler.methodWithoutArgs != null)
|
||||
{
|
||||
var t = handler.userFrame ? frame : timer;
|
||||
if (t >= handler.exeTime)
|
||||
{
|
||||
if (handler.repeat)
|
||||
{
|
||||
if (!handler.jumpFrame || awake)
|
||||
{
|
||||
handler.exeTime += handler.delay;
|
||||
handler.Run(false);
|
||||
if (t > handler.exeTime)
|
||||
{
|
||||
handler.exeTime += Mathf.Ceil((t - handler.exeTime) / handler.delay) *
|
||||
handler.delay;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (t >= handler.exeTime)
|
||||
{
|
||||
handler.exeTime += handler.delay;
|
||||
handler.Run(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handler.Run(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_count > 30 || frame % 200 == 0) _clearHandlers();
|
||||
}
|
||||
|
||||
private void _clearHandlers()
|
||||
{
|
||||
var handlers = _handlers;
|
||||
for (int i = 0, n = handlers.Count; i < n; i++)
|
||||
{
|
||||
var handler = handlers[i];
|
||||
if (handler.methodWithArgs != null || handler.methodWithoutArgs != null)
|
||||
_temp.Add(handler);
|
||||
else
|
||||
_recoverHandler(handler);
|
||||
}
|
||||
|
||||
_handlers = _temp;
|
||||
handlers.Clear();
|
||||
_temp = handlers;
|
||||
}
|
||||
|
||||
private void _recoverHandler(TimerHandler handler)
|
||||
{
|
||||
if (_map.TryGetValue(handler.key, out var h) && h == handler)
|
||||
{
|
||||
_map.Remove(handler.key);
|
||||
handler.Clear();
|
||||
_pool.Enqueue(handler);
|
||||
}
|
||||
}
|
||||
|
||||
#region 无参数回调版本
|
||||
|
||||
public void Once(float delay, object caller, Action method, bool coverBefore = true)
|
||||
{
|
||||
_create(false, false, delay, caller, null, method, null, coverBefore);
|
||||
}
|
||||
|
||||
public void Loop(float delay, object caller, Action method, bool coverBefore = true, bool jumpFrame = false)
|
||||
{
|
||||
var handler = _create(false, true, delay, caller, null, method, null, coverBefore);
|
||||
if (handler != null) handler.jumpFrame = jumpFrame;
|
||||
}
|
||||
|
||||
public void FrameOnce(int delay, object caller, Action method, bool coverBefore = true)
|
||||
{
|
||||
_create(true, false, delay, caller, null, method, null, coverBefore);
|
||||
}
|
||||
|
||||
public void FrameLoop(int delay, object caller, Action method, bool coverBefore = true)
|
||||
{
|
||||
_create(true, true, delay, caller, null, method, null, coverBefore);
|
||||
}
|
||||
|
||||
public void Clear(object caller, Action method)
|
||||
{
|
||||
var handler = _getHandler(caller, null, method);
|
||||
handler?.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 带参数回调版本
|
||||
|
||||
public void Once(float delay, object caller, Action<object> method, object args = null, bool coverBefore = true)
|
||||
{
|
||||
_create(false, false, delay, caller, method, null, args, coverBefore);
|
||||
}
|
||||
|
||||
public void Loop(float delay, object caller, Action<object> method, object args = null, bool coverBefore = true,
|
||||
bool jumpFrame = false)
|
||||
{
|
||||
var handler = _create(false, true, delay, caller, method, null, args, coverBefore);
|
||||
if (handler != null) handler.jumpFrame = jumpFrame;
|
||||
}
|
||||
|
||||
public void FrameOnce(int delay, object caller, Action<object> method, object args = null,
|
||||
bool coverBefore = true)
|
||||
{
|
||||
_create(true, false, delay, caller, method, null, args, coverBefore);
|
||||
}
|
||||
|
||||
public void FrameLoop(int delay, object caller, Action<object> method, object args = null,
|
||||
bool coverBefore = true)
|
||||
{
|
||||
_create(true, true, delay, caller, method, null, args, coverBefore);
|
||||
}
|
||||
|
||||
public void Clear(object caller, Action<object> method)
|
||||
{
|
||||
var handler = _getHandler(caller, method, null);
|
||||
handler?.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private TimerHandler _create(bool useFrame, bool repeat, float delay, object caller,
|
||||
Action<object> methodWithArgs, Action methodWithoutArgs,
|
||||
object args, bool coverBefore)
|
||||
{
|
||||
// 如果延迟为0,则立即执行
|
||||
if (delay <= 0)
|
||||
{
|
||||
if (methodWithoutArgs != null)
|
||||
methodWithoutArgs.Invoke();
|
||||
else
|
||||
methodWithArgs?.Invoke(args);
|
||||
return null;
|
||||
}
|
||||
|
||||
TimerHandler handler;
|
||||
// 先覆盖相同函数的计时
|
||||
if (coverBefore)
|
||||
{
|
||||
handler = _getHandler(caller, methodWithArgs, methodWithoutArgs);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.repeat = repeat;
|
||||
handler.userFrame = useFrame;
|
||||
handler.delay = delay;
|
||||
handler.caller = caller;
|
||||
handler.methodWithArgs = methodWithArgs;
|
||||
handler.methodWithoutArgs = methodWithoutArgs;
|
||||
handler.args = args;
|
||||
handler.exeTime = delay + (useFrame ? CurrFrame : CurrTimer + Time.time - _lastTimer);
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
// 找到一个空闲的timerHandler
|
||||
handler = _pool.Count > 0 ? _pool.Dequeue() : new TimerHandler();
|
||||
handler.repeat = repeat;
|
||||
handler.userFrame = useFrame;
|
||||
handler.delay = delay;
|
||||
handler.caller = caller;
|
||||
handler.methodWithArgs = methodWithArgs;
|
||||
handler.methodWithoutArgs = methodWithoutArgs;
|
||||
handler.args = args;
|
||||
handler.exeTime = delay + (useFrame ? CurrFrame : CurrTimer + Time.time - _lastTimer);
|
||||
|
||||
// 索引handler
|
||||
_indexHandler(handler);
|
||||
|
||||
// 插入数组
|
||||
_handlers.Add(handler);
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
private TimerHandler _getHandler(object caller, Action<object> methodWithArgs, Action methodWithoutArgs)
|
||||
{
|
||||
var key = caller.GetHashCode() + "_" +
|
||||
(methodWithArgs?.GetHashCode() ?? methodWithoutArgs.GetHashCode());
|
||||
return _map.GetValueOrDefault(key);
|
||||
}
|
||||
|
||||
private void _indexHandler(TimerHandler handler)
|
||||
{
|
||||
var key = handler.caller.GetHashCode() + "_" +
|
||||
(handler.methodWithArgs?.GetHashCode() ?? handler.methodWithoutArgs.GetHashCode());
|
||||
handler.key = key;
|
||||
_map[key] = handler;
|
||||
}
|
||||
|
||||
public void ClearAll(object caller)
|
||||
{
|
||||
if (caller == null) return;
|
||||
for (int i = 0, n = _handlers.Count; i < n; i++)
|
||||
{
|
||||
var handler = _handlers[i];
|
||||
if (handler.caller == caller)
|
||||
{
|
||||
handler.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "handlers:" + _handlers.Count + "pool:" + _pool.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Services/Timer.cs.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Services/Timer.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34564c54c20648aab48bc9dcdc333435
|
||||
timeCreated: 1614222135
|
||||
Reference in New Issue
Block a user