四类委托
- 官方步骤: 声明代理、绑定函数到代理、代理调用
单播委托: 绑定单个可调用对象, 支持返回值.
多播委托: 可以绑定多个可调用对象, 实质是维持了一个单播委托的数组, 调用时一个个调用.没有返回值.
事件: 其实就是多播委托, 只是比多播委托多了个friend class OwningType;
动态委托: 同样分为单播和多播. 只能绑定UFUNCTION, 支持序列化, 可在蓝图中使用(UPROPERTY修饰).
委托之间的区别和主要方法
单播委托
- 只能绑定一个回调函数指针的委托,也只会触发一次。
- 绑定函数:BindSataic、BindLambda、BindUFunction
- 执行方面函数:ExecuteIfBound、IsBound、Unbind
单播委托Demo
- 1 UObject中的声明委托和定义,以及SelfDelegateCallback
// 声明两个委托
DECLARE_DELEGATE(FMyDelegate);
DECLARE_DELEGATE_OneParam(FMyDelegateWithRetValue, int32);
class UTestObject : public UObject
{
GENERATED_BODY()
public:
FMyDelegate MyDelegate;
FMyDelegateWithRetValue MyDelegateWithRetValue;
void TriggerDelegate();
UFUNCTION()
// 绑定到自身的委托回调
void SelfDelegateCallback(int32 var)
{
UE_LOG(LogTemp,Warning,TEXT("SelfDelegate Callback :%d"), var);
}
- 2 绑定lambda函数、UFunction 和 全局函数 触发委托和解绑
// 构造对象 绑定委托和触发委托
UTestObject* MyObj = NewObject<UTestObject>();
// BindLambda绑定
MyObj->MyDelegate.BindLambda([]() {
// TriggerDelegate 会导致处理委托
UE_LOG(LogTemp, Warning, TEXT("FMikeTest1::RunTest Delegate triggered!"));
});
// 直接执行
MyObj->MyDelegate.ExecuteIfBound();
// 绑定 到对象成员函数(必须有UFUNCTION()宏)
MyObj->MyDelegate1P.BindUFunction(MyObj, FName("SelfDelegateCallback"));
MyObj->MyDelegate1P.ExecuteIfBound(1);
if(MyObj->MyDelegate1P.IsBound())
{
MyObj->MyDelegate1P.Unbind();
}
// 绑定 全局函数
MyObj->MyDelegate1P.BindStatic(Delegate1PCallback);
MyObj->MyDelegate1P.ExecuteIfBound(2);
// 全局函数的委托回调
void Delegate1PCallback(int32 var)
{
UE_LOG(LogTemp,Warning,TEXT("Delegate1PCallback Param :%d"), var);
}
多播委托
// 多播委托 不可以有返回值,不然用谁的返回值呢?
DECLARE_MULTICAST_DELEGATE_OneParam(FMyMultDelegate1P, int32);
// 多播(不可以有返回值,不然用谁的返回值呢?)
FMyMultDelegate1P MyMultDelegate1P;
- 2 添加回调触发函数 全局函数 成员函数 和 Lambda函数
UTestObject* pUObject = NewObject<UTestObject>();
// 1 BindLambda绑定
pUObject->MyMultDelegate1P.AddLambda([](int32 n) {
UE_LOG(LogTemp,Warning,TEXT("From:BindLambda Callback :%d"), n);
});
// 2 绑定全局函数 第二次移除
FDelegateHandle Handle = pUObject->MyMultDelegate1P.AddStatic(Delegate1PCallback);
// 3 绑定到对象成员函数(必须有UFUNCTION()宏)
pUObject->MyMultDelegate1P.AddUFunction(pUObject, FName("SelfDelegateCallback"));
- 3 广播、移除 和 清空
- FDelegateHandle Handle此句柄用来移除时需要
// 广播
if(pUObject->MyMultDelegate1P.IsBound())
{
pUObject->MyMultDelegate1P.Broadcast(666);
// 通过句柄 移除全局函数回调
pUObject->MyMultDelegate1P.Remove(Handle);
pUObject->MyMultDelegate1P.Broadcast(666);
// 删除pUObject对象上的回调SelfDelegateCallback
pUObject->MyMultDelegate1P.RemoveAll(pUObject);
pUObject->MyMultDelegate1P.Broadcast(666); // 余下Lambda
}
动态多播委托
- 动态多播用法类似多播委托
- 可支持蓝图的回调.
- AddDynamic绑定的方法得被UFUNCTION标记,否则绑定无效
- 代理对象用UPROPERTY标记,并设置BlueprintAssignable,暴露给蓝图使用
// 动态多播:支持在蓝图中使用,类似EventDispatcher
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDynamicMulticastDelegate1P, int32, num);
// 动态多播
UPROPERTY(BlueprintAssignable) // 添加此标记,蓝图才可用
FDynamicMulticastDelegate1P MyDynamicDe1P;
// 动态多播委托 支持蓝图里回调
if(1)
{
UTestObject* pUObject = NewObject<UTestObject>();
// 只能绑定到对象成员函数(必须有UFUNCTION()宏)
pUObject->MyDynamicDe1P.AddDynamic(pUObject, &UTestObject::SelfDelegateCallback);
// 广播
if(pUObject->MyDynamicDe1P.IsBound())
{
pUObject->MyDynamicDe1P.Broadcast(1);
// 解除指定
pUObject->MyDynamicDe1P.RemoveDynamic(pUObject, &UTestObject::SelfDelegateCallback);
pUObject->MyDynamicDe1P.Broadcast(2);
pUObject->MyDynamicDe1P.Clear(); // 全部解绑
pUObject->MyDynamicDe1P.Broadcast(3);
}
}
UOBject的事件
- 底层实现是一个多播委托 Multicast Delegate。
- 只能够通过声明它的对象来BoardCast、IsBound、Clear
- 传进来的OwningType其实就是绑定的ClassType,声明为它的友元类,这样一来这个OwningClass就对这个Event的成员有完全Public的访问权限。
- 通常用法:将Event定义于类内,设为私有,类外通过公开的访问接口进行绑定,触发,解绑,
- 这种方式起到了保护隐私的作用
// OwingType:拥有此Event的类,本例中使用本类:UTestObject
DECLARE_EVENT_OneParam(UTestObject, FMyEvent, int32);
//公开对Event对象的访问接口
FMyEvent& GetEvent() { return DelegateEvent; }
//将Event设为私有,防止类外直接访问到,起到安全作用
private:
FMyEvent DelegateEvent;
- 通过把Evnet绑定在对象上,声明为它的友元类
- 来达到 只能通过对象来BoardCast、IsBound、Clear的封装性
// Evnet事件(绑定在某对象上)
if(1)
{
UTestObject* pUObject = NewObject<UTestObject>();
// 1 BindLambda绑定
pUObject->GetEvent().AddLambda([](int32 n) {
UE_LOG(LogTemp, Warning, TEXT("From:BindLambda Callback :%d"), n);
});
// 2 绑定全局函数
pUObject->GetEvent().AddStatic(Delegate1PCallback);
// 3 绑定到对象成员函数(必须有UFUNCTION()宏)
pUObject->GetEvent().AddUFunction(pUObject, FName("SelfDelegateCallback"));
// 触发广播
if (pUObject->GetEvent().IsBound())
{
pUObject->GetEvent().Broadcast(666);
pUObject->GetEvent().Clear(); // 全清
pUObject->GetEvent().Broadcast(5);
}
}
网友评论