UE C++基础 | 委托与事件

Unreal 委托与代理

关于声明与特点

事件

  • 特点:
    • 只有宣称事件的类才能调用事件的Broadcast, IsBound和Clear方法。
    • 和多播一样,可以绑定多个回调函数。
  • 声明:
DECLARE_EVENT(OwnType, FEventName)DECLARE_EVENT_OneParam(OwnType, FEventName, int32);
DECLARE_EVENT_TwoParams(OwnType, FEventName, int32, float);
DECLARE_EVENT_ThreeParams(OwnType, FEventName, int32, float, bool);
DECLARE_EVENT_FourParams(OwnType, FEventName, ...); // ... 是省略参数类型,不是代码
DECLARE_EVENT_FiveParams(OwnType, FEventName, ...);
DECLARE_EVENT_SixParams(OwnType, FEventName, ...);
DECLARE_EVENT_SevenParams(OwnType, FEventName, ...);
DECLARE_EVENT_EightParams(OwnType, FEventName, ...);
DECLARE_EVENT_NineParams(OwnType, FEventName, ...);
  • 通常用法
// 声明在自己的类中
class AMyActor:public AActor
{
	GENERATED_BODY()
public:
  DECLARE_EVENT_OneParam(ADelegateActor, MyDelegateEvent, int32);
  //公开对Event对象的访问接口
  MyDelegateEvent& OnEventTrigger(){return DelegateEvent;}
  //......
private:
  //将Event设为私有,防止类外直接访问到。
  MyDelegateEvent DelegateEvent;
}
支持的绑定实例类型
AddStatic
AddLambda
AddWeakLambda
AddRaw
AddSP
AddThreadSafeSP
AddUObject
AddUFunction

单播

  • 特点:
    1. 绑定单个可调用对象。
    2. 支持返回值。
    3. 支持参数。
    4. 不支持反射以及序列化。
  • 声明:
// 不带返回值
DECLARE_DELEGATE(FOnMyDelegate);
DECLARE_DELEGATE_OneParam(FOnMyDelegate, int32);
DECLARE_DELEGATE_TwoParams(FOnMyDelegate, int32, float);
DECLARE_DELEGATE_ThreeParams(FOnMyDelegate, int32, float, bool);
DECLARE_DELEGATE_FourParams(FOnMyDelegate, ...); // ... 是省略参数类型,不是代码
DECLARE_DELEGATE_FiveParams(FOnMyDelegate, ...);
DECLARE_DELEGATE_SixParams(FOnMyDelegate, ...);
DECLARE_DELEGATE_SevenParams(FOnMyDelegate, ...);
DECLARE_DELEGATE_EightParams(FOnMyDelegate, ...);
DECLARE_DELEGATE_NineParams(FOnMyDelegate, ...);
// 带返回值
DECLARE_DELEGATE_RetVal(ReturnValueType, FOnMyDelegate);
DECLARE_DELEGATE_RetVal_OneParam(ReturnValueType, FOnMyDelegate, int32);
DECLARE_DELEGATE_RetVal_TwoParams(ReturnValueType, FOnMyDelegate, int32, float);
DECLARE_DELEGATE_RetVal_ThreeParams(ReturnValueType, FOnMyDelegate, int32, float, bool);
DECLARE_DELEGATE_RetVal_FourParams(ReturnValueType, FOnMyDelegate, ...); // ... 是省略,不是代码
DECLARE_DELEGATE_RetVal_FiveParams(ReturnValueType, FOnMyDelegate, ...);
DECLARE_DELEGATE_RetVal_SixParams(ReturnValueType, FOnMyDelegate, ...);
DECLARE_DELEGATE_RetVal_SevenParams(ReturnValueType, FOnMyDelegate, ...);
DECLARE_DELEGATE_RetVal_EightParams(ReturnValueType, FOnMyDelegate, ...);
DECLARE_DELEGATE_RetVal_NineParams(ReturnValueType, FOnMyDelegate, ...);
  • 通常用法
支持的绑定实例类型
BindStatic
BindLambda
BindWeakLambda
BindRaw
BindSP
BindThreadSafeSP
BindUObject
BindUFunction

