UE4各种代理(委托)使用方法

前言

UE4中有茫茫多的代理类型, 对于初学者刚开始都是一头雾水, 本篇文章逐步分析每一种代理的使用方法

我们先用一个输入整形输入参数的形式,声明所有类型的代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//单播代理
DECLARE_DELEGATE_OneParam(FDlg_1P,int32);
//多播代理
DECLARE_MULTICAST_DELEGATE_OneParam(FDlgMul_1P, int32);
//事件
DECLARE_EVENT_OneParam(AActor,FDlgEvent_1P,int32);
//动态代理
DECLARE_DYNAMIC_DELEGATE_OneParam(FDlgDy_1P, int32, number);
//动态多播代理
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDlgDyMul_1P, int32, number);
//带返回的单播
DECLARE_DELEGATE_RetVal_OneParam(bool,FDlgRet_1P,int32);
//带返回值的动态单播
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(bool, FDlgDyRet_1P, int32, number);
1
2
3
4
5
6
7
8
9
10
		FDlg_1P Dlg_1P;
FDlgMul_1P DlgMul_1P;
FDlgEvent_1P DlgEvent_1P;
FDlgDy_1P DlgDy_1P;
//唯一可以声明为蓝图变量的类型
UPROPERTY(BlueprintAssignable, BlueprintCallable)
FDlgDyMul_1P DlgDyMul_1P;

FDlgRet_1P DlgRet_1P;
FDlgDyRet_1P DlgDyRet_1P;

按使用方式, 一般就是普通的单播代理, 动态代理, 多播代理以及动态多播代理, 每种类型都有无参数很若干参数的版本以及带返回值的版本(多播无返回值);

后续我们也按照蓝图可否使用来区分各个代理

单播代理

  • 声明
1
2
DECLARE_DELEGATE_OneParam(FDlg_1P,int32);
DECLARE_DELEGATE_RetVal_OneParam(bool,FDlgRet_1P,int32);//带返回值
  • 定义
1
2
FDlg_1P Dlg_1P;
FDlgRet_1P DlgRet_1P;
  • 绑定/解绑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Event_FDlg_1P(int32 number);
Dlg_1P.BindUObject(this, &ATestActor::Event_FDlg_1P);
Dlg_1P.Unbind();

bool Event_DlgRet_1P(int32 number);
GetFDlgRet_1P().BindUObject(this, &ATestActor::Event_DlgRet_1P);


//Static函数 // BindStatic
//普通C++对象的成员函数 // BindRaw
//Lambda表达式 // BindLambda // BindWeakLambda
//与某个UObject对象关联的Lambda表达式
//共享引用包裹的普通C++对象的成员函数 // BindSP // BindThreadSafeSP
//线程安全的共享引用包裹的普通C++对象的成员函数
//UObject对象的成员函数 // BindUObject
//UObject对象的UFunction成员函数 // BindUFunction
  • 调用/触发
1
2
3
4
5
Dlg_1P.ExecuteIfBound(number);
if (DlgRet_1P.IsBound())//有返回值
{
return DlgRet_1P.Execute(number);
}

不支持反射以及序列化,可以有返回值,支持Playload参数,可以绑定一个

另外定义的变量无法定义为蓝图变量, 也无法作为参数传递给蓝图;

绑定以后会顶替掉其他绑定的类,即绑定唯一

多播代理/事件

  • 声明/定义
1
2
3
4
DECLARE_MULTICAST_DELEGATE_OneParam(FDlgMul_1P, int32);
DECLARE_EVENT_OneParam(AActor,FDlgEvent_1P,int32);
FDlgMul_1P DlgMul_1P;
FDlgEvent_1P DlgEvent_1P;
  • 绑定/解绑
1
2
3
4
5
6
7
8
9
10
11
12
GetFDlgMul_1P().AddUObject(this, &ATestActor::Event_FDlgMul_1P);
GetFDlgMul_1P().RemoveAll(this);

//Static函数 // AddStddatic
//普通C++对象的成员函数 // AddRaw
//Lambda表达式 // AddLambda // AddWeakLambda
//与某个UObject对象关联的Lambda表达式
//共享引用包裹的普通C++对象的成员函数 // AddSP // AddThreadSafeSP
//线程安全的共享引用包裹的普通C++对象的成员函数
//UObject对象的成员函数 // AddUObject
//UObject对象的UFunction成员函数 // AddUFunction
//也可以创建FDelegate对象,然后调用Add函数
  • 触发/调用
1
DlgMul_1P.Broadcast(number);

不支持反射以及序列化,无返回值,支持Playload参数,可以绑定多个

动态代理

  • 声明/定义
1
2
3
4
DECLARE_DYNAMIC_DELEGATE_OneParam(FDlgDy_1P, int32, number);
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(bool, FDlgDyRet_1P, int32, number);
FDlgDy_1P DlgDy_1P;
FDlgDyRet_1P DlgDyRet_1P;
  • 绑定/解绑
1
2
3
4
5
6
void Event_FDlgDy_1P(int32 number);
GetFDlgDy_1P().BindUFunction(this, TEXT("Event_FDlgDy_1P"));
//GetFDlgDy_1P().BindDynamic(this, &ATestActor::Event_FDlgDy_1P);//宏绑定
GetFDlgDy_1P().Unbind();

//带返回值的类同
  • 触发/调用
1
2
3
4
5
GetFDlgDy_1P().Broadcast(number);
if (DlgDyRet_1P.IsBound())//带返回值
{
return DlgDyRet_1P.Execute(number);
}

支持反射以及序列化,可以有返回值,不支持Playload参数,绑定唯一

另外动态代理支持作为蓝图函数的参数, 如下

1
2
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
bool TestFunction(const FDlgDy_1P& callback_Dy, const FDlgDyRet_1P& callback_DyRet);

UE4Editor_lvL7XrynEG

调用此函数以后也作为唯一绑定而顶替掉原有绑定.

动态多播代理

  • 声明/定义
1
2
3
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDlgDyMul_1P, int32, number);
UPROPERTY(BlueprintAssignable, BlueprintCallable)//唯一可以声明为蓝图变量的
FDlgDyMul_1P DlgDyMul_1P;
  • 绑定/解绑
1
2
3
GetFDlgDyMul_1P().AddDynamic(this, &ATestActor::Event_FDlgDyMul_1P);
GetFDlgDyMul_1P().RemoveDynamic(this, &ATestActor::Event_FDlgDyMul_1P);
//也同样支持Add和AddUnique函数
  • 调用/触发
1
DlgDyMul_1P.Broadcast(number);

如果定义的时候加入了BlueprintAssignable, BlueprintCallable即可以作为蓝图变量, 类似蓝图的Dispatcher的使用

UE4Editor_o15wfc0YJ4

关于Payload

1
2
3
4
5
6
7
8
9
DECLARE_DELEGATE_OneParam(FTestDlg, int);
static void TestPayload(int number, FString txt)
{
UE_LOG(LogTemp, Log, TEXT("TestPayload : %d %s"), number, *txt);
}

FTestDlg TestDlg;
TestDlg.BindStatic(TestPayload, TEXT("Hello"));
TestDlg.ExecuteIfBound(2);