版权声明:本文为CSDN博主「永远的小白虾」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
事件调度器非常的适合在各个蓝图之间实现通信功能。
当前 UE4 版本 4.8.3。
在蓝图中,事件调度器的作用就像是事件的 派发器。通过将事件预先的 绑定 在事件调度器上,可以让系统可以在需要时将事件 派发 给所有已经绑定的事件。
事件调度器的使用
一个比较常见的使用事件调度器的地方,就是 关卡蓝图。
关卡蓝图中的很多物体的 Actor 及其逻辑,如果要脱离关卡蓝图的话会比较难于使用。因此,可以通过将关卡蓝图中实现好的功能绑定到某个类,例如 GameMode 的事件调度器上来方便调度。
如下图,在关卡蓝图的 BeginPlay 中将功能 绑定 到 GameMode 上:
然后可以在 GameMode 的蓝图中,设定定时的调度关卡蓝图上的功能
事件调度器同时还支持解绑和解绑全部,以方便对事件调度的逻辑进行进一步的控制。
Delegate
在 C++ 和蓝图混合使用时,使用 Blueprint Function Library 可以方便的实现蓝图到 C++ 的调用。如果要实现 C++ 对蓝图的逻辑的话,事件调度机制就非常的方便。
在 C++ 中,与事件调度器对应的是 Delegate 机制。事实上,Delegate 机制的涵盖范围比事件调度器要大一些。
Delegate 机制是一种常见的设计模式,相信做程序的童鞋都比较熟悉。这里不做多余的说明了。
UE4 官方对 Delegate 的翻译名称唯代理(委托)。按照类型,分为 单播代理 和 多播代理 。其中,多播代理与事件调度器的功能类似,而单播代理更接近单纯的代理,也就是 只能绑定一个执行函数 。
要让多播代理像是事件调度器一样使用的话,需要将其定义为 Dynamic 。对于单播代理也是一样的。
在 C++ 中使用 UE4 的代理功能,需要使用官方提供的 宏 进行定义。
| 函数签名 | 声明宏 |
|---|---|
void Function() | DECLARE_DELEGATE( DelegateName ) |
void Function( <Param1> ) | DECLARE_DELEGATE_OneParam( DelegateName, Param1Type ) |
void Function( <Param1>, <Param2> ) | DECLARE_DELEGATE_TwoParams( DelegateName, Param1Type, Param2Type ) |
void Function( <Param1>, <Param2>, … ) | DECLARE_DELEGATE_<Num>Params( DelegateName, Param1Type, Param2Type, … ) |
<RetVal> Function() | DECLARE_DELEGATE_RetVal( RetValType, DelegateName ) |
<RetVal> Function( <Param1> ) | DECLARE_DELEGATE_RetVal_OneParam( RetValType, DelegateName, Param1Type ) |
<RetVal> Function( <Param1>, <Param2> ) | DECLARE_DELEGATE_RetVal_TwoParams( RetValType, DelegateName, Param1Type, Param2Type ) |
<RetVal> Function( <Param1>, <Param2>, … ) | DECLARE_DELEGATE_RetVal_<Num>Params( RetValType, DelegateName, Param1Type, Param2Type, … ) |
针对不同的 代理类型,使用不同的 宏前缀 即可:
| 多播代理 | DECLARE_MULTICAST_DELEGATE… |
|---|---|
| 动态单播代理 | DECLARE_DYNAMIC_DELEGATE… |
| 动态多播代理 | DECLARE_DYNAMIC_MULTICAST_DELEGATE… |
实际使用时,首先要 对代理类型进行定义
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams ( FDspLRValDelegate , float , LVals , float , RVals ) ;
然后在具体的类,例如 GameState 中进行 具体的声明
UPROPERTY ( BlueprintAssignable , Category = "SoundFuncs" )
FDspLRValDelegate DspLRVals ;
这样一来,就可以在 C++ 需要调用这个代理的地方进行 调用 了,例如在某个数据生成的地方。
AMyGameState * tags = Cast<AMyGameState>( SL_Contex.LC_cGameState ) ;
if ( tags )
tags->DspLRVals.Broadcast( tfLval, tfRval ) ;
之后,就可以在蓝图中向这个多播代理 绑定事件 来获得生成的数据了
总结
事件调度器的机制在逻辑实现中非常的方便,尤其是在关卡设计中,可能会比较经常用到。使用中也没有遇到什么特别需要注意的地方,逻辑很单纯。