首次提交
This commit is contained in:
3
Assets/Scripts/NBC/Core/Runtime.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8922eeb5251f469eb8b055035568bef6
|
||||
timeCreated: 1715241124
|
||||
8
Assets/Scripts/NBC/Core/Runtime/Attributes.meta
Normal file
8
Assets/Scripts/NBC/Core/Runtime/Attributes.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba24caabe0c56054fba853ec098610d9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class BaseAttribute: Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32bc35c38967479d81a79bd1354d38e8
|
||||
timeCreated: 1733995116
|
||||
8
Assets/Scripts/NBC/Core/Runtime/Event.meta
Normal file
8
Assets/Scripts/NBC/Core/Runtime/Event.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce41c13bdce12484b82277f6d4596bac
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
128
Assets/Scripts/NBC/Core/Runtime/Event/EventArgs.cs
Normal file
128
Assets/Scripts/NBC/Core/Runtime/Event/EventArgs.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/NBC/Core/Runtime/Event/EventArgs.cs.meta
Normal file
11
Assets/Scripts/NBC/Core/Runtime/Event/EventArgs.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 371d9cba4de694e47a6a6f28b7f0c956
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
217
Assets/Scripts/NBC/Core/Runtime/Event/EventDispatcher.cs
Normal file
217
Assets/Scripts/NBC/Core/Runtime/Event/EventDispatcher.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d03163cd522f1f44a06979858fa2ee5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
71
Assets/Scripts/NBC/Core/Runtime/Event/IEventDispatcher.cs
Normal file
71
Assets/Scripts/NBC/Core/Runtime/Event/IEventDispatcher.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee3ce226192bcd648bc228e5e92b6ee2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/NBC/Core/Runtime/Exception.meta
Normal file
8
Assets/Scripts/NBC/Core/Runtime/Exception.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f301d2312bd67b4f860f00c46cb3bae
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
38
Assets/Scripts/NBC/Core/Runtime/Exception/WhootException.cs
Normal file
38
Assets/Scripts/NBC/Core/Runtime/Exception/WhootException.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏框架异常类
|
||||
/// </summary>
|
||||
public class WhootException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化游戏框架异常类的新实例
|
||||
/// </summary>
|
||||
public WhootException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用指定错误消息初始化游戏框架异常类的新实例
|
||||
/// </summary>
|
||||
/// <param name="message">描述错误的消息</param>
|
||||
public WhootException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用指定错误消息和对作为此异常原因的内部异常的引用来初始化游戏框架异常类的新实例
|
||||
/// </summary>
|
||||
/// <param name="message">解释异常原因的错误消息</param>
|
||||
/// <param name="innerException">导致当前异常的异常。如果 innerException 参数不为空引用,则在处理内部异常的 catch 块中引发当前异常。</param>
|
||||
public WhootException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae413443f2a549eeb99383d1206cdae2
|
||||
timeCreated: 1603355057
|
||||
8
Assets/Scripts/NBC/Core/Runtime/Extensions.meta
Normal file
8
Assets/Scripts/NBC/Core/Runtime/Extensions.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f8f296ce61749a41b5f440108b1dbb9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
285
Assets/Scripts/NBC/Core/Runtime/Extensions/CSharpExtension.cs
Normal file
285
Assets/Scripts/NBC/Core/Runtime/Extensions/CSharpExtension.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
/// <summary>
|
||||
/// 一些基础类型的扩展
|
||||
/// </summary>
|
||||
public static class BasicValueExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否相等
|
||||
///
|
||||
/// 示例:
|
||||
/// <code>
|
||||
/// if (this.Is(player))
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <param name="selfObj"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Is(this object selfObj, object value)
|
||||
{
|
||||
return selfObj == value;
|
||||
}
|
||||
|
||||
public static bool Is<T>(this T selfObj, Func<T, bool> condition)
|
||||
{
|
||||
return condition(selfObj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表达式成立 则执行 Action
|
||||
///
|
||||
/// 示例:
|
||||
/// <code>
|
||||
/// (1 == 1).Do(()=>XLog.Log("1 == 1");
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <param name="selfCondition"></param>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Do(this bool selfCondition, Action action)
|
||||
{
|
||||
if (selfCondition)
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
return selfCondition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 不管表达成不成立 都执行 Action,并把结果返回
|
||||
///
|
||||
/// 示例:
|
||||
/// <code>
|
||||
/// (1 == 1).Do((result)=>XLog.Log("1 == 1:" + result);
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <param name="selfCondition"></param>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Do(this bool selfCondition, Action<bool> action)
|
||||
{
|
||||
action(selfCondition);
|
||||
|
||||
return selfCondition;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通用的扩展,类的扩展
|
||||
/// </summary>
|
||||
public static class ClassExtention
|
||||
{
|
||||
/// <summary>
|
||||
/// 功能:判断是否为空
|
||||
///
|
||||
/// 示例:
|
||||
/// <code>
|
||||
/// var simpleObject = new object();
|
||||
///
|
||||
/// if (simpleObject.IsNull()) // 等价于 simpleObject == null
|
||||
/// {
|
||||
/// // do sth
|
||||
/// }
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <param name="selfObj">判断对象(this)</param>
|
||||
/// <typeparam name="T">对象的类型(可不填)</typeparam>
|
||||
/// <returns>是否为空</returns>
|
||||
public static bool IsNull<T>(this T selfObj) where T : class
|
||||
{
|
||||
return null == selfObj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 功能:判断不是为空
|
||||
/// 示例:
|
||||
/// <code>
|
||||
/// var simpleObject = new object();
|
||||
///
|
||||
/// if (simpleObject.IsNotNull()) // 等价于 simpleObject != null
|
||||
/// {
|
||||
/// // do sth
|
||||
/// }
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <param name="selfObj">判断对象(this)</param>
|
||||
/// <typeparam name="T">对象的类型(可不填)</typeparam>
|
||||
/// <returns>是否不为空</returns>
|
||||
public static bool IsNotNull<T>(this T selfObj) where T : class
|
||||
{
|
||||
return null != selfObj;
|
||||
}
|
||||
|
||||
public static void DoIfNotNull<T>(this T selfObj, Action<T> action) where T : class
|
||||
{
|
||||
if (selfObj != null)
|
||||
{
|
||||
action(selfObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 泛型工具
|
||||
///
|
||||
/// 实例:
|
||||
/// <code>
|
||||
/// 示例:
|
||||
/// var typeName = GenericExtention.GetTypeName<string>();
|
||||
/// typeName.LogInfo(); // string
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public static class GenericUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取泛型名字
|
||||
/// <code>
|
||||
/// var typeName = GenericExtention.GetTypeName<string>();
|
||||
/// typeName.LogInfo(); // string
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static string GetTypeName<T>()
|
||||
{
|
||||
return typeof(T).ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对 System.IO 的一些扩展
|
||||
/// </summary>
|
||||
public static class IOExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 检测路径是否存在,如果不存在则创建
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
public static string CreateDirIfNotExists4FilePath(this string path)
|
||||
{
|
||||
var direct = Path.GetDirectoryName(path);
|
||||
|
||||
if (!Directory.Exists(direct))
|
||||
{
|
||||
Directory.CreateDirectory(direct);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建新的文件夹,如果存在则不创建
|
||||
/// <code>
|
||||
/// var testDir = "Assets/TestFolder";
|
||||
/// testDir.CreateDirIfNotExists();
|
||||
/// // 结果为,在 Assets 目录下创建 TestFolder
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public static string CreateDirIfNotExists(this string dirFullPath)
|
||||
{
|
||||
if (!Directory.Exists(dirFullPath))
|
||||
{
|
||||
Directory.CreateDirectory(dirFullPath);
|
||||
}
|
||||
|
||||
return dirFullPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除文件夹,如果存在
|
||||
/// <code>
|
||||
/// var testDir = "Assets/TestFolder";
|
||||
/// testDir.DeleteDirIfExists();
|
||||
/// // 结果为,在 Assets 目录下删除了 TestFolder
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public static void DeleteDirIfExists(this string dirFullPath)
|
||||
{
|
||||
if (Directory.Exists(dirFullPath))
|
||||
{
|
||||
Directory.Delete(dirFullPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空 Dir(保留目录),如果存在。
|
||||
/// <code>
|
||||
/// var testDir = "Assets/TestFolder";
|
||||
/// testDir.EmptyDirIfExists();
|
||||
/// // 结果为,清空了 TestFolder 里的内容
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public static void EmptyDirIfExists(this string dirFullPath)
|
||||
{
|
||||
if (Directory.Exists(dirFullPath))
|
||||
{
|
||||
Directory.Delete(dirFullPath, true);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(dirFullPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除文件 如果存在
|
||||
/// <code>
|
||||
/// // 示例
|
||||
/// var filePath = "Assets/Test.txt";
|
||||
/// File.Create("Assets/Test);
|
||||
/// filePath.DeleteFileIfExists();
|
||||
/// // 结果为,删除了 Test.txt
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath"></param>
|
||||
/// <returns> 是否进行了删除操作 </returns>
|
||||
public static bool DeleteFileIfExists(this string fileFullPath)
|
||||
{
|
||||
if (File.Exists(fileFullPath))
|
||||
{
|
||||
File.Delete(fileFullPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并路径
|
||||
/// <code>
|
||||
/// // 示例:
|
||||
/// Application.dataPath.CombinePath("Resources").LogInfo(); // /projectPath/Assets/Resources
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <param name="selfPath"></param>
|
||||
/// <param name="toCombinePath"></param>
|
||||
/// <returns> 合并后的路径 </returns>
|
||||
public static string CombinePath(this string selfPath, string toCombinePath)
|
||||
{
|
||||
return Path.Combine(selfPath, toCombinePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 类型扩展
|
||||
/// </summary>
|
||||
public static class TypeEx
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取默认值
|
||||
/// </summary>
|
||||
/// <param name="targetType"></param>
|
||||
/// <returns></returns>
|
||||
public static object DefaultForType(this Type targetType)
|
||||
{
|
||||
return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac644ae7280c4a65ae705cb0e4dd782d
|
||||
timeCreated: 1680837299
|
||||
8
Assets/Scripts/NBC/Core/Runtime/Log.meta
Normal file
8
Assets/Scripts/NBC/Core/Runtime/Log.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b809a9bd4bfdcb742b23e649be6b487a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
47
Assets/Scripts/NBC/Core/Runtime/Log/Log.cs
Normal file
47
Assets/Scripts/NBC/Core/Runtime/Log/Log.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public static class Log
|
||||
{
|
||||
public static bool Open = false;
|
||||
|
||||
static Log()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
Open = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// [Conditional("UNITY_EDITOR"), Conditional("LOG")]
|
||||
public static void Info(object message)
|
||||
{
|
||||
UnityEngine.Debug.Log(message);
|
||||
}
|
||||
|
||||
// [Conditional("UNITY_EDITOR"), Conditional("LOG")]
|
||||
public static void Warning(object message)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(message);
|
||||
}
|
||||
|
||||
// [Conditional("UNITY_EDITOR"), Conditional("LOG"), Conditional("ERROR")]
|
||||
public static void Error(object message)
|
||||
{
|
||||
UnityEngine.Debug.LogError(message);
|
||||
}
|
||||
|
||||
// [Conditional("UNITY_EDITOR"), Conditional("LOG"), Conditional("ERROR")]
|
||||
public static void Exception(Exception exception)
|
||||
{
|
||||
UnityEngine.Debug.LogException(exception);
|
||||
}
|
||||
|
||||
// [Conditional("UNITY_EDITOR"), Conditional("LOG"), Conditional("ERROR")]
|
||||
public static void Exception(Exception exception, UnityEngine.Object context)
|
||||
{
|
||||
UnityEngine.Debug.LogException(exception, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Log/Log.cs.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Log/Log.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03ea3505028b46fb8356fcd77001236c
|
||||
timeCreated: 1680834940
|
||||
3
Assets/Scripts/NBC/Core/Runtime/NBC.Core.asmdef
Normal file
3
Assets/Scripts/NBC/Core/Runtime/NBC.Core.asmdef
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "NBC.Core"
|
||||
}
|
||||
7
Assets/Scripts/NBC/Core/Runtime/NBC.Core.asmdef.meta
Normal file
7
Assets/Scripts/NBC/Core/Runtime/NBC.Core.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3c9c3fa0cbae6e438ac062aa5d78b76
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/NBC/Core/Runtime/Services.meta
Normal file
8
Assets/Scripts/NBC/Core/Runtime/Services.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 189f83d60804d8f4585e3f9efb5cc163
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
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
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Structures.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Structures.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5a966ae39a544c9b345cf9f8e178615
|
||||
timeCreated: 1733995883
|
||||
144
Assets/Scripts/NBC/Core/Runtime/Structures/DoubleMap.cs
Normal file
144
Assets/Scripts/NBC/Core/Runtime/Structures/DoubleMap.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public class DoubleMap<K, V>
|
||||
{
|
||||
private readonly Dictionary<K, V> kv = new();
|
||||
private readonly Dictionary<V, K> vk = new();
|
||||
|
||||
public DoubleMap()
|
||||
{
|
||||
}
|
||||
|
||||
public DoubleMap(int capacity)
|
||||
{
|
||||
kv = new Dictionary<K, V>(capacity);
|
||||
vk = new Dictionary<V, K>(capacity);
|
||||
}
|
||||
|
||||
public void ForEach(Action<K, V> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Dictionary<K, V>.KeyCollection keys = kv.Keys;
|
||||
foreach (K key in keys)
|
||||
{
|
||||
action(key, kv[key]);
|
||||
}
|
||||
}
|
||||
|
||||
public List<K> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<K>(kv.Keys);
|
||||
}
|
||||
}
|
||||
|
||||
public List<V> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<V>(vk.Keys);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(K key, V value)
|
||||
{
|
||||
if (key == null || value == null || kv.ContainsKey(key) || vk.ContainsKey(value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
kv.Add(key, value);
|
||||
vk.Add(value, key);
|
||||
}
|
||||
|
||||
public V GetValueByKey(K key)
|
||||
{
|
||||
if (key != null && kv.ContainsKey(key))
|
||||
{
|
||||
return kv[key];
|
||||
}
|
||||
return default(V);
|
||||
}
|
||||
|
||||
public K GetKeyByValue(V value)
|
||||
{
|
||||
if (value != null && vk.ContainsKey(value))
|
||||
{
|
||||
return vk[value];
|
||||
}
|
||||
return default(K);
|
||||
}
|
||||
|
||||
public void RemoveByKey(K key)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
V value;
|
||||
if (!kv.TryGetValue(key, out value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
kv.Remove(key);
|
||||
vk.Remove(value);
|
||||
}
|
||||
|
||||
public void RemoveByValue(V value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
K key;
|
||||
if (!vk.TryGetValue(value, out key))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
kv.Remove(key);
|
||||
vk.Remove(value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
kv.Clear();
|
||||
vk.Clear();
|
||||
}
|
||||
|
||||
public bool ContainsKey(K key)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return kv.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool ContainsValue(V value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return vk.ContainsKey(value);
|
||||
}
|
||||
|
||||
public bool Contains(K key, V value)
|
||||
{
|
||||
if (key == null || value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return kv.ContainsKey(key) && vk.ContainsKey(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 512992ac5b0b472fb720cfbd3a0d768a
|
||||
timeCreated: 1733994332
|
||||
@@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public class UnOrderMultiMapSet<T, K> : Dictionary<T, HashSet<K>>
|
||||
{
|
||||
// 重用HashSet
|
||||
public new HashSet<K> this[T t]
|
||||
{
|
||||
get
|
||||
{
|
||||
HashSet<K> set;
|
||||
if (!this.TryGetValue(t, out set))
|
||||
{
|
||||
set = new HashSet<K>();
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<T, HashSet<K>> GetDictionary()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Add(T t, K k)
|
||||
{
|
||||
HashSet<K> set;
|
||||
this.TryGetValue(t, out set);
|
||||
if (set == null)
|
||||
{
|
||||
set = new HashSet<K>();
|
||||
base[t] = set;
|
||||
}
|
||||
|
||||
set.Add(k);
|
||||
}
|
||||
|
||||
public bool Remove(T t, K k)
|
||||
{
|
||||
HashSet<K> set;
|
||||
this.TryGetValue(t, out set);
|
||||
if (set == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!set.Remove(k))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (set.Count == 0)
|
||||
{
|
||||
this.Remove(t);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Contains(T t, K k)
|
||||
{
|
||||
HashSet<K> set;
|
||||
this.TryGetValue(t, out set);
|
||||
if (set == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return set.Contains(k);
|
||||
}
|
||||
|
||||
public new int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
foreach (KeyValuePair<T, HashSet<K>> kv in this)
|
||||
{
|
||||
count += kv.Value.Count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7f20db4c53f4bd1959c0bfcb4e1c8db
|
||||
timeCreated: 1733995067
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Task.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Task.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 603802d919d844e4a925c31a134040cb
|
||||
timeCreated: 1715240502
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Task/Collection.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Task/Collection.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d069cf2e375b8a74ebab6f3df1f74a91
|
||||
timeCreated: 1656996254
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33f78136d6a7de14688a6d3ed6903557
|
||||
timeCreated: 1657002644
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7440203326fc09a479080181660af525
|
||||
timeCreated: 1657003965
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e84dd447d4e477a478c1cefaf7a14bc3
|
||||
timeCreated: 1656996883
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2532701b307e7d64386ae6a0ccedbf3c
|
||||
timeCreated: 1657434862
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Task/Extensions.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Task/Extensions.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea8861aa2e7ea884ea4ee74daeda8caa
|
||||
timeCreated: 1657007208
|
||||
@@ -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;
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb9626fffe2a12242999e5c295218da1
|
||||
timeCreated: 1657007222
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Task/Interface.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Task/Interface.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3fdfec8acff76af4daef6cf6c55c78f0
|
||||
timeCreated: 1656996246
|
||||
10
Assets/Scripts/NBC/Core/Runtime/Task/Interface/IProcess.cs
Normal file
10
Assets/Scripts/NBC/Core/Runtime/Task/Interface/IProcess.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace NBC
|
||||
{
|
||||
/// <summary>
|
||||
/// 进度
|
||||
/// </summary>
|
||||
public interface IProcess
|
||||
{
|
||||
NTaskStatus Process();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5556e4b457d51d49bf2d9ed0e024899
|
||||
timeCreated: 1656996282
|
||||
49
Assets/Scripts/NBC/Core/Runtime/Task/Interface/IRunner.cs
Normal file
49
Assets/Scripts/NBC/Core/Runtime/Task/Interface/IRunner.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed95fa20b281e8640a154c48d1780c70
|
||||
timeCreated: 1656996361
|
||||
77
Assets/Scripts/NBC/Core/Runtime/Task/Interface/ITask.cs
Normal file
77
Assets/Scripts/NBC/Core/Runtime/Task/Interface/ITask.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f025551734ce37a479414f55be095790
|
||||
timeCreated: 1656996448
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ae6582e140d07049accaf0b5db4b2f4
|
||||
timeCreated: 1656996765
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace NBC
|
||||
{
|
||||
public interface ITaskRun
|
||||
{
|
||||
void Run(IRunner runner);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3b784189f1caf1488eb81fb903ff63e
|
||||
timeCreated: 1656996836
|
||||
224
Assets/Scripts/NBC/Core/Runtime/Task/NTask.cs
Normal file
224
Assets/Scripts/NBC/Core/Runtime/Task/NTask.cs
Normal 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
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/NBC/Core/Runtime/Task/NTask.cs.meta
Normal file
11
Assets/Scripts/NBC/Core/Runtime/Task/NTask.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8035be535392c22489664156d78df1ef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
25
Assets/Scripts/NBC/Core/Runtime/Task/NTaskStatus.cs
Normal file
25
Assets/Scripts/NBC/Core/Runtime/Task/NTaskStatus.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace NBC
|
||||
{
|
||||
public enum NTaskStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务还未执行
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 任务运行
|
||||
/// </summary>
|
||||
Running,
|
||||
|
||||
/// <summary>
|
||||
/// 任务执行成功
|
||||
/// </summary>
|
||||
Success,
|
||||
|
||||
/// <summary>
|
||||
/// 任务执行失败
|
||||
/// </summary>
|
||||
Fail
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/NBC/Core/Runtime/Task/NTaskStatus.cs.meta
Normal file
11
Assets/Scripts/NBC/Core/Runtime/Task/NTaskStatus.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d69db579faa30f4db7ae1b2c27cb10f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/NBC/Core/Runtime/Task/Runner.meta
Normal file
8
Assets/Scripts/NBC/Core/Runtime/Task/Runner.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63bed6143f265e3449b00af0ef891a5a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace NBC
|
||||
{
|
||||
/// <summary>
|
||||
/// 操作信息类
|
||||
/// </summary>
|
||||
public class FlushingOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否暂停
|
||||
/// </summary>
|
||||
public bool Paused;
|
||||
|
||||
/// <summary>
|
||||
/// 是否被终结
|
||||
/// </summary>
|
||||
public bool Kill;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc64e5709b547264b90f53b13ee8aaa9
|
||||
timeCreated: 1657004343
|
||||
97
Assets/Scripts/NBC/Core/Runtime/Task/Runner/Runner.cs
Normal file
97
Assets/Scripts/NBC/Core/Runtime/Task/Runner/Runner.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3bd5593733a84d74f83248aa0170da03
|
||||
timeCreated: 1657005250
|
||||
78
Assets/Scripts/NBC/Core/Runtime/Task/Runner/RunnerProcess.cs
Normal file
78
Assets/Scripts/NBC/Core/Runtime/Task/Runner/RunnerProcess.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3647c1233c788034e91db438d16c23a5
|
||||
timeCreated: 1657004572
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Utils.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Utils.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0af3ab5ef5304e1fa7551bdcbbc99929
|
||||
timeCreated: 1716186772
|
||||
6
Assets/Scripts/NBC/Core/Runtime/Utils/Flag.cs
Normal file
6
Assets/Scripts/NBC/Core/Runtime/Utils/Flag.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace NBC
|
||||
{
|
||||
public class Flag
|
||||
{
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Utils/Flag.cs.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Utils/Flag.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57ed4dea58b7413b91b3156bcd12b97a
|
||||
timeCreated: 1716186802
|
||||
408
Assets/Scripts/NBC/Core/Runtime/Utils/IOC.cs
Normal file
408
Assets/Scripts/NBC/Core/Runtime/Utils/IOC.cs
Normal file
@@ -0,0 +1,408 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public class IOCGroup : MonoBehaviour
|
||||
{
|
||||
private IOCContainer _container = new IOCContainer();
|
||||
public IOCContainer Container => _container;
|
||||
}
|
||||
|
||||
public class IOCContainer
|
||||
{
|
||||
private class Item
|
||||
{
|
||||
public object Instance;
|
||||
public MulticastDelegate Function;
|
||||
|
||||
public Item(object instance)
|
||||
{
|
||||
Instance = instance;
|
||||
}
|
||||
|
||||
public Item(MulticastDelegate function)
|
||||
{
|
||||
Function = function;
|
||||
}
|
||||
|
||||
public T Resolve<T>()
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
return (T)Instance;
|
||||
}
|
||||
|
||||
return ((Func<T>)Function)();
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<Type, Dictionary<string, Item>> m_named = new Dictionary<Type, Dictionary<string, Item>>();
|
||||
private Dictionary<Type, Item> m_registered = new Dictionary<Type, Item>();
|
||||
private Dictionary<Type, Item> m_fallbacks = new Dictionary<Type, Item>();
|
||||
|
||||
public bool IsRegistered<T>(string name)
|
||||
{
|
||||
if (!m_named.TryGetValue(typeof(T), out Dictionary<string, Item> nameToItem))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return nameToItem.ContainsKey(name);
|
||||
}
|
||||
|
||||
public void Register<T>(string name, Func<T> func)
|
||||
{
|
||||
if (func == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(func));
|
||||
}
|
||||
|
||||
if (!m_named.TryGetValue(typeof(T), out var nameToItem))
|
||||
{
|
||||
nameToItem = new Dictionary<string, Item>();
|
||||
m_named.Add(typeof(T), nameToItem);
|
||||
}
|
||||
|
||||
if (nameToItem.ContainsKey(name))
|
||||
{
|
||||
Debug.LogWarningFormat("item with name {0} already registered", name);
|
||||
}
|
||||
|
||||
nameToItem[name] = new Item(func);
|
||||
}
|
||||
|
||||
public void Register<T>(string name, T instance)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("func");
|
||||
}
|
||||
|
||||
if (!m_named.TryGetValue(typeof(T), out var nameToItem))
|
||||
{
|
||||
nameToItem = new Dictionary<string, Item>();
|
||||
m_named.Add(typeof(T), nameToItem);
|
||||
}
|
||||
|
||||
if (nameToItem.ContainsKey(name))
|
||||
{
|
||||
Debug.LogWarningFormat("item with name {0} already registered", name);
|
||||
}
|
||||
|
||||
nameToItem[name] = new Item(instance);
|
||||
}
|
||||
|
||||
public bool IsRegistered<T>()
|
||||
{
|
||||
return m_registered.ContainsKey(typeof(T));
|
||||
}
|
||||
|
||||
public void Register<T>(Func<T> func)
|
||||
{
|
||||
if (func == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(func));
|
||||
}
|
||||
|
||||
if (m_registered.ContainsKey(typeof(T)))
|
||||
{
|
||||
Debug.LogWarningFormat("type {0} already registered.", typeof(T).FullName);
|
||||
}
|
||||
|
||||
m_registered[typeof(T)] = new Item(func);
|
||||
}
|
||||
|
||||
public void Register<T>(T instance)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(instance));
|
||||
}
|
||||
|
||||
if (m_registered.ContainsKey(typeof(T)))
|
||||
{
|
||||
Debug.LogWarningFormat("type {0} already registered.", typeof(T).FullName);
|
||||
}
|
||||
|
||||
m_registered[typeof(T)] = new Item(instance);
|
||||
}
|
||||
|
||||
public void Unregister<T>(string name, Func<T> func)
|
||||
{
|
||||
if (m_named.TryGetValue(typeof(T), out var nameToItem))
|
||||
{
|
||||
if (nameToItem.TryGetValue(name, out var item))
|
||||
{
|
||||
if (item.Function != null && item.Function.Equals(func))
|
||||
{
|
||||
nameToItem.Remove(name);
|
||||
if (nameToItem.Count == 0)
|
||||
{
|
||||
m_named.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unregister<T>(string name, T instance)
|
||||
{
|
||||
if (m_named.TryGetValue(typeof(T), out var nameToItem))
|
||||
{
|
||||
if (nameToItem.TryGetValue(name, out var item))
|
||||
{
|
||||
if (ReferenceEquals(item.Instance, instance))
|
||||
{
|
||||
nameToItem.Remove(name);
|
||||
if (nameToItem.Count == 0)
|
||||
{
|
||||
m_named.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unregister<T>(Func<T> func)
|
||||
{
|
||||
if (m_registered.TryGetValue(typeof(T), out var item))
|
||||
{
|
||||
if (item.Function != null && item.Function.Equals(func))
|
||||
{
|
||||
m_registered.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unregister<T>(T instance)
|
||||
{
|
||||
if (m_registered.TryGetValue(typeof(T), out var item))
|
||||
{
|
||||
if (ReferenceEquals(item.Instance, instance))
|
||||
{
|
||||
m_registered.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unregister<T>()
|
||||
{
|
||||
m_registered.Remove(typeof(T));
|
||||
}
|
||||
|
||||
public bool IsFallbackRegistered<T>()
|
||||
{
|
||||
return m_fallbacks.ContainsKey(typeof(T));
|
||||
}
|
||||
|
||||
public void RegisterFallback<T>(Func<T> func)
|
||||
{
|
||||
if (func == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(func));
|
||||
}
|
||||
|
||||
if (m_fallbacks.ContainsKey(typeof(T)))
|
||||
{
|
||||
Debug.LogWarningFormat("fallback for type {0} already registered.", typeof(T).FullName);
|
||||
}
|
||||
|
||||
m_fallbacks[typeof(T)] = new Item(func);
|
||||
}
|
||||
|
||||
public void RegisterFallback<T>(T instance)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(instance));
|
||||
}
|
||||
|
||||
if (m_fallbacks.ContainsKey(typeof(T)))
|
||||
{
|
||||
Debug.LogWarningFormat("type {0} already registered.", typeof(T).FullName);
|
||||
}
|
||||
|
||||
m_fallbacks[typeof(T)] = new Item(instance);
|
||||
}
|
||||
|
||||
public void UnregisterFallback<T>(Func<T> func)
|
||||
{
|
||||
if (m_fallbacks.TryGetValue(typeof(T), out var item))
|
||||
{
|
||||
if (item.Function != null && item.Function.Equals(func))
|
||||
{
|
||||
m_fallbacks.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterFallback<T>(T instance)
|
||||
{
|
||||
if (m_fallbacks.TryGetValue(typeof(T), out var item))
|
||||
{
|
||||
if (ReferenceEquals(item.Instance, instance))
|
||||
{
|
||||
m_fallbacks.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterFallback<T>()
|
||||
{
|
||||
m_fallbacks.Remove(typeof(T));
|
||||
}
|
||||
|
||||
public T Resolve<T>(string name)
|
||||
{
|
||||
if (m_named.TryGetValue(typeof(T), out var nameToItem))
|
||||
{
|
||||
if (nameToItem.TryGetValue(name, out var item))
|
||||
{
|
||||
return item.Resolve<T>();
|
||||
}
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public T Resolve<T>()
|
||||
{
|
||||
if (m_registered.TryGetValue(typeof(T), out var item))
|
||||
{
|
||||
return item.Resolve<T>();
|
||||
}
|
||||
|
||||
if (m_fallbacks.TryGetValue(typeof(T), out item))
|
||||
{
|
||||
return item.Resolve<T>();
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
m_registered.Clear();
|
||||
m_fallbacks.Clear();
|
||||
m_named.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public class IOC
|
||||
{
|
||||
public static bool IsRegistered<T>(string name)
|
||||
{
|
||||
return _defaultContainer.IsRegistered<T>(name);
|
||||
}
|
||||
|
||||
public static void Register<T>(string name, Func<T> func)
|
||||
{
|
||||
_defaultContainer.Register(name, func);
|
||||
}
|
||||
|
||||
public static void Register<T>(string name, T instance)
|
||||
{
|
||||
_defaultContainer.Register(name, instance);
|
||||
}
|
||||
|
||||
public static void Unregister<T>(string name, Func<T> func)
|
||||
{
|
||||
_defaultContainer.Unregister(name, func);
|
||||
}
|
||||
|
||||
public static void Unregister<T>(string name, T instance)
|
||||
{
|
||||
_defaultContainer.Unregister(name, instance);
|
||||
}
|
||||
|
||||
public static bool IsRegistered<T>()
|
||||
{
|
||||
return _defaultContainer.IsRegistered<T>();
|
||||
}
|
||||
|
||||
public static void Register<T>(Func<T> func)
|
||||
{
|
||||
_defaultContainer.Register(func);
|
||||
}
|
||||
|
||||
public static void Register<T>(T instance)
|
||||
{
|
||||
_defaultContainer.Register(instance);
|
||||
}
|
||||
|
||||
public static void Unregister<T>(Func<T> func)
|
||||
{
|
||||
_defaultContainer.Unregister(func);
|
||||
}
|
||||
|
||||
public static void Unregister<T>(T instance)
|
||||
{
|
||||
_defaultContainer.Unregister(instance);
|
||||
}
|
||||
|
||||
public static void Unregister<T>()
|
||||
{
|
||||
_defaultContainer.Unregister<T>();
|
||||
}
|
||||
|
||||
public static bool IsFallbackRegistered<T>()
|
||||
{
|
||||
return _defaultContainer.IsFallbackRegistered<T>();
|
||||
}
|
||||
|
||||
public static void RegisterFallback<T>(Func<T> func)
|
||||
{
|
||||
_defaultContainer.RegisterFallback(func);
|
||||
}
|
||||
|
||||
public static void RegisterFallback<T>(T instance)
|
||||
{
|
||||
_defaultContainer.RegisterFallback(instance);
|
||||
}
|
||||
|
||||
public static void UnregisterFallback<T>(Func<T> func)
|
||||
{
|
||||
_defaultContainer.UnregisterFallback(func);
|
||||
}
|
||||
|
||||
public static void UnregisterFallback<T>(T instance)
|
||||
{
|
||||
_defaultContainer.UnregisterFallback(instance);
|
||||
}
|
||||
|
||||
public static void UnregisterFallback<T>()
|
||||
{
|
||||
_defaultContainer.UnregisterFallback<T>();
|
||||
}
|
||||
|
||||
public static T Resolve<T>(string name)
|
||||
{
|
||||
return _defaultContainer.Resolve<T>(name);
|
||||
}
|
||||
|
||||
public static T Resolve<T>()
|
||||
{
|
||||
return _defaultContainer.Resolve<T>();
|
||||
}
|
||||
|
||||
public static void ClearAll()
|
||||
{
|
||||
_defaultContainer.Clear();
|
||||
}
|
||||
|
||||
private static readonly IOCContainer _defaultContainer = new IOCContainer();
|
||||
|
||||
public static IOCContainer GetContainerFor(MonoBehaviour monoBehaviour = null)
|
||||
{
|
||||
if (monoBehaviour == null)
|
||||
{
|
||||
return _defaultContainer;
|
||||
}
|
||||
|
||||
IOCGroup group = monoBehaviour.GetComponentInParent<IOCGroup>();
|
||||
return group != null ? group.Container : _defaultContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/NBC/Core/Runtime/Utils/IOC.cs.meta
Normal file
3
Assets/Scripts/NBC/Core/Runtime/Utils/IOC.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf3b404ec20d46068f285c3f75db31c2
|
||||
timeCreated: 1716780264
|
||||
92
Assets/Scripts/NBC/Core/Runtime/Utils/RandomGenerator.cs
Normal file
92
Assets/Scripts/NBC/Core/Runtime/Utils/RandomGenerator.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
// 支持多线程
|
||||
public static class RandomGenerator
|
||||
{
|
||||
[ThreadStatic] private static Random random;
|
||||
|
||||
private static Random GetRandom()
|
||||
{
|
||||
return random ??= new Random(Guid.NewGuid().GetHashCode() ^ Environment.TickCount);
|
||||
}
|
||||
|
||||
public static ulong RandUInt64()
|
||||
{
|
||||
int r1 = RandInt32();
|
||||
int r2 = RandInt32();
|
||||
return ((ulong)r1 << 32) | (uint)r2;
|
||||
}
|
||||
|
||||
public static int RandInt32()
|
||||
{
|
||||
return GetRandom().Next();
|
||||
}
|
||||
|
||||
public static uint RandUInt32()
|
||||
{
|
||||
return (uint)GetRandom().Next();
|
||||
}
|
||||
|
||||
public static long RandInt64()
|
||||
{
|
||||
uint r1 = RandUInt32();
|
||||
uint r2 = RandUInt32();
|
||||
return (long)(((ulong)r1 << 32) | r2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取lower与Upper之间的随机数,包含下限,不包含上限
|
||||
/// </summary>
|
||||
/// <param name="lower"></param>
|
||||
/// <param name="upper"></param>
|
||||
/// <returns></returns>
|
||||
public static int RandomNumber(int lower, int upper)
|
||||
{
|
||||
int value = GetRandom().Next(lower, upper);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static bool RandomBool()
|
||||
{
|
||||
return GetRandom().Next(2) == 0;
|
||||
}
|
||||
|
||||
public static T RandomArray<T>(T[] array)
|
||||
{
|
||||
return array[RandomNumber(0, array.Length)];
|
||||
}
|
||||
|
||||
public static T RandomArray<T>(List<T> array)
|
||||
{
|
||||
return array[RandomNumber(0, array.Count)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打乱数组
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="arr">要打乱的数组</param>
|
||||
public static void BreakRank<T>(List<T> arr)
|
||||
{
|
||||
if (arr == null || arr.Count < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < arr.Count; i++)
|
||||
{
|
||||
int index = GetRandom().Next(0, arr.Count);
|
||||
(arr[index], arr[i]) = (arr[i], arr[index]);
|
||||
}
|
||||
}
|
||||
|
||||
public static float RandFloat01()
|
||||
{
|
||||
int a = RandomNumber(0, 1000000);
|
||||
return a / 1000000f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fcef27fa83a45efaa4f85df9acbdf42
|
||||
timeCreated: 1733994673
|
||||
Reference in New Issue
Block a user