事件分发器:一对多广播
接口解决"一对一解耦",事件分发器(Event Dispatcher)解决"一对多"。
经典场景:Boss 死亡。要通知 UI 切画面、通知小怪逃跑、通知任务系统计数、通知全体玩家。如果 Boss 逐一 Cast 调用,代码里就写死了四个接收者,以后加第五个还得改 Boss。
蓝图用法
- 在 Boss 蓝图的 My Blueprint 面板新建 Event Dispatcher,如
OnBossDied; - 别的蓝图通过 Bind Event to OnBossDied 节点订阅(输入 Boss 引用);
- Boss 死亡时调用 Call OnBossDied——所有订阅者同时收到。
Boss 蓝图
└─ Call OnBossDied ──┬──> UI 蓝图(播结算)
├──> 小怪 AI(进入逃跑)
├──> 任务系统(+1 计数)
└──> 玩家控制器(成就)
关键优势:Boss 完全不知道有谁订阅,新增订阅者不用动 Boss 一根线。
C++ 侧:委托
C++ 里同样效果用委托(Delegate)实现。蓝图里的事件分发器,本质就是暴露给蓝图的 C++ 委托:
// 声明(类里)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnBossDied, AActor*, Boss);
public:
UPROPERTY(BlueprintAssignable, Category="Boss")
FOnBossDied OnBossDied;
BlueprintAssignable 让蓝图能绑定事件;C++ 里用 OnBossDied.Broadcast(Boss) 广播。这就是"跨层事件"的标准做法:C++ 负责广播,蓝图负责订阅与表现。
委托的三种形态
| 类型 | C++ 宏 | 谁能订阅 | 何时清理 |
|---|---|---|---|
| 普通委托 | DECLARE_DELEGATE |
只 C++ | 手动 |
| 多播委托 | DECLARE_MULTICAST_DELEGATE |
只 C++(多个) | 手动 |
| 动态多播 | DECLARE_DYNAMIC_MULTICAST... |
C++ + 蓝图 | 蓝图绑定自动随对象销毁清理 |
给蓝图用的事件一律 DYNAMIC_MULTICAST + BlueprintAssignable。参数用 OneParam/TwoParams/ThreeParam 后缀,蓝图里就能直接取到参数。
广播的生命周期注意
- 广播时若某个订阅者已被销毁 → 动态委托会自动跳过(安全),普通委托需要自己确保;
- Broadcast 的顺序不是调用者能依赖的——不要写"依赖订阅顺序"的逻辑;
- 广播在 C++ 里执行,订阅回调可能进入蓝图 VM——同.hot path 限制(别每帧广播给几百个蓝图订阅者)。
本章小结
- 事件分发器 = 一对多广播:发布者不认识订阅者。
- 蓝图事件分发器底层就是
DECLARE_DYNAMIC_MULTICAST_DELEGATE+BlueprintAssignable。 - 跨"系统→表现"的事件流(Boss 死亡、物品拾取、任务完成)都该用广播,而非互相 Cast。
