前言
代理可以解决一对一或一对多的任务分配工作,还可以解决通知问题
通过代理完成调用某一个对象的一个函数,而不直接持有该对象的任何指针
要调用某个函数,但并不直接去调用,而是通过另一个入口去调用,这就是代理
代理分为:
单播代理(只能进行通知一个人)
多播代理(可以进行多人通知)
动态代理(可以被序列化,体现在可与蓝图进行交互,C++中可以将通知事件进行蓝图广播)
提示:以下是本篇文章正文内容,下面案例可供参考
一、单播代理
单播代理只能绑定一个通知对象,无法进行多个对象通知
通过宏进行构建,分为两种:
1.有返回类型
2.没有返回类型
常用绑定函数:
1.BindUObject:绑定UObject类型对象成员函数的代理
2.BindSP:绑定基于共享引用的成员函数代理
3.BindRaw:绑定原始自定义对象成员函数的代理,操作调用需要注意执行需要检查IsBound
4.BindStatic:绑定全局函数成为代理
5.UnBind:解除绑定代理关系
6.绑定中传递的对象类型必须和函数指针所属类的类型相同,否则绑定会报错
调用执行:
1.执行Execute函数之前,需要检查是否存在有效绑定使用函数 IsBound
2.Execute 调用代理通知,不安全
3.ExecuteIfBound 调用代理通知,安全,但是有返回类型的回调函数无法使用此函数执行回调
4.IsBound 检查当前是否存在有效代理绑定
构建步骤:
1.通过宏进行声明代理对象类型(根据回调函数选择不同的宏)
2.使用代理类型进行构建代理对象
3.绑定回调对象、操作函数
4.执行代理对象回调
//(在.h文件中)
//1.构建单播代理(此例以无参无返单播代理为例)
//① 单播代理:无参数无返回值单播代理
DECLARE_DELEGATE(CallTest)
//② 1个参数的单播代理
DECLARE_DELEGATE_OneParam(Delegate_OneP, int32)
//③ 2个参数的单播代理
DECLARE_DELEGATE_TwoParams(Delegate_TwoP, int32, int32)
//④ 有返回值,和2个参数的单播代理
DECLARE_DELEGATE_RetVal_TwoParams(float, Delegate_RTwoP, float, float)
UCLASS(config=Game)
class AUECCharacter : public ACharacter
{
GENERATED_BODY()
public:
//2. 声明无参无返的单播代理
CallTest Dnop;
//3.创建要绑定到无参无返的单播代理上的函数
void Func();
virtual void BeginPlay();
};
//(在.cpp文件中)
void AUECCharacter::Func()
{
UE_LOG(LogTemp, Log, TEXT("---我是无参无返的单播代理!---"));
}
void AUECCharacter::BeginPlay()
{
Super::BeginPlay();
//4.将Func函数绑定到单播代理
Dnop.BindUObject(this, &AUECCharacter::Func);
//5.判断单播代理是否绑定
if (Dnop.IsBound())
{
//6.调用代理,执行绑定的函数
Dnop.Execute();
}
}
二、单播代理
无法构建具有返回值的多播代理,只能构建参数
广播
调用函数Broadcast,但是调用不保证执行顺序的正确性
构建步骤:
1.使用宏构建代理类型
2.使用代理类型构建多播代理对象
3.添加绑定代理
4.执行调用
//(在.h文件中)
//1.构建多播代理(不可以构建有返回值的)
//① 无参的多播代理
DECLARE_MULTICAST_DELEGATE(Delegate_MultiNoP)
//② 单播代理:有2个参数的单播代理
DECLARE_MULTICAST_DELEGATE_TwoParams(Delegate_MultiTwoP, int32, int32)
UCLASS(config=Game)
class AUECCharacter : public ACharacter
{
GENERATED_BODY()
public:
//2. 声明多播代理
Delegate_MultiNoP MultiNoP;
Delegate_MultiTwoP MultiTwoP;
//3.创建要绑定到无参无返的单播代理上的函数
void Func1_MultiNoP();
void Func2_MultiNoP();
void Func1_MultiTwoP(int32 A, int32 B);
void Func2_MultiTwoP(int32 C, int32 D);
virtual void BeginPlay();
};
//(在.cpp文件中)
void AUECCharacter::Func1_MultiNoP()
{
UE_LOG(LogTemp, Log, TEXT("---------我是无参的多播代理Func1_MultiNoP()!---------"));
}
void AUECCharacter::Func2_MultiNoP()
{
UE_LOG(LogTemp, Log, TEXT("---------我是无参的多播代理Func2_MultiNoP()!---------"));
}
void AUECCharacter::Func1_MultiTwoP(int32 A, int32 B)
{
UE_LOG(LogTemp, Log, TEXT("---------我是有2个int参AB的多播代理Func1_MultiTwoP!---------"));
}
void AUECCharacter::Func2_MultiTwoP(int32 C, int32 D)
{
UE_LOG(LogTemp, Log, TEXT("---------我是有2个int参CD的多播代理Func1_MultiTwoP!---------"));
}
void AUECCharacter::BeginPlay()
{
Super::BeginPlay();
//4.将多个函数绑定到多播代理
MultiNoP.AddUObject(this, &AUECCharacter::Func1_MultiNoP);
MultiNoP.AddUObject(this, &AUECCharacter::Func2_MultiNoP);
MultiTwoP.AddUObject(this, &AUECCharacter::Func1_MultiTwoP);
MultiTwoP.AddUObject(this, &AUECCharacter::Func2_MultiTwoP);
//5.判断多播代理是否绑定
if (MultiNoP.IsBound())
{
//6.调用多播代理,执行绑定的函数
MultiNoP.Broadcast();
}
//5.判断多播代理是否绑定
if (MultiTwoP.IsBound())
{
//6.调用多播代理,执行绑定的函数
MultiTwoP.Broadcast(2,3);
}
//清空所有绑定函数
MultiNoP.Clear();
//移除单绑定,需要传递 FDelegateHandle(代理句柄)
FDelegateHandle DH_Fun = MultiTwoP.AddUObject(this, &AUECCharacter::Func1_MultiTwoP);
MultiTwoP.Remove(DH_Fun);
//移除某个对象中的所有函数绑定
MultiTwoP.RemoveAll(this);
}
三、动态代理
是允许被序列化的数据结构(代理可以被数据化提供给蓝图进行使用),使得可以在.cpp中调用代理广播,并将事件通知到蓝图
UE中的大部分通知事件均使用动态代理,方便蓝图操作(如碰撞通知)
动态代理无法使用带有返回值的函数进行构建
动态代理分为
动态单播(但是创建动态单播还不如创建普通的多播,单播无法在蓝图中绑定,无法使用宏BlueprintAssignable修饰)
动态多播
动态代理与上面单播多播的区别:
动态代理的类型名称需要用 F 开头(动态代理实现了机制构建类)
动态代理对象类型可以使用UPROPERTY标记;其他代理均无法使用(不加编译可过,调用就会出错)
动态代理绑定对象的函数需要使用UFUNCTION进行描述(因为需要跟随代理被序列化)
构建步骤
通过宏进行声明代理对象类型(根据回调函数选择不同的宏)
使用代理类型进行构建代理对象
绑定回调对象、操作函数
执行代理对象回调
总结
以上就是今天要讲的内容,本文仅仅简单介绍了虚幻引擎中的代理说明使用。