事件系统
Fink Framework 内置一套 轻量级、强类型、无 GC 的全局事件系统,用于模块间解耦通信。 你可以通过事件实现:
- UI → 逻辑通信
- 场景加载进度同步
- 输入事件广播
- 数据变化通知
- 任意模块间的松耦合消息分发
1. 添加事件类型
所有事件都必须在 E_EventType.cs 中声明。
路径:
Framework/Event/E_EventType.cs
示例:
/// <summary>
/// 测试事件 —— 无参数
/// </summary>
E_Test,
/// <summary>
/// 场景加载进度 —— float
/// </summary>
E_SceneLoadChange
如果你不在这里声明事件,事件系统将无法识别该事件类型!
事件最好按模块分类,如:
#region UI
UI_Open,
UI_Close,
#endregion
#region Scene
Scene_LoadChange,
Scene_Loaded,
#endregion
2. 核心结构
EventManager // 全局事件中心(单例)
EventInfo // 无参事件容器
EventInfo<T> // 单参数事件容器
EventInfo<T1,T2> // 双参数事件容器
E_EventType // 全局枚举事件类型
3. 注册事件监听
3.1 无参事件
示例:
EventManager.Instance.AddEventListener(E_EventType.E_Test, OnTest);
// 回调函数
void OnTest()
{
Debug.Log("Test Event Triggered");
}
3.2 单参数事件
示例:
EventManager.Instance.AddEventListener<float>(E_EventType.E_SceneLoadChange, OnProgress);
// 回调函数
void OnProgress(float value)
{
Debug.Log("Progress = " + value);
}
3.3 双参数事件
示例:
EventManager.Instance.AddEventListener<float, float>(E_EventType.E_Loading, OnLoadStep);
// 回调函数
void OnLoadStep(float cur, float total)
{
Debug.Log($"{cur}/{total}");
}
4. 触发事件
4.1 无参触发
示例:
EventManager.Instance.EventTrigger(E_EventType.E_Test);
4.2 单参触发
示例:
EventManager.Instance.EventTrigger<float>(E_EventType.E_SceneLoadChange, 0.5f);
4.3 双参触发
示例:
EventManager.Instance.EventTrigger<float, float>(E_EventType.E_Loading, 20, 100);
5. 移除监听(必须)
如果你在 OnEnable 注册事件,必须在 OnDisable 移除:
示例:
EventManager.Instance.RemoveEventListener(E_EventType.E_Test, OnTest);\
防止内存泄漏和重复监听。
6. 清理事件(切换场景时推荐)
若您使用框架内置的场景切换系统来加载场景,则已经内置了在切换场景时清除事件监听的逻辑。 详情请见场景切换系统
EventManager.Instance.ClearAllEvent();
或只清理某一类事件:
EventManager.Instance.ClearEvent(E_EventType.E_Test);
7. 粘性事件(Sticky Event)
粘性事件的特性:
事件触发后,新加入的监听者也会立刻收到最近一次的值。
注册方式:
EventManager.Instance.AddEventListener<float>(E_EventType.E_SceneLoadChange, OnProgress, sticky: true);
适合:
- 场景加载进度
- 配置初始化状态
- 玩家数据准备完成
不适合:
- 高频 Tick
- 输入事件
- 每帧更新事件
8. 事件自动绑定工具(强烈推荐)
为了避免手动移除监听带来的重复绑定、忘记解绑、切场景残留等问题, Fink Framework 提供了 EventAutoBinder —— 一行代码即可实现事件的自动注册与自动解绑。
EventAutoBinder 支持两种工作模式:
-
Bind() —— 立即注册,并在 OnDestroy 自动解绑(适合逻辑类、常驻对象)
-
BindAuto() —— OnEnable 自动注册,OnDisable 自动解绑(适合 UI 面板、临时对象)
7.1 Bind() 默认模式
用法:
EventAutoBinder.Bind(this, E_EventType.UI_Open, OnOpen);
等价于:
AddEventListener(...) // 立即注册
OnDestroy -> RemoveEventListener(...) // 自动解绑
示例:
private void Start()
{
EventAutoBinder.Bind(this, E_EventType.UI_Open, OnOpen);
}
void OnOpen()
{
Debug.Log("UI Open Event Received");
}
7.2 BindAuto() 自动模式
用法:
EventAutoBinder.BindAuto(this, E_EventType.E_SceneLoadChange, OnProgress);
等价于:
OnEnable -> AddEventListener(...)
OnDisable -> RemoveEventListener(...)
示例:
private void OnEnable()
{
EventAutoBinder.BindAuto(this, E_EventType.E_SceneLoadChange, OnProgress);
}
void OnProgress(float p)
{
Debug.Log("Loading: " + p);
}
你无需再写 OnDisable 代码,自动解绑会帮你做干净。
7.3 支持 0 / 1 / 2 参数事件
EventAutoBinder 完全支持:
Bind(type, UnityAction)
Bind<T>(type, UnityAction<T>)
Bind<T1,T2>(type, UnityAction<T1,T2>)
以及对应的 BindAuto 版本。
示例:
EventAutoBinder.BindAuto<float, float>(this, E_EventType.E_Loading, OnStep);
void OnStep(float cur, float total)
{
Debug.Log($"{cur}/{total}");
}