SuperAPI AI 工具集

delegates-and-events

编程与开发

查看项目

更新于 11-06 16:21

技能介绍

本技能面向虚幻引擎 C++ 开发者,系统讲解委托(Delegate)与事件机制。委托是虚幻引擎的类型安全函数指针/观察者系统,所有绑定代码编写前必须先选定委托家族,因为不同家族在蓝图可见性、绑定 API 与序列化能力上存在差异。

【用途】当一个对象需要在某事发生时通知其他对象(观察者模式);把 C++ 事件暴露给蓝图订阅(BlueprintAssignable);解耦系统,用广播事件代替直接调用已知类;绑定需要 UFUNCTION 的重叠/命中/技能完成回调;以及排查因绑定类型错误、对象已销毁或宏使用不当导致的崩溃或静默无操作。

【三大委托家族】单播(DECLARE_DELEGATE*):恰好一个监听者,不对蓝图开放,可带返回值(_RetVal);多播(DECLARE_MULTICAST_DELEGATE*):多个监听者,不对蓝图开放,无返回值;动态多播(DECLARE_DYNAMIC_MULTICAST_DELEGATE*):多个监听者,对蓝图开放,无返回值。决定规则:蓝图需订阅则用动态多播;纯 C++ 多监听者用多播;单个必需回调(可带返回值)用单播;若只是存储可调用对象而非事件,用 TFunction<Ret(Args...)>。后缀编码签名,如 _OneParam、_TwoParams、_RetVal_OneParam;最多支持 9 个参数,非动态委托最多 4 个 payload 变量;动态委托参数必须在宏中命名。声明需在全局、命名空间或类作用域,不能在函数体内。

【绑定方式】纯 C++ 委托可用 BindUObject(弱引用,对象死亡安全)、BindLambda(无生命周期保护,需手动解绑)、BindWeakLambda(由 UObject 弱引用保护)、AddUObject/AddWeakLambda/AddLambda 等;多播绑定返回 FDelegateHandle。动态委托只接受 UFUNCTION 标记的方法,用 AddDynamic/RemoveDynamic 宏包装,处理器必须是签名完全一致的 UFUNCTION()。

【执行与广播】多播与动态多播用 Broadcast() 通知所有监听者,零绑定时调用也安全;单播调用前应检查 IsBound(),或使用 ExecuteIfBound(未绑定则无操作但不返回值),Execute 在未绑定时会断言。多播委托不能有返回值。

【Payload 变量】非动态委托可在绑定时把额外参数烘焙进绑定,追加在声明参数之后,最多四个。

【解绑与生命周期】多播可用 Remove(Handle) 移除单个绑定、RemoveAll(this) 移除某对象全部绑定、Clear() 清空;动态多播用 RemoveDynamic;单播用 Unbind()。AddUObject/BindUObject、AddDynamic/BindDynamic、AddWeakLambda/BindWeakLambda、AddSP/BindSP 都跟踪生命周期,对象死亡后跳过绑定;AddLambda/BindLambda 与 AddRaw/BindRaw 不跟踪生命周期,捕获对象死亡后调用会崩溃,需在 EndPlay 或析构前保存句柄并 Remove(Handle)。

【其它】DECLARE_EVENT 为遗留写法,源码标记已弃用,建议改用普通多播配合私有广播方法实现封装;DECLARE_TS_MULTICAST_DELEGATE* 生成带读写锁保护的线程安全多播,适用于多线程增删绑定或广播,但每个回调体本身仍需自行同步。

【常见陷阱】AddDynamic 目标不是 UFUNCTION 会编译或注册错误;AddLambda/AddRaw 捕获 this 未在销毁前移除会崩溃;对未绑定单播调用 Execute 会断言;蓝图只能绑定动态多播;参数数量/类型与 _NParams 后缀不匹配无法编译;动态宏未提供参数名会编译错误;在 Broadcast 过程中增删监听者会被推迟到广播结束,委托会安全处理。

【参考】引擎源码 UE 5.8 中的 DelegateCombinations.h、Delegate.h、DelegateSignatureImpl.inl、MulticastDelegateBase.h、IDelegateInstance.h、Function.h,以及官方单播/多播/动态委托文档链接;本技能还附带引用文件,分别覆盖委托类型矩阵、绑定与生命周期、动态委托与蓝图接线。