动态 单播

  • 特点:
    1. 绑定单个可调用对象,需要UFUNCTION()宏修饰绑定函数。
    2. 支持返回值。
    3. 支持参数。
    4. 不支持反射以及序列化。
    5. 动态单播委托在执行时需要实时在类中按照给定的函数名字查找对应的函数,因此执行速度很慢。
  • 声明:
// 不带返回值
DECLARE_DYNAMIC_DELEGATE(FOnMyDelegate);
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnMyDelegate, int32, val_1);
DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnMyDelegate, int32, val_1, float, val_2);
DECLARE_DYNAMIC_DELEGATE_ThreeParams(FOnMyDelegate, int32, val_1, float, val_2, bool, val_3);
DECLARE_DYNAMIC_DELEGATE_FourParams(FOnMyDelegate, ...); // ... 是省略参数类型,不是代码
DECLARE_DYNAMIC_DELEGATE_FiveParams(FOnMyDelegate, ...);
DECLARE_DYNAMIC_DELEGATE_SixParams(FOnMyDelegate, ...);
DECLARE_DYNAMIC_DELEGATE_SevenParams(FOnMyDelegate, ...);
DECLARE_DYNAMIC_DELEGATE_EightParams(FOnMyDelegate, ...);
DECLARE_DYNAMIC_DELEGATE_NineParams(FOnMyDelegate, ...);
// 带返回值
DECLARE_DYNAMIC_DELEGATE_RetVal(ReturnValueType, FOnMyDelegate);
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(ReturnValueType, FOnMyDelegate, int32, val_1);
DECLARE_DYNAMIC_DELEGATE_RetVal_TwoParams(ReturnValueType, FOnMyDelegate, int32, val_1, float, val_2);
DECLARE_DYNAMIC_DELEGATE_RetVal_ThreeParams(ReturnValueType, FOnMyDelegate, int32, val_1, float, val_2, bool, val_3);
DECLARE_DYNAMIC_DELEGATE_RetVal_FourParams(ReturnValueType, FOnMyDelegate, ...); // ... 是省略参数类型,不是代码
DECLARE_DYNAMIC_DELEGATE_RetVal_FiveParams(ReturnValueType, FOnMyDelegate, ...);
DECLARE_DYNAMIC_DELEGATE_RetVal_SixParams(ReturnValueType, FOnMyDelegate, ...);
DECLARE_DYNAMIC_DELEGATE_RetVal_SevenParams(ReturnValueType, FOnMyDelegate, ...);
DECLARE_DYNAMIC_DELEGATE_RetVal_EightParams(ReturnValueType, FOnMyDelegate, ...);
DECLARE_DYNAMIC_DELEGATE_RetVal_NineParams(ReturnValueType, FOnMyDelegate, ...);
  • 通常用法
支持的绑定实例类型
BindUFunction
BindDynamic

多播

  • 特点:
    1. 绑定多个可调用对象。
    2. 不支持返回值。
    3. 支持参数。
    4. 不支持反射以及序列化。
  • 声明:
// 只有无返回值
DECLARE_MULTICAST_DELEGATE(FOnMyDelegate);
DECLARE_MULTICAST_DELEGATE_OneParam(FOnMyDelegate, int32);
DECLARE_MULTICAST_DELEGATE_TwoParams(FOnMyDelegate, int32, float);
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnMyDelegate, int32, float, bool);
DECLARE_MULTICAST_DELEGATE_FourParams(FOnMyDelegate, ...); // ... 是省略参数类型,不是代码
DECLARE_MULTICAST_DELEGATE_FiveParams(FOnMyDelegate, ...);
DECLARE_MULTICAST_DELEGATE_SixParams(FOnMyDelegate, ...);
DECLARE_MULTICAST_DELEGATE_SevenParams(FOnMyDelegate, ...);
DECLARE_MULTICAST_DELEGATE_EightParams(FOnMyDelegate, ...);
DECLARE_MULTICAST_DELEGATE_NineParams(FOnMyDelegate, ...);
  • 通常用法
支持的绑定实例类型
AddStatic
AddLambda
AddWeakLambda
AddRaw
AddSP
AddThreadSafeSP
AddUObject
AddUFunction

