Appearance
代理
代理,帮助我们解决一对一或是一对多的任务分配工作,主要解决通知方面的问题。通过代理完成调用某一个对象的一个函数,而不直接持有该对象的任何指针。
单播代理仅通知一人
多播代理可通知多人
动态代理可被序列化(表现在与蓝图交互,C++中可将通知事件进行蓝图广播)
代理要用到绑定函数。这里提前讲一下:
方法 | 说明 |
---|---|
BindUObject | 绑定UObject类型对象成员函数的代理 |
BindSP | 绑定基于共享引用的成员函数代理 |
BindRaw | 绑定原始定义自定义对象成员函数的代理,操作调用需要注意执行需要检查IsBound |
BindStatic | 绑定全局函数成为代理 |
UnBind | 解除绑定代理关系 |
注意 绑定中传递的对象类型必须和函数指针所属类的类型相同,否则绑定会报错 GmDel.BindUObject(act, &AMyActor::Say);
绑定完成后要调用。调用有两种方法:Execute,ExecuteIfBound。
如果用前一种(Execute),则要先使用IsBound检查当前是否存在有效代理绑定。
如果用后一种,要注意,有返回类型的回调函数无法使用此函数执行回调。
GmDel.ExecuteIfBound(); GmDel.Execute();
总体来讲,代理的构建步骤如下:
- 通过宏进行声明代理对象类型(根据回调函数选择不同的宏)
- 使用代理类型进行构建代理对象
- 绑定回调对象和操作函数
- 执行代理对象回调
单播代理
宏构建,只绑定一个通知对象。
构建宏分两种,一种有返回类型一种没有
cpp
// 构建宏。无返回无参数
DECLARE_DELEGATE(GMDelegateOne)
// 构建宏。有返回单参数。参数从左到右按顺序依次为:返回值类型,代理名称,参数类型
DECLARE_DELEGATE_RetVal_OneParam(int32, CallTestRe, int32)
GMDelegateOne GmDel; // 声明代理
CallTestRe ctr;
// 在cpp中调用
// 先构建一个AMyActor对象并绑定到代理上
AMyActor* my = GetWorld()->SpawnActor<AMyActor>(AMyActor::StaticClass());
// 绑定函数到代理上
GmDel.BindUOjbect(my, &AMyActor::CallBackFun); // CallBackFun是在.h文件中声明的函数
ctr.BindUObject()
// 执行代理调用
GmDel.ExecuteIfBound();
多播代理
无法构建具有返回值的多播代理
DECLARE_MULTICAST_DELEGATE[_Const, _RetVal, etc.](DelegateName)
广播:调用函数Broadcast,但是调用不保证执行顺序
cpp
DECLARE_MULTICAST_DELEGATE_OneParam(DelMulTest, int32&); // 代理名称,参数类型
DelMulTest DelMul;
void CallBackFunMul(int32& num);
// cpp里绑定
AMyActor* my1 = GetWorld()->SpawnActor<AMyActor>(AMyActor::StaticClass());
AMyActor* my2 = GetWorld()->SpawnActor<AMyActor>(AMyActor::StaticClass());
// 绑定函数到代理上
DelMul.AddUObject(my1, &AMyActor::CallBackFunMul); // 用AddUObject去添加到序列中
DelMul.AddUObject(my2, &AMyActor::CallBackFunMul);
// 执行代理
int32 Num = 10;
DelMul.Broadcast(Num);
// 为了能够更加安全,可以先验证绑定是否成功
if(DelMul.IsBound())
{
DelMul.Broadcast(Num);
}
动态代理
允许被序列化,也就是说能够与蓝图交互。
动态代理无法使用带有返回值的函数进行构建(动态单播除外。单播无法在蓝图中绑定,无法使用宏BlueprintAssignable修饰)
注意
动态代理构建类型名称必须用F开头
动态代理对象类型可以使用UPROPERTY标记,其他代理均无法使用(不加的时候,编译可过,调用出错)
动态代理绑定对象的函数需要使用UFUNCTION进行描述(为了跟随代理被序列化)
cpp
// 创建一个动态代理
// DECLARE_DYNAMIC_DELEGATE[_Const, _RetVal, etc.](DelegateName)
// 创建一个动态的多播代理
// DECLARE_DYNAMIC_MULTICAST_DELEGATE[_Const, _RetVal, etc.](DelegateName)
// 构建
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDynDelMul, int32, Num);
DynDelMul DynDel; // 动态多播对象
// 绑定到多播对象上
DynDel.AddDynamic(my1, &AMyActor::CallBackDynMUL);
DynDel.AddDynamic(my2, &AMyActor::CallBackDynMUL);
// cpp中调用
if(DelMul.IsBound())
{
DelMul.Broadcast(Num);
}