功能:通过全局事件使类与类之间的通信解耦(两个类之间无需知道彼此的存在,类似广播电台,一个类发送,一个类监听)。
特点:使一个类继承Ib_Event即可快速声明一个全局同步事件,支持立即/延迟一帧调用、同步/异步执行、重载了至多五个参数的传入。
性能:在事件注册和注销时会有容器容量变化产生的GC。通过List和脏标记,大量相同事件在同一帧内同时注册或注销会有多次List扩容和一次数组复制扩容带来的GC(在注册后第一次调用时产生),后续调用事件不会产生GC。
可能的缺点:要十分注意事件的注册和注销,尤其是场景切换的时候,不然会内存泄漏。
更新记录:
2025-12-14 v0.3 优化了n个相同事件在同一帧同时注册/注销时,会进行n次数组复制扩容的性能问题。现在每次注册/注销只会List进行扩容,产生微量GC,并在注册后的首次调用时将List转化为数组(n次同时注册只会产生一次数组的扩容)。对异步事件中心进行优化。
2025-12-23 v0.4 使用Ib_Event.InvokeNextFrame()延迟一帧调用事件时,每次都会为Ib_Async.DelayDoSomething()方法传入新的委托实例产生GC。现在使用了一个只读静态委托变量CachedInvokeAction缓存,避免了每次调用的GC。
public abstract partial class Ib_Event<T, T1, T2> : IIb_Event where T : Ib_Event<T, T1, T2>
{
private static readonly Action<T1, T2> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, cts);
}
2026-07-30 v0.5 增加Ib_EventListener拓展Listen()方法,支持监听生命周期(OnDestroy,OnDisable)自动取消订阅(Listen中包含Register注册,并在特定生命周期时DeRegister)。
示例:我挂了,使游戏结束。
玩家类:在挂了以后发送OnPlayerDead事件。
//一个类继承Ib_Event,即可新建一个全局事件。这个类不需要任何成员。
public class OnPlayerDead : Ib_Event<OnPlayerDead> { }
public class Sample_Ib_Event_Player : MonoBehaviour
{
void Start()
{
//我在五秒后挂了
Ib_Async.DelayDoSomething(5,Die,this.GetCancellationTokenOnDestroy());
}
void Die()
{
Ib_Log.Info($"{GetType().Name} >> 啊,我挂了。");
//发送我挂了的消息
OnPlayerDead.Invoke();
}
}
管理器:监听OnPlayerDead事件,触发后调用GameOver()结束游戏。
//游戏进程的管理器,可以在这里接收玩家挂了的消息。
public class Sample_Ib_Event_GameManager : Ib_Singleton<Sample_Ib_Event_GameManager>
{
protected override void Awake()
{
base.Awake();
//订阅玩家挂了的事件,如果消息传来,就调用GameOver()方法使游戏结束。
OnPlayerDead.Register(GameOver);
}
protected override void OnDestroy()
{
base.OnDestroy();
//(必须)在生命周期的末尾取消订阅事件,避免内存泄漏。
OnPlayerDead.Deregister(GameOver);
}
//如果玩家挂了,就游戏结束
void GameOver()
{
Ib_Log.Info($"{GetType().Name} >> 玩家挂了,游戏结束");
}
}

玩家类和管理器类之间并没有任何的相互引用,它们不知道彼此的存在,它们的通信全都由第三方的事件中心来进行接收和转发。这样这两个之间就没有了耦合关系,哪怕管理器类不存在,也不有任何的报错。
Ib_Event也支持参数的传递,如玩家挂了,我需要传递玩家挂了的消息和遗言。管理器的GameOver方法就需要接收传来的string类型遗言,并进行打印。
//一个类继承Ib_Event,即可就新建一个全局事件。这个类不需要任何成员。
public class OnPlayerDead : Ib_Event<OnPlayerDead,string> { }
public class Sample_Ib_Event_Player : MonoBehaviour
{
void Start()
{
//我在五秒后挂了
Ib_Async.DelayDoSomething(5,Die,this.GetCancellationTokenOnDestroy());
}
void Die()
{
Ib_Log.Info($"{GetType().Name} >> 啊,我挂了。");
//发送我挂了的消息
OnPlayerDead.Invoke("卧槽,我竟然挂了,我不甘心啊");
}
}
//如果玩家挂了,就游戏结束
void GameOver(string message)
{
Ib_Log.Info($"遗言 >> {message}");
Ib_Log.Info($"{GetType().Name} >> 玩家挂了,游戏结束");
}