动态 多播

  • 特点:
    1. 绑定多个可调用对象,
    2. 在蓝图分配中分配时,使用UFUNCTION(BlueprintAssignable)宏修饰绑定函数。
    3. C++中使用时,使用 UFUNCTION()宏修饰绑定函数。
    4. 不支持返回值。
    5. 支持参数。
    6. 支持反射以及序列化。
  • 声明:
// 只有无返回值
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnMyDelegate);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMyDelegate, int32);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnMyDelegate, int32, val_1, float, val_2);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnMyDelegate, int32, val_1, float, val_2, bool, val_3);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FOnMyDelegate, ...); // ... 是省略参数类型,不是代码
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams(FOnMyDelegate, ...);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_SixParams(FOnMyDelegate, ...);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_SevenParams(FOnMyDelegate, ...);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_EightParams(FOnMyDelegate, ...);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_NineParams(FOnMyDelegate, ...);
  • 通常用法
支持的绑定实例类型
AddDynamic
AddUniqueDynamic

线程安全 多播

  • 声明:
DECLARE_TS_MULTICAST_DELEGATE(FOnMyDelegate);
DECLARE_TS_MULTICAST_DELEGATE_OneParam(FOnMyDelegate, int32);
DECLARE_TS_MULTICAST_DELEGATE_TwoParams(FOnMyDelegate, int32, float);
DECLARE_TS_MULTICAST_DELEGATE_ThreeParams(FOnMyDelegate, int32, float, bool);
DECLARE_TS_MULTICAST_DELEGATE_FourParams(FOnMyDelegate, ...); // ... 是省略参数类型,不是代码
DECLARE_TS_MULTICAST_DELEGATE_FiveParams(FOnMyDelegate, ...);
DECLARE_TS_MULTICAST_DELEGATE_SixParams(FOnMyDelegate, ...);
DECLARE_TS_MULTICAST_DELEGATE_SevenParams(FOnMyDelegate, ...);
DECLARE_TS_MULTICAST_DELEGATE_EightParams(FOnMyDelegate, ...);
DECLARE_TS_MULTICAST_DELEGATE_NineParams(FOnMyDelegate, ...);
  • 通常用法
支持的绑定实例类型
AddStatic
AddLambda
AddWeakLambda
AddRaw
AddSP
AddThreadSafeSP
AddUObject
AddUFunction

关于如何绑定

前缀Bind、前缀Add

  • 首先非动态委托
  • Bind + ...用于绑定单播委托。
  • Add + ...用于绑定多播的委托或事件。
BindStatic、AddStatic
  • 用于绑定于类的静态函数。
// 单播
MyDelegate.BindStatic(&UMyObject::OnMyDelegateStaticFunc);
// 多播
MyDelegate.AddStatic(&UMyObject::OnMyDelegateStaticFunc);
BindLambda、AddLambda
  • 是用于绑定Lambda函数。
  • lambda表达式的说明:
    • [] - 没有任何函数对象参数。
    • [=] - 函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
    • [&] - 函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是引用传递方式(相当于是编译器自动为我们按引用传递了所有局部变量)。
    • [this] - 函数体内可以使用 Lambda 所在类中的成员变量。
  • lambda允许捕捉对象的this指针,但是当多线程处理或者离开作用域等原因,对象的生命期已经结束的情况下,还继续访问lambda函数就会可能会造成比较严重的问题。
// 单播
MyDelegate.BindLambda([this]() { MyFunction(); });
// 多播
MyDelegate.AddLambda([this]() { MyFunction(); });
BindWeakLambda、AddWeakLambda
  • 是用于绑定Lambda函数。
  • 方法需要要在UObject类中使用,非继承自U类的是不能使用的,绑定Lambda表达式并且是持有UObject对象的弱引用。
  • 定时器绑代理的时候绑Lambda, 结果this可能是野指针, 如果this无效不会执行lambda。
// 单播
MyDelegate.BindWeakLambda(this, [this]() { MyFunction(); });
// 多播
MyDelegate.AddWeakLambda(this, [this]() { MyFunction(); });
BindRaw、AddRaw
  • 绑定原始C++指针委托。
  • 如果删除了对象,则调用此函数可能不安全。
