首次提交

This commit is contained in:
Bob.Song
2026-03-05 18:07:55 +08:00
commit e125bb869e
4534 changed files with 563920 additions and 0 deletions

View 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);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5543bf08377d4c0289f50e9b465963b6
timeCreated: 1733994653

View 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();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: be7c9a4c9ef34fadae987d40419f7509
timeCreated: 1733994882

View 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();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 869c4449527c495c833b9d848ce61968
timeCreated: 1614234084

View 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()
{
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 42905ef6b2464dbd92290701d39348a5
timeCreated: 1715240819

View 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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fd695c053e2b4ac9b51cf819f764543f
timeCreated: 1733994392

View 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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 34564c54c20648aab48bc9dcdc333435
timeCreated: 1614222135