核心功能简易实现:
using System;
using System.Collections.Generic;
/// <summary>
/// 事件系统的基础接口(标记接口)。
/// <para>主要用于泛型约束,确保只有实现了该接口的类型才能被注册到事件中心。</para>
/// </summary>
public interface ISample_Ib_Event { }
/// <summary>
/// 事件基类。所有自定义事件需继承此类。使用示例:public class 事件名 : Sample_Ib_Event<事件名> { }
/// <para>使用 CRTP (Curiously Recurring Template Pattern) 模式,简化静态调用。</para>
/// </summary>
/// <typeparam name="T">具体的事件类型(即子类自身)。</typeparam>
public abstract class Sample_Ib_Event<T> : ISample_Ib_Event where T : Sample_Ib_Event<T>
{
/// <summary>
/// 触发(广播)事件。
/// <para>通知所有订阅了该事件的监听者。</para>
/// </summary>
public static void Invoke()
{
Sample_Ib_EventHandler.Invoke<T>();
}
/// <summary>
/// 注册(订阅)事件。
/// </summary>
/// <param name="action">事件触发时要执行的回调函数。</param>
public static void Register(Action action)
{
Sample_Ib_EventHandler.Register<T>(action);
}
/// <summary>
/// 取消注册(退订)事件。
/// <para>注意:必须传入与注册时完全相同的委托实例。</para>
/// </summary>
/// <param name="action">需要移除的回调函数。</param>
public static void Deregister(Action action)
{
Sample_Ib_EventHandler.Deregister<T>(action);
}
}
/// <summary>
/// 事件中心(核心管理器)。
/// <para>负责底层存储和分发消息。通常不需要直接调用此类,而是通过继承 <see cref="Sample_Ib_Event{T}"/> 来使用。</para>
/// </summary>
public static class Sample_Ib_EventHandler
{
// 存储所有事件委托的字典,Key 为事件类型,Value 为多播委托
private static readonly Dictionary<Type, Action> EventsDict = new();
/// <summary>
/// 执行指定类型的事件。
/// </summary>
/// <typeparam name="T">必须实现 <see cref="ISample_Ib_Event"/> 的事件类型。</typeparam>
public static void Invoke<T>() where T : ISample_Ib_Event
{
if (EventsDict.TryGetValue(typeof(T), out var action))
{
action?.Invoke();
}
}
/// <summary>
/// 将回调注册到指定类型的事件中。
/// </summary>
/// <typeparam name="T">事件类型。</typeparam>
/// <param name="action">回调委托。</param>
public static void Register<T>(Action action) where T : ISample_Ib_Event
{
Type eventType = typeof(T);
// 如果字典中不存在该 Key,则添加;如果存在,则使用 += 进行多播委托叠加
if (!EventsDict.TryAdd(eventType, action))
EventsDict[eventType] += action;
}
/// <summary>
/// 从指定类型的事件中移除回调。
/// </summary>
/// <typeparam name="T">事件类型。</typeparam>
/// <param name="action">要移除的回调委托。</param>
public static void Deregister<T>(Action action) where T : ISample_Ib_Event
{
Type eventType = typeof(T);
if (EventsDict.ContainsKey(eventType))
{
EventsDict[eventType] -= action;
}
}
}
同步事件中心源码:
*订阅Register/注销Deregister后首次Invoke会有数组分配,之后的Invoke零分配。