// 单播
MyClass* NewClass = new MyClass();
MyDelegate.BindRaw(NewClass, &NewClass::MyFunction)
// 多播
MyClass* NewClass = new MyClass();
MyDelegate.AddRaw(NewClass, &NewClass::MyFunction)
BindSP、AddSP
  • 是用于绑定基于指针的共享成员函数委托。
// 单播
TSharedPtr<MyClass, ESPMode::NotThreadSafe> NewClass(new MyClass());
MyDelegate.BindSP(NewClass.ToSharedRef(), &NewClass::MyFunction);
// 多播
TSharedPtr<MyClass, ESPMode::NotThreadSafe> NewClass(new MyClass());
MyDelegate.AddSP(NewClass.ToSharedRef(), &NewClass::MyFunction);
BindThreadSafeSP、AddThreadSafeSP
  • 是用于绑定基于指针的线程安全的共享成员函数委托。
// 单播
TSharedPtr<MyClass, ESPMode::ThreadSafe> NewClass(new MyClass());
MyDelegate.BindThreadSafeSP(NewClass.ToSharedRef(), &NewClass::MyFunction);
// 多播
TSharedPtr<MyClass, ESPMode::ThreadSafe> NewClass(new MyClass());
MyDelegate.AddThreadSafeSP(NewClass.ToSharedRef(), &NewClass::MyFunction);
BindUFunction、AddUFunction
  • 是通过函数名来绑定的。
// 单播
MyDelegate.BindUFunction(this,"FunctionName");
// 多播
MyDelegate.AddUFunction(this,"FunctionName");
BindUObject、AddUObject
  • 绑定到基类为UObject对象上的某个函数。
// 单播
MyObject->MyDelegate.BindUObject(this, &ThisClass::MyFunction);
// 多播
MyObject->MyDelegate.AddUObject(this, &ThisClass::MyFunction);

绑定动态

  • 当委托是动态委托使用以下方式绑定。
BindDynamic
  • 绑定动态单播时使用。
AddDynamic
  • 绑定动态多播时使用。
AddUniqueDynamic
  • 绑定动态多播时使用,增加代理去重功能。
  • 如下:情况A调用两次,情况B调用一次。
// 当调用:OnEvent.Broadcast();

// 情况 A:
MyClass->OnEvent.AddDynamic(this, &AMyClassManager::OnEvent);
MyClass->OnEvent.AddDynamic(this, &AMyClassManager::OnEvent);

// 情况 B:
MyClass->OnEvent.AddUniqueDynamic(this, &AMyClassManager::OnEvent);
MyClass->OnEvent.AddUniqueDynamic(this, &AMyClassManager::OnEvent);

关于如何解除绑定

FDelegateHandle

  • 委托句柄的声明
FDelegateHandle DelegateHandle;
  • 委托句柄的赋值
// 当添加委托对象时会返回此委托对象的句柄,可通过Remove移除。
DelegateHandle = MyObject->MyDelegate.AddUObject(this, &ThisClass::MyFunction);

UnBind

  • 移除单播、或动态单播的绑定。
MyDelegate.Unbind();

Remove | RemoveAll

  • 移除多播、或动态多播的绑定。
MyObject->MyDelegate.Remove(this, &ThisClass::MyFunction); //解除绑定针对某个函数
MyObject->MyDelegate.Remove(DelegateHandle);              //解除绑定针对某个委托句柄
MyObject->MyDelegate.RemoveAll();                         //解除所有绑定

Clear

  • 清空全部绑定。
MyObject->MyDelegate.Clear();  

关于如何调用

IsBound

  • 判断是否绑定了指针
MyDelegate.IsBound();

Execute | ExecuteIfBound

  • 执行委托,用于单播
MyDelegate.ExecuteIfBound(); 
MyDelegate.Execute();        // Execute如果在委托绑定无效的函数指针的情况下就执行会报错,所以ExecuteIfBound更安全。

BroadCast

  • 向外广播,用于多播
MyDelegate.Broadcast();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Flame老唐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值