升级框架版本

This commit is contained in:
Bob.Song
2025-11-12 17:24:02 +08:00
parent 4059c207c0
commit 5e6119a073
2246 changed files with 6233 additions and 313 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cf2ee6bcf7bf9f94eb3eab2a87540dcd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
using System;
namespace NBC
{
[AttributeUsage(AttributeTargets.Class)]
public class BaseAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Method)]
public class SortAttribute : Attribute
{
public int Sort;
public SortAttribute(int sort)
{
Sort = sort;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 32bc35c38967479d81a79bd1354d38e8
timeCreated: 1733995116

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5ccc2499679c40909ac59a0a325c78c4
timeCreated: 1759160041

View File

@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace NBC
{
public interface IConfigContext
{
// 定义非泛型接口
}
public class ConfigContext<T> : IConfigContext where T : IConfigTable
{
private static List<T> _cacheList = new List<T>();
#region Cache
public void Association(List<T> list)
{
if (list != null)
{
_cacheList = list;
}
}
#endregion
public int Count()
{
return _cacheList.Count;
}
public int Count(Func<T, bool> predicate)
{
return _cacheList.Count(predicate);
}
public T Get(uint key)
{
return First(key);
}
public T Fist()
{
return _cacheList.First();
}
public T Last()
{
return _cacheList.Last();
}
public T Fist(Predicate<T> match)
{
return Get(match);
}
public T Last(Predicate<T> match)
{
return _cacheList.FindLast(match);
}
public T Get(Predicate<T> match)
{
return _cacheList.Find(match);
}
public T GetRandom()
{
Random random = new Random();
// 随机从列表中取一个对象
return _cacheList[random.Next(_cacheList.Count)];
}
public List<T> GetList()
{
return _cacheList;
}
public List<T> GetList(Predicate<T> match)
{
return _cacheList.FindAll(match);
}
private T First(uint key)
{
return _cacheList.Find(t => t.Key == key);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f916dd8f41b047068d570fc87f9163c2
timeCreated: 1760064105

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json.Linq;
namespace NBC
{
/// <summary>
/// 配置表帮助类
/// </summary>
public static class ConfigTableHelper
{
private static readonly Dictionary<Type, IConfigContext> _dictionary = new Dictionary<Type, IConfigContext>();
/// <summary>
/// 初始化ConfigTableHelper
/// </summary>
public static void Initialize(string json)
{
var jsonObj = JObject.Parse(json);
Dictionary<string, JArray> tokens = new();
foreach (var item in jsonObj)
{
try
{
var name = item.Key;
var value = item.Value;
if (value is JArray jArray)
{
tokens[name] = jArray;
}
}
catch (Exception e)
{
Log.Error($"读表异常请检查name={item.Key} ex={e}");
}
}
//反射获取所有IConfigTable的非抽象类
var tableTypes = GetAllConfigTableTypes();
foreach (var type in tableTypes)
{
var name = type.Name;
if (tokens.TryGetValue(name, out var jArray))
{
// 通过反射调用 ParseJson 方法
var parseMethod = type.GetMethod("ParseJson", BindingFlags.Public | BindingFlags.Static);
parseMethod?.Invoke(null, new object[] { jArray });
}
}
}
public static ConfigContext<T> Table<T>() where T : IConfigTable
{
var type = typeof(T);
if (_dictionary.TryGetValue(type, out var context))
{
return context as ConfigContext<T>;
}
var jsonContext = new ConfigContext<T>();
_dictionary[type] = jsonContext;
return jsonContext;
}
public static List<T> ParseLine<T>(JArray arr) where T : IConfigTable, new()
{
List<T> list = new List<T>();
foreach (var jToken in arr)
{
T instance = jToken.ToObject<T>();
if (instance != null)
{
list.Add(instance);
}
}
var context = Table<T>();
context.Association(list);
return list;
}
/// <summary>
/// 获取所有实现了 IConfigTable 接口的非抽象类
/// </summary>
/// <returns>所有非抽象的配置对象类</returns>
private static List<Type> GetAllConfigTableTypes()
{
var types = new List<Type>();
var interfaceType = typeof(IConfigTable);
// 遍历当前程序集中的所有类型
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in assembly.GetTypes())
{
// 检查是否实现了 IConfigTable 接口,并且不是抽象类
if (interfaceType.IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface)
{
types.Add(type);
}
}
}
return types;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: de53a788ec4e446eb6c07c50c65afcc2
timeCreated: 1759160093

View File

@@ -0,0 +1,19 @@
namespace NBC
{
/// <summary>
/// 表示是一个配置文件
/// </summary>
public interface IConfigTable
{
public uint Key { get; }
}
public interface IConfigItemTable
{
public string Model { get; }
public string Quality { get; }
public string Icon { get; }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: df4eb038440a4a498e27ccaf23a1cd9b
timeCreated: 1759160060

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7be619d8f5a4dc641a1a1f92306d41e0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
namespace NBC
{
/// <summary>
/// 事件对象 用于派发事件传参数使用
/// </summary>
public class EventArgs
{
public EventArgs()
{
}
public EventArgs(string type)
{
Type = type;
}
public EventArgs(string type, object data)
{
Type = type;
Data = data;
}
// private static readonly Queue<EventArgs> _poolQueue = new Queue<EventArgs>();
/// <summary>
/// 派发事件的对象
/// </summary>
public IEventDispatcher Sender;
/// <summary>
/// 派发事件夹带的普通参数
/// </summary>
public object Data;
/// <summary>
/// 事件类型
/// </summary>
public string Type;
/// <summary>
/// 是否停止事件派发
/// </summary>
public bool IsPropagationImmediateStopped;
/// <summary>
/// 流转传递参数(用于高优先级往低优先级传递)
/// </summary>
public object TransmitData;
/// <summary>
/// 停止一个事件的派发
/// </summary>
public void StopImmediatePropagation()
{
IsPropagationImmediateStopped = true;
}
/// <summary>
/// 设置流转数据
/// </summary>
/// <param name="data">需要流转的数据</param>
public void SetTransmitData(object data)
{
TransmitData = data;
}
/// <summary>
/// 清理对象
/// </summary>
protected void Clean()
{
Data = null;
IsPropagationImmediateStopped = false;
}
public static T Create<T>(string type) where T : EventArgs, new()
{
EventArgs eventArgs;
// if (_poolQueue.Count > 0)
// {
// eventArgs = _poolQueue.Dequeue();
// }
// else
// {
// var t = typeof(T);
// eventArgs = Activator.CreateInstance(t) as EventArgs;
// _poolQueue.Enqueue(eventArgs);
// }
var t = typeof(T);
eventArgs = Activator.CreateInstance(t) as EventArgs;
if (eventArgs != null)
{
eventArgs.Type = type;
}
return eventArgs as T;
}
/// <summary>
/// 派发一个特定事件
/// </summary>
/// <param name="target">派发一个事件</param>
/// <param name="type">事件类型</param>
/// <param name="data">事件附带参数</param>
public static void DispatchEvent(IEventDispatcher target, string type, object data)
{
var ev = Create<EventArgs>(type);
ev.Data = data;
target.DispatchEvent(ev);
Release(ev);
}
/// <summary>
/// 释放事件对象
/// </summary>
/// <param name="ev"></param>
public static void Release(EventArgs ev)
{
ev.Clean();
// _poolQueue.Enqueue(ev);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 371d9cba4de694e47a6a6f28b7f0c956
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,217 @@
using System;
using System.Collections.Generic;
namespace NBC
{
struct EventBin
{
public string type;
public Action<EventArgs> listener;
public object thisObject;
public int priority;
public EventDispatcher target;
public bool dispatchOnce;
}
public class EventDispatcher : IEventDispatcher
{
private readonly Dictionary<string, List<EventBin>>
_dicEventListener = new Dictionary<string, List<EventBin>>();
// private Queue<EventBin> _curNeedDispatcherListeners;
private readonly Stack<EventBin> _onceList = new Stack<EventBin>();
public IEventDispatcher On(string type, Action<EventArgs> listener, object caller, int priority = 0,
bool once = false)
{
List<EventBin> list;
if (HasEventListener(type))
{
list = _dicEventListener[type];
}
else
{
list = new List<EventBin>();
_dicEventListener[type] = list;
}
InsertEventBin(list, type, listener, caller, priority, once);
return this;
}
public IEventDispatcher Once(string type, Action<EventArgs> listener, object caller, int priority = 0)
{
On(type, listener, caller, priority, true);
return this;
}
public IEventDispatcher Off(string type, Action<EventArgs> listener, object caller)
{
RemoveListener(type, listener, caller);
return this;
}
public IEventDispatcher OffAll(string type = "")
{
if (type != "" && HasEventListener(type))
{
_dicEventListener.Remove(type);
}
else
{
_dicEventListener.Clear();
}
return this;
}
public IEventDispatcher OffAllCaller(object caller)
{
List<EventBin> arr = new List<EventBin>();
foreach (var v in _dicEventListener.Values)
{
foreach (var eventBin in v)
{
if (eventBin.thisObject == caller)
{
arr.Add(eventBin);
}
}
}
foreach (var e in arr)
{
RemoveListener(e.type, e.listener, e.thisObject);
}
return this;
}
public bool HasEventListener(string type)
{
return _dicEventListener.ContainsKey(type);
}
public void DispatchEvent(EventArgs ev)
{
ev.Sender = this;
notifyListener(ev);
}
public bool DispatchEventWith(string type, object data = null)
{
if (HasEventListener(type))
{
EventArgs eventArgs = EventArgs.Create<EventArgs>(type);
eventArgs.Data = data;
DispatchEvent(eventArgs);
EventArgs.Release(eventArgs);
}
return true;
}
private bool InsertEventBin(List<EventBin> list, string type, Action<EventArgs> listener, object thisObject,
int priority = 0, bool dispatchOnce = false)
{
var insertIndex = -1;
var length = list.Count;
for (var i = 0; i < length; i++)
{
var bin = list[i];
if (bin.listener == listener && bin.thisObject == thisObject && bin.target == this)
{
return false;
}
if (insertIndex == -1 && bin.priority < priority)
{
insertIndex = i;
}
}
var eventBin = new EventBin
{
type = type,
listener = listener,
thisObject = thisObject,
priority = priority,
target = this,
dispatchOnce = dispatchOnce
};
if (insertIndex != -1)
{
list.Insert(insertIndex, eventBin);
}
else
{
list.Add(eventBin);
}
return true;
}
private void RemoveListener(string type, Action<EventArgs> listener, object caller)
{
if (HasEventListener(type))
{
RemoveEventBin(_dicEventListener[type], listener, caller);
}
}
private bool RemoveEventBin(List<EventBin> list, Action<EventArgs> listener, object caller)
{
var length = list.Count;
for (var i = 0; i < length; i++)
{
var bin = list[i];
if (bin.listener == listener && bin.thisObject == caller && bin.target == this)
{
list.RemoveAt(i);
return true;
}
}
return false;
}
private void notifyListener(EventArgs eventArgs)
{
if (!_dicEventListener.ContainsKey(eventArgs.Type)) return;
var list = _dicEventListener[eventArgs.Type];
var length = list.Count;
if (length <= 0) return;
var curNeedDispatcherListeners = new Queue<EventBin>();
var curIndex = 0;
while (curIndex < list.Count)
{
var eventBin = list[curIndex];
curNeedDispatcherListeners.Enqueue(eventBin);
curIndex++;
}
while (curNeedDispatcherListeners.Count > 0)
{
var eventBin = curNeedDispatcherListeners.Dequeue();
eventBin.listener?.Invoke(eventArgs);
if (eventBin.dispatchOnce)
{
_onceList.Push(eventBin);
}
if(eventArgs.IsPropagationImmediateStopped) break;
}
while (_onceList.Count > 0)
{
var eventBin = _onceList.Pop();
eventBin.target.Off(eventBin.type, eventBin.listener, eventBin.thisObject);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d03163cd522f1f44a06979858fa2ee5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,71 @@
using System;
namespace NBC
{
public interface IEventDispatcher
{
/// <summary>
/// 注册一个消息
/// </summary>
/// <param name="type">消息类型</param>
/// <param name="listener">监听函数</param>
/// <param name="caller">监听对象</param>
/// <param name="priority">优先级</param>
/// <param name="once">是否只执行一次监听</param>
/// <returns></returns>
IEventDispatcher On(string type, Action<EventArgs> listener, object caller, int priority = 0,
bool once = false);
/// <summary>
/// 注册一个监听一次的消息
/// </summary>
/// <param name="type">消息类型</param>
/// <param name="listener">监听函数</param>
/// <param name="caller">监听对象</param>
/// <param name="priority">优先级</param>
/// <returns></returns>
IEventDispatcher Once(string type, Action<EventArgs> listener, object caller, int priority = 0);
/// <summary>
/// 取消监听
/// </summary>
/// <param name="type"></param>
/// <param name="listener"></param>
/// <param name="caller"></param>
/// <returns></returns>
IEventDispatcher Off(string type, Action<EventArgs> listener, object caller);
/// <summary>
/// 取消这个消息的所有监听
/// </summary>
/// <param name="type"></param>
IEventDispatcher OffAll(string type = "");
/// <summary>
/// 取消接受对象上的所有消息
/// </summary>
/// <param name="caller"></param>
/// <returns></returns>
IEventDispatcher OffAllCaller(object caller);
/// <summary>
/// 是否存在监听
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
bool HasEventListener(string type);
/// <summary>
/// 派发消息
/// </summary>
/// <param name="ev"></param>
void DispatchEvent(EventArgs ev);
/// <summary>
/// 根据消息类型派发消息
/// </summary>
/// <param name="type"></param>
/// <param name="data"></param>
bool DispatchEventWith(string type, object data = null);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ee3ce226192bcd648bc228e5e92b6ee2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b7ea503f24bbc61469a7fc48ec60659f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using Unity.VisualScripting;
namespace NBC
{
public class Fsm<TOwnerClass>
{
private FsmBaseState<TOwnerClass> _currentState;
private Dictionary<uint, FsmBaseState<TOwnerClass>> _states = new Dictionary<uint, FsmBaseState<TOwnerClass>>();
private Dictionary<Type, uint> _stateType2Id = new Dictionary<Type, uint>();
private bool _doDebugOutput;
private TOwnerClass _owner;
private string _description;
public uint CurrentStateId => _currentState.StateId;
public FsmBaseState<TOwnerClass> CurrentState => _currentState;
public Fsm(string description, TOwnerClass owner, bool debugOutput = false)
{
_description = description;
_owner = owner;
_doDebugOutput = debugOutput;
}
public void RegisterState<T>() where T : FsmBaseState<TOwnerClass>, new()
{
var type = typeof(T);
if (_stateType2Id.ContainsKey(type))
{
LogError("State {0} already registered", type);
return;
}
T result = new T();
_stateType2Id[type] = result.StateId;
_states[result.StateId] = result;
result.Init(_owner, this);
}
public void Start<T>() where T : FsmBaseState<TOwnerClass>, new()
{
Log("start");
EnterState(typeof(T));
}
public void EnterState(Type type, FsmBaseState<TOwnerClass> sourceState = null)
{
if (_stateType2Id.TryGetValue(type, out var id))
{
EnterState(id, sourceState);
}
}
public void EnterState(uint stateId, FsmBaseState<TOwnerClass> sourceState = null)
{
uint prevState = 0;
FsmTransmit param = null;
if (_currentState != null)
{
prevState = _currentState.StateId;
param = _currentState.Params;
_currentState.Exit();
}
_currentState = _states[stateId];
_currentState.PrevState = prevState;
if (param != null)
{
_currentState.Params.AddRange(param);
param.Clear();
}
if (sourceState != null)
{
_currentState.Transition(sourceState);
}
else
{
_currentState.Enter();
}
}
public void Update()
{
if (_currentState != null)
{
_currentState.PreUpdate();
var type = _currentState.Update();
if (type != 0)
{
_currentState.NextState = type;
EnterState(type);
}
}
}
public void FixedUpdate()
{
if (_currentState != null)
{
var type = _currentState.FixedUpdate();
if (type != 0)
{
_currentState.NextState = type;
EnterState(type);
}
}
}
public void LateUpdate()
{
if (_currentState != null)
{
var type = _currentState.LateUpdate();
if (type != 0)
{
_currentState.NextState = type;
EnterState(type);
}
}
}
public void LogError(string textPattern, params object[] args)
{
}
public void Log(string text)
{
if (!_doDebugOutput)
{
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 53d2b03339c14d70af4039451671366f

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace NBC
{
public abstract class FsmBaseState<TOwnerClass>
{
protected TOwnerClass _owner;
protected Fsm<TOwnerClass> Root;
public FsmTransmit Params = new FsmTransmit();
public abstract uint StateId { get; }
public uint PrevState { get; set; }
public uint NextState { get; set; }
protected float EnterTime { get; set; }
public void Init(TOwnerClass owner, Fsm<TOwnerClass> fsm)
{
_owner = owner;
Root = fsm;
}
public virtual void Transition(FsmBaseState<TOwnerClass> source)
{
Enter();
}
public void Enter()
{
EnterTime = Time.time;
onEnter();
}
protected virtual void onEnter()
{
}
public void Exit()
{
onExit();
}
protected virtual void onExit()
{
}
public uint Update()
{
return onUpdate();
}
protected virtual uint onUpdate()
{
return 0;
}
public uint FixedUpdate()
{
return onFixedUpdate();
}
protected virtual uint onFixedUpdate()
{
return 0;
}
public void PreUpdate()
{
OnPreUpdate();
}
protected virtual void OnPreUpdate()
{
}
public uint LateUpdate()
{
return OnLateUpdate();
}
protected virtual uint OnLateUpdate()
{
return 0;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6fefa29788c940ebb9bfb95358cca1a0
timeCreated: 1732110077

View File

@@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Linq;
namespace NBC
{
public class FsmTransmit
{
private readonly List<object> _queue = new List<object>();
public List<object> AllParam => _queue;
public void Add(object o)
{
_queue.Add(o);
}
public void AddRange(FsmTransmit transmit)
{
_queue.AddRange(transmit.AllParam);
}
public void AddRange(IEnumerable<object> o)
{
_queue.AddRange(o);
}
public object Get(int index)
{
if (index >= 0 && index < _queue.Count)
{
return _queue[index];
}
return null;
}
public void Clear()
{
_queue.Clear();
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4288fa116ccf436983b60932fbe19d3b

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1669c1cc72dc47b9a04dc04d157cef0f
timeCreated: 1762935551

View File

@@ -0,0 +1,121 @@
using System;
using System.Diagnostics;
namespace NBC
{
public static class Log
{
/// <summary>
/// 记录跟踪级别的日志消息。
/// </summary>
/// <param name="msg">日志消息。</param>
public static void Trace(string msg)
{
Fantasy.Log.Trace(msg);
}
/// <summary>
/// 记录调试级别的日志消息。
/// </summary>
/// <param name="msg">日志消息。</param>
public static void Debug(string msg)
{
Fantasy.Log.Debug(msg);
}
/// <summary>
/// 记录信息级别的日志消息。
/// </summary>
/// <param name="msg">日志消息。</param>
public static void Info(string msg)
{
Fantasy.Log.Info(msg);
}
/// <summary>
/// 记录跟踪级别的日志消息,并附带调用栈信息。
/// </summary>
/// <param name="msg">日志消息。</param>
public static void TraceInfo(string msg)
{
Fantasy.Log.TraceInfo(msg);
}
/// <summary>
/// 记录警告级别的日志消息。
/// </summary>
/// <param name="msg">日志消息。</param>
public static void Warning(string msg)
{
Fantasy.Log.Warning(msg);
}
/// <summary>
/// 记录错误级别的日志消息,并附带调用栈信息。
/// </summary>
/// <param name="msg">日志消息。</param>
public static void Error(string msg)
{
Fantasy.Log.Error(msg);
}
/// <summary>
/// 记录异常的错误级别的日志消息,并附带调用栈信息。
/// </summary>
/// <param name="e">异常对象。</param>
public static void Error(Exception e)
{
Fantasy.Log.Error(e);
}
/// <summary>
/// 记录跟踪级别的格式化日志消息,并附带调用栈信息。
/// </summary>
/// <param name="message">日志消息模板。</param>
/// <param name="args">格式化参数。</param>
public static void Trace(string message, params object[] args)
{
Fantasy.Log.Trace(message, args);
}
/// <summary>
/// 记录警告级别的格式化日志消息。
/// </summary>
/// <param name="message">日志消息模板。</param>
/// <param name="args">格式化参数。</param>
public static void Warning(string message, params object[] args)
{
Fantasy.Log.Warning(message, args);
}
/// <summary>
/// 记录信息级别的格式化日志消息。
/// </summary>
/// <param name="message">日志消息模板。</param>
/// <param name="args">格式化参数。</param>
public static void Info(string message, params object[] args)
{
Fantasy.Log.Info(message, args);
}
/// <summary>
/// 记录调试级别的格式化日志消息。
/// </summary>
/// <param name="message">日志消息模板。</param>
/// <param name="args">格式化参数。</param>
public static void Debug(string message, params object[] args)
{
Fantasy.Log.Debug(message, args);
}
/// <summary>
/// 记录错误级别的格式化日志消息,并附带调用栈信息。
/// </summary>
/// <param name="message">日志消息模板。</param>
/// <param name="args">格式化参数。</param>
public static void Error(string message, params object[] args)
{
Fantasy.Log.Error(message, args);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b9649baebc8f4002b5e0778a454b5573
timeCreated: 1762935556

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 611da49ee53645f5baed0faff24cbe33
timeCreated: 1751421490

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d069cf2e375b8a74ebab6f3df1f74a91
timeCreated: 1656996254

View File

@@ -0,0 +1,111 @@
namespace NBC
{
public class ParallelTaskCollection : TaskCollection
{
private int _currentIndex = 0;
/// <summary>
/// 最大并行数量 (默认为9)
/// </summary>
public int ParallelNum = 9;
protected override NTaskStatus RunTasksAndCheckIfDone()
{
var st = NTaskStatus.Running;
if (CurRunTask.Count < ParallelNum && _currentIndex < RawList.Count)
{
var num = ParallelNum - CurRunTask.Count;
for (var index = 0; index < num; index++)
{
if (_currentIndex < RawList.Count)
{
CurRunTask.Add(RawList[_currentIndex]);
_currentIndex += 1;
}
}
}
for (var index = 0; index < CurrentTask.Count; index++)
{
var element = CurrentTask[index];
var childSt = element.Process();
if (FailBreak && childSt == NTaskStatus.Fail)
{
_errorMsg = element.ErrorMsg;
st = NTaskStatus.Fail;
break;
}
if (childSt == NTaskStatus.Success || childSt == NTaskStatus.Fail)
{
CurrentTask.RemoveAt(index);
index--;
FinishList.Add(element);
}
}
if (FinishList.Count >= RawList.Count)
{
st = NTaskStatus.Success;
}
// for (var index = 0; index < CurrentTask.Count; index++)
// {
// var element = CurrentTask[index];
// var childSt = element.Process();
//
// if (childSt >= Status.Success)
// {
// if (FailBreak && childSt == Status.Fail)
// {
// _errorMsg = element.ErrorMsg;
// st = Status.Fail;
// }
//
// CurrentTask.RemoveAt(index);
// index--;
// FinishList.Add(element);
// }
// }
//
// if (FinishList.Count >= RawList.Count)
// {
// st = Status.Success;
// }
// else if (CurRunTask.Count < ParallelNum && _currentIndex < RawList.Count)
// {
// var num = ParallelNum - CurRunTask.Count;
// for (var index = 0; index < num; index++)
// {
// if (_currentIndex < RawList.Count)
// {
// CurRunTask.Add(RawList[_currentIndex]);
// _currentIndex += 1;
// }
// }
// }
return st;
}
public override void Reset()
{
base.Reset();
_currentIndex = 0;
}
public override void Stop()
{
base.Stop();
_currentIndex = 0;
}
public override void Clear()
{
base.Clear();
_currentIndex = 0;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 33f78136d6a7de14688a6d3ed6903557
timeCreated: 1657002644

View File

@@ -0,0 +1,119 @@
namespace NBC
{
public class SequenceTaskCollection : TaskCollection
{
private int _currentIndex;
public override string Info
{
get
{
if (CurrentTask != null && CurrentTask.Count > 0)
{
return CurrentTask[0].Info;
}
return TaskInfo;
}
}
protected override NTaskStatus RunTasksAndCheckIfDone()
{
var st = NTaskStatus.Running;
if (RawList.Count > 0)
{
if (CurRunTask.Count == 0 && _currentIndex < RawList.Count)
{
CurRunTask.Add(RawList[_currentIndex]);
}
NTaskStatus curSt;
do
{
var childTask = CurRunTask[0];
curSt = childTask.Process();
if (curSt >= NTaskStatus.Success)
{
if (FailBreak && curSt == NTaskStatus.Fail)
{
_errorMsg = childTask.ErrorMsg;
st = NTaskStatus.Fail;
break;
}
FinishList.Add(childTask);
CurRunTask.RemoveAt(0);
_currentIndex++;
if (_currentIndex < RawList.Count)
CurRunTask.Add(RawList[_currentIndex]);
}
} while (curSt >= NTaskStatus.Success && CurRunTask.Count > 0);
if (FinishList.Count == RawList.Count)
st = NTaskStatus.Success;
}
else
{
st = NTaskStatus.Success;
}
// if (RawList.Count > 0)
// {
// if (FinishList.Count == RawList.Count)
// {
// st = Status.Success;
// }
// else
// {
// if (CurRunTask.Count == 0)
// {
// CurRunTask.Add(RawList[_currentIndex]);
// }
//
// var childTask = CurRunTask[0];
// var curSt = childTask.Process();
//
//
// if (curSt >= Status.Success)
// {
// if (FailBreak && curSt == Status.Fail)
// {
// _errorMsg = childTask.ErrorMsg;
// st = Status.Fail;
// }
//
// FinishList.Add(childTask);
// CurRunTask.RemoveAt(0);
// _currentIndex++;
// }
// }
// }
// else
// {
// st = Status.Success;
// }
return st;
}
public override void Reset()
{
base.Reset();
_currentIndex = 0;
}
public override void Stop()
{
base.Stop();
_currentIndex = 0;
}
public override void Clear()
{
base.Clear();
_currentIndex = 0;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7440203326fc09a479080181660af525
timeCreated: 1657003965

View File

@@ -0,0 +1,95 @@
using System.Collections.Generic;
namespace NBC
{
public abstract class TaskCollection : NTask, ITaskCollection
{
protected readonly List<ITask> RawList;
protected readonly List<ITask> FinishList;
protected readonly List<ITask> CurRunTask;
public TaskCollection(string taskInfo = "")
{
RawList = new List<ITask>();
FinishList = new List<ITask>();
CurRunTask = new List<ITask>();
TaskInfo = taskInfo;
Status = NTaskStatus.None;
}
public List<ITask> CurrentTask => CurRunTask;
public virtual int Count => RawList.Count + FinishList.Count;
/// <summary>
/// 任务失败中断任务链
/// </summary>
public virtual bool FailBreak
{
get;
set;
}
public override float Progress
{
get
{
if (Status == NTaskStatus.Success) return 1;
if (Status == NTaskStatus.None) return 0;
var finishCount = FinishList.Count;
for (var index = 0; index < CurRunTask.Count; index++)
{
var element = CurRunTask[index];
finishCount += (int)element.Progress;
}
return finishCount * 1f / RawList.Count;
}
}
protected override NTaskStatus OnProcess()
{
return this.RunTasksAndCheckIfDone();
}
public ITaskCollection AddTask(ITask task)
{
RawList.Add(task);
return this;
}
public override void Reset()
{
FinishList.Clear();
CurrentTask.Clear();
Status = NTaskStatus.None;
for (int i = 0,len = RawList.Count; i < len; i++)
{
RawList[i].Reset();
}
}
public override void Stop()
{
FinishList.Clear();
Status = NTaskStatus.None;
for (var i = 0; i < CurRunTask.Count; i++)
{
var task = CurrentTask[i];
task.Stop();
}
}
public virtual void Clear()
{
FinishList.Clear();
RawList.Clear();
Status = NTaskStatus.None;
}
protected abstract NTaskStatus RunTasksAndCheckIfDone();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e84dd447d4e477a478c1cefaf7a14bc3
timeCreated: 1656996883

View File

@@ -0,0 +1,85 @@
using UnityEngine;
namespace NBC
{
public class TimelineTaskCollection : TaskCollection
{
private float _startTime = -1;
protected override NTaskStatus RunTasksAndCheckIfDone()
{
if (_startTime < 0) _startTime = Time.time;
var st = NTaskStatus.Running;
if (RawList.Count > 0)
{
for (var index = 0; index < RawList.Count; index++)
{
var raw = RawList[index];
if (raw == null) continue;
var t = raw["time"];
if (t != null)
{
float time = 0;
if (t is int i)
{
time = i;
}
else if (t is float f)
{
time = f;
}
else if (t is string s)
{
float.TryParse(s, out time);
}
if (Time.time >= (_startTime + time))
{
CurrentTask.Add(RawList[index]);
RawList.RemoveAt(index);
index--;
}
}
}
}
else if (RawList.Count <= 0 && CurrentTask.Count <= 0)
{
st = NTaskStatus.Success;
}
for (var index = 0; index < CurrentTask.Count; index++)
{
var element = CurrentTask[index];
var childSt = element.Process();
if (childSt >= NTaskStatus.Success)
{
CurrentTask.RemoveAt(index);
index--;
FinishList.Add(element);
}
}
return st;
}
public override void Reset()
{
base.Reset();
_startTime = -1;
}
public override void Stop()
{
base.Stop();
_startTime = -1;
}
public override void Clear()
{
base.Clear();
_startTime = -1;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2532701b307e7d64386ae6a0ccedbf3c
timeCreated: 1657434862

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ea8861aa2e7ea884ea4ee74daeda8caa
timeCreated: 1657007208

View File

@@ -0,0 +1,32 @@
using System;
using UnityEngine;
namespace NBC.Extensions
{
public static partial class TaskChainExtension
{
public static SequenceTaskCollection Sequence<T>(this T selfbehaviour) where T : MonoBehaviour
{
var retNodeChain = new SequenceTaskCollection();
return retNodeChain;
}
public static ParallelTaskCollection Parallel<T>(this T selfbehaviour) where T : MonoBehaviour
{
var retNodeChain = new ParallelTaskCollection();
return retNodeChain;
}
// public static TimelineList Timeline<T>(this T selfbehaviour) where T : MonoBehaviour
// {
// var retNodeChain = new TimelineList();
// return retNodeChain;
// }
// public static ITaskCollection OnComplete(this ITaskCollection selfChain, Action<bool> callback)
// {
// selfChain.OnComplete(callback);
// return selfChain;
// }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bb9626fffe2a12242999e5c295218da1
timeCreated: 1657007222

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3fdfec8acff76af4daef6cf6c55c78f0
timeCreated: 1656996246

View File

@@ -0,0 +1,10 @@
namespace NBC
{
/// <summary>
/// 进度
/// </summary>
public interface IProcess
{
NTaskStatus Process();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a5556e4b457d51d49bf2d9ed0e024899
timeCreated: 1656996282

View File

@@ -0,0 +1,49 @@
namespace NBC
{
public interface IRunner
{
/// <summary>
/// 是否暂停
/// </summary>
bool IsPaused { get; set; }
/// <summary>
/// 是否已经终止了
/// </summary>
bool IsKilled { get; }
/// <summary>
/// 当前运行的任务数量
/// </summary>
int RunningTaskNum { get; }
/// <summary>
/// 准备执行的任务数量
/// </summary>
int NeedRunTaskNum { get; }
/// <summary>
/// 执行一个任务
/// </summary>
/// <param name="task">任务对象</param>
void Run(ITask task);
void Process();
/// <summary>
/// 停止任务
/// </summary>
/// <param name="task">任务对象</param>
void StopTask(ITask task);
/// <summary>
/// 停止所有任务
/// </summary>
void StopAllTask();
/// <summary>
/// 终止任务
/// </summary>
void ShutDown();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ed95fa20b281e8640a154c48d1780c70
timeCreated: 1656996361

View File

@@ -0,0 +1,77 @@
using System;
using System.Collections;
namespace NBC
{
public interface ITask : IProcess, IEnumerator
{
NTaskStatus Status { get; }
/// <summary>
/// 当前任务的信息
/// </summary>
string Info { get; }
/// <summary>
/// 错误信息
/// </summary>
string ErrorMsg { get; }
/// <summary>
/// 当前任务的进度
/// </summary>
float Progress { get; }
/// <summary>
/// 任务正在执行
/// </summary>
bool IsRunning { get; }
/// <summary>
/// 任务是否执行完成
/// </summary>
bool IsDone { get; }
/// <summary>
/// 停止任务
/// </summary>
void Stop();
/// <summary>
/// 任务开始回调
/// </summary>
/// <param name="callback"></param>
/// <param name="cover"></param>
/// <returns></returns>
ITask OnStarted(Action<ITask> callback, bool cover = false);
/// <summary>
/// 任务执行回调
/// </summary>
/// <param name="callback"></param>
/// <param name="cover"></param>
/// <returns></returns>
ITask OnUpdated(Action<ITask> callback, bool cover = false);
/// <summary>
/// 任务完成回调
/// </summary>
/// <param name="callback"></param>
/// <param name="cover"></param>
/// <returns></returns>
ITask OnCompleted(Action<ITask> callback, bool cover = false);
/// <summary>
/// 运行任务
/// </summary>
/// <param name="runner">任务运行器</param>
void Run(IRunner runner);
/// <summary>
/// 任务参数
/// </summary>
/// <param name="argsName"></param>
object this[string argsName] { get; set; }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f025551734ce37a479414f55be095790
timeCreated: 1656996448

View File

@@ -0,0 +1,24 @@
using System.Collections.Generic;
namespace NBC
{
public interface ITaskCollection : ITask
{
/// <summary>
/// 当前运行的任务堆栈
/// </summary>
List<ITask> CurrentTask { get; }
/// <summary>
/// 添加一个任务
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
ITaskCollection AddTask(ITask task);
/// <summary>
/// 清理任务列表
/// </summary>
void Clear();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2ae6582e140d07049accaf0b5db4b2f4
timeCreated: 1656996765

View File

@@ -0,0 +1,7 @@
namespace NBC
{
public interface ITaskRun
{
void Run(IRunner runner);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a3b784189f1caf1488eb81fb903ff63e
timeCreated: 1656996836

View File

@@ -0,0 +1,224 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace NBC
{
public abstract class NTask : ITask
{
protected float _progress = 0;
protected string _errorMsg;
protected string TaskInfo;
protected readonly Dictionary<string, object> _argsDic = new Dictionary<string, object>();
public virtual string Info
{
get => TaskInfo;
set => TaskInfo = value;
}
public NTaskStatus Status { get; protected set; } = NTaskStatus.None;
public virtual string ErrorMsg => _errorMsg;
public virtual float Progress => _progress;
public virtual bool IsRunning => Status == NTaskStatus.Running;
public virtual bool IsDone => Status == NTaskStatus.Success || Status == NTaskStatus.Fail;
public object this[string argsName]
{
get
{
if (_argsDic.TryGetValue(argsName, out object args))
{
return args;
}
return null;
}
set => _argsDic[argsName] = value;
}
public virtual void Stop()
{
Status = NTaskStatus.None;
}
public virtual void Run(IRunner runner)
{
Reset();
runner?.Run(this);
}
public NTaskStatus Process()
{
if (Status == NTaskStatus.None)
{
Start();
}
Status = OnProcess();
CallUpdateListener();
if (Status == NTaskStatus.Success)
{
_progress = 1;
CallCompleteListener(Status);
}
else if (Status == NTaskStatus.Fail)
{
_progress = 1;
CallCompleteListener(Status);
}
return Status;
}
protected virtual void OnStart()
{
}
protected virtual void OnComplete()
{
}
protected virtual NTaskStatus OnProcess()
{
return this.Status;
}
protected void Finish()
{
_progress = 1;
Status = NTaskStatus.Success;
}
protected void Fail(string message)
{
_progress = 1;
Status = NTaskStatus.Fail;
_errorMsg = message;
}
private void Start()
{
Reset();
Status = NTaskStatus.Running;
_progress = 0;
OnStart();
CallStartListener();
}
#region
protected event Action<ITask> OnStartListener;
protected event Action<ITask> OnCompleteListener;
protected event Action<ITask> OnUpdateListener;
public ITask OnStarted(Action<ITask> callback, bool cover = false)
{
if (cover)
{
OnStartListener = callback;
}
else
{
OnStartListener += callback;
}
return this;
}
public ITask OnUpdated(Action<ITask> callback, bool cover = false)
{
if (cover)
{
OnUpdateListener = callback;
}
else
{
OnUpdateListener += callback;
}
return this;
}
public ITask OnCompleted(Action<ITask> callback, bool cover = false)
{
if (cover)
{
OnCompleteListener = callback;
}
else
{
OnCompleteListener += callback;
}
return this;
}
protected void CallStartListener()
{
OnStartListener?.Invoke(this);
}
protected void CallCompleteListener(NTaskStatus taskStatus)
{
OnComplete();
OnCompleteListener?.Invoke(this);
_taskCompletionSource?.TrySetResult(null);
}
protected void CallUpdateListener()
{
OnUpdateListener?.Invoke(this);
}
#endregion
#region
private TaskCompletionSource<object> _taskCompletionSource;
/// <summary>
/// 异步操作任务
/// </summary>
public Task Task
{
get
{
if (_taskCompletionSource == null)
{
_taskCompletionSource = new TaskCompletionSource<object>();
if (IsDone)
_taskCompletionSource.SetResult(null);
}
return _taskCompletionSource.Task;
}
}
#endregion
#region IEnumerator
bool IEnumerator.MoveNext()
{
return !IsDone;
}
public virtual void Reset()
{
Status = NTaskStatus.None;
}
object IEnumerator.Current => null;
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8035be535392c22489664156d78df1ef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
namespace NBC
{
public enum NTaskStatus
{
/// <summary>
/// 任务还未执行
/// </summary>
None = 0,
/// <summary>
/// 任务运行
/// </summary>
Running,
/// <summary>
/// 任务执行成功
/// </summary>
Success,
/// <summary>
/// 任务执行失败
/// </summary>
Fail
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8d69db579faa30f4db7ae1b2c27cb10f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 63bed6143f265e3449b00af0ef891a5a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
namespace NBC
{
/// <summary>
/// 操作信息类
/// </summary>
public class FlushingOperation
{
/// <summary>
/// 是否暂停
/// </summary>
public bool Paused;
/// <summary>
/// 是否被终结
/// </summary>
public bool Kill;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dc64e5709b547264b90f53b13ee8aaa9
timeCreated: 1657004343

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
namespace NBC
{
public class Runner : IRunner
{
public bool IsPaused
{
get => FlushingOperation.Paused;
set => FlushingOperation.Paused = value;
}
public bool IsKilled => FlushingOperation.Kill;
public int RunningTaskNum => Coroutines.Count;
public int NeedRunTaskNum => ReadyTask.Count;
/// <summary>
/// 当前运行的任务
/// </summary>
protected readonly List<ITask> Coroutines = new List<ITask>();
/// <summary>
/// 准备要运行的任务
/// </summary>
protected readonly Queue<ITask> ReadyTask = new Queue<ITask>();
/// <summary>
/// 当前操作的信息
/// </summary>
protected readonly FlushingOperation FlushingOperation = new FlushingOperation();
public virtual void Run(ITask task)
{
ReadyTask.Enqueue(task);
}
public virtual void Process()
{
var count = ReadyTask.Count;
for (var i = 0; i < count; i++)
{
var task = ReadyTask.Dequeue();
Coroutines.Add(task);
}
if (Coroutines.Count < 1) return;
var index = 0;
bool mustExit;
do
{
var childTask = Coroutines[index];
var st = childTask.Process();
if (st >= NTaskStatus.Success)
{
Coroutines.Remove(childTask);
}
else
{
index++;
}
mustExit = Coroutines.Count == 0 || index >= Coroutines.Count;
} while (!mustExit);
}
public virtual void StopTask(ITask task)
{
var index = Coroutines.IndexOf(task);
if (index != -1)
{
var t = Coroutines[index];
t.Stop();
Coroutines.RemoveAt(index);
}
}
public virtual void StopAllTask()
{
ReadyTask.Clear();
for (int i = 0; i < Coroutines.Count; i++)
{
Coroutines[i].Stop();
}
Coroutines.Clear();
}
public virtual void ShutDown()
{
IsPaused = false;
FlushingOperation.Kill = true;
StopAllTask();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3bd5593733a84d74f83248aa0170da03
timeCreated: 1657005250

View File

@@ -0,0 +1,78 @@
using System.Collections.Generic;
namespace NBC
{
public class RunnerProcess : IProcess
{
/// <summary>
/// 当前运行的任务
/// </summary>
protected readonly List<ITask> Coroutines;
/// <summary>
/// 准备要运行的任务
/// </summary>
protected readonly Queue<ITask> ReadyTask;
/// <summary>
/// 当前操作的信息
/// </summary>
protected readonly FlushingOperation FlushingOperation;
/// <summary>
/// 进程名称
/// </summary>
protected string Name;
public RunnerProcess(string name, List<ITask> coroutines, Queue<ITask> readyTask, FlushingOperation op)
{
this.Name = name;
Coroutines = coroutines;
ReadyTask = readyTask;
FlushingOperation = op;
}
public NTaskStatus Process()
{
var flag = false;
if (this.FlushingOperation.Kill) flag = true;
else
{
for (var index = 0; index < this.ReadyTask.Count; index++)
{
// var task = ReadyTask[0];
var task = ReadyTask.Dequeue();
this.Coroutines.Add(task);
// ReadyTask.RemoveAt(0);
}
if (this.Coroutines.Count == 0 || this.FlushingOperation.Paused)
{
flag = false;
}
else
{
var index = 0;
var mustExit = false;
do
{
var childTask = this.Coroutines[index];
var st = childTask.Process();
if (st >= NTaskStatus.Success)
{
this.Coroutines.RemoveAt(index); //.splice(index, 1);
}
else
{
index++;
}
mustExit = this.Coroutines.Count == 0 || index >= this.Coroutines.Count;
} while (!mustExit);
}
}
return flag ? NTaskStatus.Success : NTaskStatus.Running;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3647c1233c788034e91db438d16c23a5
timeCreated: 1657004572

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 876bd2f6c6f095c4c9532c5812ea7545
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

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,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()
{
App.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