//支持至多五个参数的事件中心。
//使用方法:
//1、声明一个事件类,继承Ib_Event
// public class OnGameLog : Ib_Event<OnGameLog,string> { };
//2、在Mono类中进行注册与注销
// Action<string> testAction = (string content)=>Ib_Log.Info(content);
// OnGameLog.Register(testAction);
// OnGameLog.Deregister(testAction);
//3、调用
//OnGameLog.Invoke("成功调用");
namespace Ib_Core
{
using System;
using System.Collections.Generic;
internal interface IIb_Event
{
}
#region 无参数事件基类
public abstract partial class Ib_Event<T> : IIb_Event where T : Ib_Event<T>
{
public static void Invoke() => Ib_EventHandler.Invoke<T>();
public static void Register(Action action) => Ib_EventHandler.Register<T>(action);
public static void Deregister(Action action) => Ib_EventHandler.Deregister<T>(action);
}
#endregion
#region 单参数事件基类
public abstract partial class Ib_Event<T, T1> : IIb_Event where T : Ib_Event<T, T1>
{
public static void Invoke(T1 arg1) => Ib_EventHandler.Invoke<T, T1>(arg1);
public static void Register(Action<T1> action) => Ib_EventHandler.Register<T, T1>(action);
public static void Deregister(Action<T1> action) => Ib_EventHandler.Deregister<T, T1>(action);
}
#endregion
#region 双参数事件基类
public abstract partial class Ib_Event<T, T1, T2> : IIb_Event where T : Ib_Event<T, T1, T2>
{
public static void Invoke(T1 arg1, T2 arg2) => Ib_EventHandler.Invoke<T, T1, T2>(arg1, arg2);
public static void Register(Action<T1, T2> action) => Ib_EventHandler.Register<T, T1, T2>(action);
public static void Deregister(Action<T1, T2> action) => Ib_EventHandler.Deregister<T, T1, T2>(action);
}
#endregion
#region 三参数事件基类
public abstract partial class Ib_Event<T, T1, T2, T3> : IIb_Event where T : Ib_Event<T, T1, T2, T3>
{
public static void Invoke(T1 arg1, T2 arg2, T3 arg3) => Ib_EventHandler.Invoke<T, T1, T2, T3>(arg1, arg2, arg3);
public static void Register(Action<T1, T2, T3> action) => Ib_EventHandler.Register<T, T1, T2, T3>(action);
public static void Deregister(Action<T1, T2, T3> action) => Ib_EventHandler.Deregister<T, T1, T2, T3>(action);
}
#endregion
#region 四参数事件基类
public abstract partial class Ib_Event<T, T1, T2, T3, T4> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4>
{
public static void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4) =>
Ib_EventHandler.Invoke<T, T1, T2, T3, T4>(arg1, arg2, arg3, arg4);
public static void Register(Action<T1, T2, T3, T4> action) =>
Ib_EventHandler.Register<T, T1, T2, T3, T4>(action);
public static void Deregister(Action<T1, T2, T3, T4> action) =>
Ib_EventHandler.Deregister<T, T1, T2, T3, T4>(action);
}
#endregion
#region 五参数事件基类
public abstract partial class Ib_Event<T, T1, T2, T3, T4, T5> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4, T5>
{
public static void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) =>
Ib_EventHandler.Invoke<T, T1, T2, T3, T4, T5>(arg1, arg2, arg3, arg4, arg5);
public static void Register(Action<T1, T2, T3, T4, T5> action) =>
Ib_EventHandler.Register<T, T1, T2, T3, T4, T5>(action);
public static void Deregister(Action<T1, T2, T3, T4, T5> action) =>
Ib_EventHandler.Deregister<T, T1, T2, T3, T4, T5>(action);
}
#endregion
#region 事件容器
/// <summary>
/// 事件容器,使用写时复制(Copy-on-Write)策略来实现 0 GC 的 Invoke
/// </summary>
internal class Ib_EventContainer
{
// 直接持有数组,Invoke时直接遍历这个数组
private Delegate[] _actionArray = Array.Empty<Delegate>();
public bool IsEmpty => _actionList.Count == 0;
//list和脏标记用于防止同一帧内有大量事件同时注册,导致卡顿
private readonly List<Delegate> _actionList = new List<Delegate>();
private bool _isDirty = false;//脏标记
public void Add(Delegate callback)
{
if (callback == null) return;
_actionList.Add(callback);
_isDirty = true;
}
public void Remove(Delegate callback)
{
if (callback == null) return;
if (_actionList.Remove(callback))
{
_isDirty = true;
}
}
public Delegate[] GetDelegateArray()
{
if (_isDirty)
{
_actionArray = _actionList.ToArray();
_isDirty = false;
}
return _actionArray;
}
}
#endregion
internal static partial class Ib_EventHandler
{
private static readonly Dictionary<Type, Ib_EventContainer> EventsDict = new();
private static readonly object _lock = new object();
// 获取或创建容器的辅助方法
private static Ib_EventContainer GetContainer(Type type, bool createIfNull)
{
if (!EventsDict.TryGetValue(type, out var container))
{
if (createIfNull)
{
container = new Ib_EventContainer();
EventsDict[type] = container;
}
}
return container;
}
#region 无参数的事件处理
public static void Invoke<T>() where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action)actions[i];
try
{
action?.Invoke();
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T>(Action action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T>(Action action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 单参数的事件处理
public static void Invoke<T, T1>(T1 arg1) where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1>)actions[i];
try
{
action?.Invoke(arg1);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1>(Action<T1> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1>(Action<T1> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 双参数的事件处理
public static void Invoke<T, T1, T2>(T1 arg1, T2 arg2) where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1, T2>)actions[i];
try
{
action?.Invoke(arg1, arg2);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1, T2>(Action<T1, T2> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1, T2>(Action<T1, T2> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 三参数的事件处理
public static void Invoke<T, T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3) where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1, T2, T3>)actions[i];
try
{
action?.Invoke(arg1, arg2, arg3);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1, T2, T3>(Action<T1, T2, T3> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1, T2, T3>(Action<T1, T2, T3> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 四参数的事件处理
public static void Invoke<T, T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4) where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1, T2, T3, T4>)actions[i];
try
{
action?.Invoke(arg1, arg2, arg3, arg4);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1, T2, T3, T4>(Action<T1, T2, T3, T4> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1, T2, T3, T4>(Action<T1, T2, T3, T4> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
#region 五参数的事件处理
public static void Invoke<T, T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
where T : IIb_Event
{
Delegate[] actions = null;
lock (_lock)
{
if (EventsDict.TryGetValue(typeof(T), out var container))
{
actions = container.GetDelegateArray();
}
}
if (actions == null || actions.Length == 0) return;
for (int i = 0; i < actions.Length; i++)
{
var action = (Action<T1, T2, T3, T4, T5>)actions[i];
try
{
action?.Invoke(arg1, arg2, arg3, arg4, arg5);
}
catch (Exception ex)
{
Ib_Log.Error($"Error while invoking event {typeof(T).Name}: {ex.Message}\n{ex.StackTrace}");
}
}
}
public static void Register<T, T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), true);
container.Add(action);
}
}
public static void Deregister<T, T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action) where T : IIb_Event
{
lock (_lock)
{
var container = GetContainer(typeof(T), false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(typeof(T));
}
}
}
}
#endregion
}
}
Ib_EventListener订阅后自动注销
用处:避免事件订阅后忘记注销,造成内存泄漏
前提:使用类需要继承MonoBehaviour
using Ib_Core;
using Ib_Core.Ib_Controller;
//游戏进程的管理器,可以在这里接收玩家挂了的消息。
public class Sample_Ib_Event_GameManager : Ib_Singleton<Sample_Ib_Event_GameManager>
{
protected override void Awake()
{
base.Awake();
//使用Listen()订阅,自动管理事件的生命周期
OnPlayerDead.Listen(GameOver,new ListenConfig(this,Ib_EventListener.EDeregisterLc.OnDestroy));
//订阅玩家挂了的事件,如果消息传来,就调用GameOver()方法使游戏结束。
// OnPlayerDead.Register(GameOver);
}
protected override void OnDestroy()
{
base.OnDestroy();
//(必须)在生命周期的末尾取消订阅事件,避免内存泄漏。
// OnPlayerDead.Deregister(GameOver);
}
//如果玩家挂了,就游戏结束
void GameOver(string message)
{
Ib_Log.Info($"遗言 >> {message}");
Ib_Log.Info($"{GetType().Name} >> 玩家挂了,游戏结束");
}
}
使用Listen()订阅时绑定MonoBehaviour生命周期,自动注销
//事件自动注销拓展:注册事件时绑定 MonoBehaviour 生命周期,到期自动注销,无需手动 Deregister。
//支持 OnDestroy / OnDisable 两种注销时机(EDeregisterLc)。
//OnDisable 为一次性注销:在 OnEnable 中调用 Listen 注册,OnDisable 时自动注销,下次 OnEnable 需重新 Listen。
//零闭包 GC:通过 typeof(T) + Delegate 直传 Tracker,不产生 closure。
//用法:
//1、声明事件类,继承 Ib_Event
// public class OnPlayerDead : Ib_Event<OnPlayerDead, string> { }
//2、在 MonoBehaviour 中注册(泛型参数自动推导,无需手写)
// void OnEnable()
// {
// OnPlayerDead.Listen(OnPlayerDeadHandler, new ListenConfig(this, Ib_EventListener.EDeregisterLc.OnDisable));
// }
// void OnPlayerDeadHandler(string killer) { ... }
//3、调用
// OnPlayerDead.Invoke("Boss");
namespace Ib_Core
{
using System;
using UnityEngine;
public static class Ib_EventListener
{
public enum EDeregisterLc
{
OnDestroy,
OnDisable
}
internal static void AddToTracker(MonoBehaviour owner, Type type, Delegate action, EDeregisterLc deregisterLc)
{
if (!owner.TryGetComponent(out Ib_EventLifecycleTracker tracker))
tracker = owner.gameObject.AddComponent<Ib_EventLifecycleTracker>();
switch (deregisterLc)
{
case EDeregisterLc.OnDestroy:
default:
tracker.Add2Destroy(type, action);
break;
case EDeregisterLc.OnDisable:
tracker.Add2Disable(type, action);
break;
}
}
internal static void AddMessengerToTracker(MonoBehaviour owner, int hash, Delegate action, EDeregisterLc deregisterLc)
{
if (!owner.TryGetComponent(out Ib_EventLifecycleTracker tracker))
tracker = owner.gameObject.AddComponent<Ib_EventLifecycleTracker>();
switch (deregisterLc)
{
case EDeregisterLc.OnDestroy:
default:
tracker.AddMessenger2Destroy(hash, action);
break;
case EDeregisterLc.OnDisable:
tracker.AddMessenger2Disable(hash, action);
break;
}
}
}
internal static partial class Ib_EventHandler
{
public static void Deregister(Type eventType, Delegate action)
{
var container = GetContainer(eventType, false);
if (container != null)
{
container.Remove(action);
if (container.IsEmpty)
{
EventsDict.Remove(eventType);
}
}
}
}
public struct ListenConfig
{
public MonoBehaviour Listener;
public Ib_EventListener.EDeregisterLc DeregisterLc;
public ListenConfig(MonoBehaviour listener, Ib_EventListener.EDeregisterLc deregisterLc)
{
Listener = listener;
DeregisterLc = deregisterLc;
}
}
public abstract partial class Ib_Event<T> : IIb_Event where T : Ib_Event<T>
{
public static void Listen(Action action, ListenConfig listenConfig)
{
Ib_EventListener.AddToTracker(listenConfig.Listener, typeof(T), action, listenConfig.DeregisterLc);
Ib_EventHandler.Register<T>(action);
}
}
public abstract partial class Ib_Event<T, T1> : IIb_Event where T : Ib_Event<T, T1>
{
public static void Listen(Action<T1> action, ListenConfig listenConfig)
{
Ib_EventListener.AddToTracker(listenConfig.Listener, typeof(T), action, listenConfig.DeregisterLc);
Ib_EventHandler.Register<T, T1>(action);
}
}
public abstract partial class Ib_Event<T, T1, T2> : IIb_Event where T : Ib_Event<T, T1, T2>
{
public static void Listen(Action<T1, T2> action, ListenConfig listenConfig)
{
Ib_EventListener.AddToTracker(listenConfig.Listener, typeof(T), action, listenConfig.DeregisterLc);
Ib_EventHandler.Register<T, T1, T2>(action);
}
}
public abstract partial class Ib_Event<T, T1, T2, T3> : IIb_Event where T : Ib_Event<T, T1, T2, T3>
{
public static void Listen(Action<T1, T2, T3> action, ListenConfig listenConfig)
{
Ib_EventListener.AddToTracker(listenConfig.Listener, typeof(T), action, listenConfig.DeregisterLc);
Ib_EventHandler.Register<T, T1, T2, T3>(action);
}
}
public abstract partial class Ib_Event<T, T1, T2, T3, T4> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4>
{
public static void Listen(Action<T1, T2, T3, T4> action, ListenConfig listenConfig)
{
Ib_EventListener.AddToTracker(listenConfig.Listener, typeof(T), action, listenConfig.DeregisterLc);
Ib_EventHandler.Register<T, T1, T2, T3, T4>(action);
}
}
public abstract partial class Ib_Event<T, T1, T2, T3, T4, T5> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4, T5>
{
public static void Listen(Action<T1, T2, T3, T4, T5> action, ListenConfig listenConfig)
{
Ib_EventListener.AddToTracker(listenConfig.Listener, typeof(T), action, listenConfig.DeregisterLc);
Ib_EventHandler.Register<T, T1, T2, T3, T4, T5>(action);
}
}
}
using System;
using System.Collections.Generic;
using Ib_Core;
using UnityEngine;
// 隐藏组件,挂在 owner 的 GameObject 上
// 同时支持 Ib_Event (Type key) 和 Ib_Messenger (int hash key) 的自动注销
internal class Ib_EventLifecycleTracker : MonoBehaviour
{
List<(Type eventType, Delegate dlg)> _destroyEntries;
List<(Type eventType, Delegate dlg)> _disableEntries;
List<(int hash, Delegate dlg)> _messengerDestroyEntries;
List<(int hash, Delegate dlg)> _messengerDisableEntries;
void OnDestroy()
{
if (_destroyEntries != null)
{
foreach (var (type, dlg) in _destroyEntries)
Ib_EventHandler.Deregister(type, dlg);
_destroyEntries.Clear();
}
if (_messengerDestroyEntries != null)
{
foreach (var (hash, dlg) in _messengerDestroyEntries)
Ib_Messenger.Deregister(hash, dlg);
_messengerDestroyEntries.Clear();
}
}
public void Add2Destroy(Type type, Delegate action)
{
if (_destroyEntries == null) _destroyEntries = new();
_destroyEntries.Add((type, action));
}
public void Add2Disable(Type type, Delegate action)
{
if (_disableEntries == null) _disableEntries = new();
_disableEntries.Add((type, action));
}
public void AddMessenger2Destroy(int hash, Delegate action)
{
if (_messengerDestroyEntries == null) _messengerDestroyEntries = new();
_messengerDestroyEntries.Add((hash, action));
}
public void AddMessenger2Disable(int hash, Delegate action)
{
if (_messengerDisableEntries == null) _messengerDisableEntries = new();
_messengerDisableEntries.Add((hash, action));
}
void OnDisable()
{
if (_disableEntries != null)
{
foreach (var (type, dlg) in _disableEntries)
Ib_EventHandler.Deregister(type, dlg);
_disableEntries.Clear();
}
if (_messengerDisableEntries != null)
{
foreach (var (hash, dlg) in _messengerDisableEntries)
Ib_Messenger.Deregister(hash, dlg);
_messengerDisableEntries.Clear();
}
}
}
延迟一帧调用拓展:
#region 零参数事件基类延迟拓展
public abstract partial class Ib_Event<T> : IIb_Event where T : Ib_Event<T>
{
private static readonly Action CachedInvokeAction = Ib_EventHandler.Invoke<T>;
public static void InvokeNextFrame(CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, cts);
}
#endregion
#region 单参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1> : IIb_Event where T : Ib_Event<T, T1>
{
private static readonly Action<T1> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1>;
public static void InvokeNextFrame(T1 arg1, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, cts);
}
#endregion
#region 双参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1, T2> : IIb_Event where T : Ib_Event<T, T1, T2>
{
private static readonly Action<T1, T2> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, cts);
}
#endregion
#region 三参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1, T2, T3> : IIb_Event where T : Ib_Event<T, T1, T2, T3>
{
private static readonly Action<T1, T2, T3> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2, T3>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, T3 arg3, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, arg3, cts);
}
#endregion
#region 四参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1, T2, T3, T4> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4>
{
private static readonly Action<T1, T2, T3, T4> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2, T3, T4>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, T3 arg3, T4 arg4, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, arg3, arg4, cts);
}
#endregion
#region 五参数事件基类延迟拓展
public abstract partial class Ib_Event<T, T1, T2, T3, T4, T5> : IIb_Event where T : Ib_Event<T, T1, T2, T3, T4, T5>
{
private static readonly Action<T1, T2, T3, T4, T5> CachedInvokeAction = Ib_EventHandler.Invoke<T, T1, T2, T3, T4, T5>;
public static void InvokeNextFrame(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, CancellationToken cts) => Ib_Async.DelayDoSomething(0, CachedInvokeAction, arg1, arg2, arg3, arg4, arg5, cts);
}
#endregion
评论(0)
暂无评论