UE4委托

01 委托(代理)

委托,又称代理,本质是一个特殊类的对象,它内部可以储存(一个或多个)函数指针、调用参数和返回值。

委托的作用如同函数指针,但它更安全(支持编译期类型检查),而且更易于使用。

使用委托,通过对委托的一个执行就可以调用到对象的函数。

02 概念

代理:在你不知道对象是什么的时候,也可以执行对象中的函数,delegate代理为两个对象之间建立起了通信,当我需要调用对象中的成员时,可我们不知道对象是谁,这时只需要打电话给这个中介delegate即可。委托的功能类似与蓝图中的发报机。

代理主要有三个特性:绑定、呼叫、解除绑定。

03 UE4支持代理类型

  1. 单播代理:支持绑定单个函数
  2. 多播代理:支持绑定多个函数
  3. 动态代理:可序列化的Uobject

04 单播代理的使用

主要的代理类型有四种:
  • 不带形参,不带返回值
  • 带形参,不带返回值
  • 带返回值,不带形参
  • 带返回值,带形参的
代理创建方式:

虚幻4有着自己定义的一套delegate,需要通过delegate宏创建。

//声明委托 不带形参,不带返回值(它可以绑定的这个函数必须是没有参数也没有返回值的) 
DECLARE_DELEGATE(FDelegateTestA);
//声明委托 带形参,不带返回值,类似的一共有9个宏,最大带9个形参 如:DECLARE_DELEGATE_NineParams
DECLARE_DELEGATE_OneParam(FDelegateTestB,bool);
//声明委托带 带返回值,不带形参
DECLARE_DELEGATE_RetVal(bool,FDelegateTestC);
//声明委托 带返回值,带形参的,类似的一共有9个宏,最大带9个形参 如:DECLARE_DELEGATE_NineParams
DECLARE_DELEGATE_RetVal_OneParam(int32,FDelegateTestD,FString&);

目前虚幻4宏最多可以带9个形参,如:DECLARE_DELEGATE_OneParam一直到DECLARE_DELEGATE_NineParams

单播代理案列:不带参数的代理,绑定C++原生类

绑定UE4对象,后面是绑定的函数

先声明两个类并绑定代理

#include "CoreMinimal.h"
//声明委托
DECLARE_DELEGATE(FDelegateTestA);

//声明ClassA类
class ClassA 
{
    
    
public:
//声明代理
	FDelegateTestA DelegateTestA;
  
//调用代理
	void Eexcute()
	{
    
    
		//调用代理,先判断是否绑定了,绑定上了再执行代理。
		DelegateTestA.ExecuteIfBound();
	}
};

//声明ClassB类
class ClassB 
{
    
    
public:
	//构造函数,绑定代理
	ClassB(ClassA* NewClass_a)
	if (NewClass_a)
	{
    
    
		m_classA = NewClass_a;
		m_classA->DelegateTestA.BindRaw(this, &ClassB::ExecuteA);//绑定事件ExecuteA
        }
	void ExecuteA()
	{
    
    
		Print_F(TEXT("Hello world"));
	}
	//析构函数,解除绑定
	~ClassB()
	{
    
    
		if (m_classA)
		{
    
    
			m_classA->DelegateTestA.Unbind();
			m_classA->Execute();
			delete m_classA;
			m_classA = nullptr;
                 }
private:
	ClassA* m_classA;
};

调用代理

//假设为程序入口
void BeginPlay()
{
    
    
	//创建ClassA指针
	ClassA* NewClassA = new ClassA();
	//创建ClassB指针,构建函数
	ClassB* NewClassB = new ClassB(NewClassA);
	//调用代理Execute(),Execute会调用ClassB中的Execute()A函数
        //NewClassA不知道有对象NewClassB的,存在却可以调用NewClassB的成员
        //代理为ClassA类和ClassB之间建立通信
	NewClassA->Execute();
	//释放指
	delete NewClassB;
	NewClassA = nullptr;
	NewClassB = nullptr;
}

结果

//屏幕会打印“Hello world”,ClassA在不知道对象ClassB情况下调用了ClassB的成员

05 动态代理的使用

动态委托可以序列化,其函数可按命名查找,但其执行速度比常规委托慢。

声明
DECLARE_DYNAMIC_DELEGATE[
绑定
辅助宏 说明
BindDynamic( UserObject, FuncName ) 用于在动态委托上调用BindDynamic()的辅助宏。自动生成函数命名字符串。
执行
执行函数 描述
Execute 不检查其绑定情况即执行一个委托
ExecuteIfBound 检查一个委托是否已绑定,如是,则调用Execute
IsBound 检查一个委托是否已绑定,经常出现在包含 Execute 调用的代码前

06 多播代理的使用

多播委托拥有大部分与单播委托相同的功能。它们只拥有对对象的弱引用,可以与结构体一起使用,可以四处轻松复制等等。
就像常规委托一样,多播委托可以远程加载/保存和触发;但多播委托函数不能使用返回值。它们最适合用来 四处轻松传递一组委托。

事件是一种特殊类型的多播委托,它在访问"Broadcast()"、"IsBound()"和"Clear()"函数时会受到限制。

声明
声明宏 说明
DECLARE_MULTICAST_DELEGATE[_RetVal, ...]( DelegateName ) 创建一个多播委托。
DECLARE_DYNAMIC_MULTICAST_DELEGATE[_RetVal, ...]( DelegateName ) 创建一个动态多播委托。
绑定

多播委托可以绑定多个函数,当委托触发时,将调用所有这些函数。因此,绑定函数在语义上与数组更加类似。

函数 说明
“Add()” 将函数委托添加到该多播委托的调用列表中。
“AddStatic()” 添加原始C++指针全局函数委托。
“AddRaw()” 添加原始C++指针委托。原始指针不使用任何类型的引用,因此如果从委托下面删除了对象,则调用此函数可能不安全。调用Execute()时请小心!
“AddSP()” 添加基于共享指针的(快速、非线程安全)成员函数委托。共享指针委托保留对对象的弱引用。
“AddUObject()” 添加基于UObject的成员函数委托。UObject委托保留对对象的弱引用。
“Remove()” 从该多播委托的调用列表中删除函数(性能为O(N))。请注意,委托的顺序可能不会被保留!
“RemoveAll()” 从该多播委托的调用列表中删除绑定到指定UserObject的所有函数。请注意,委托的顺序可能不会被保留!

"RemoveAll()"将删除绑定到所提供指针的所有已注册委托。切记,未绑定到对象指针的原始委托不会被该函数所删除!

执行

多播委托允许您附加多个函数委托,然后通过调用多播委托的"Broadcast()"函数一次性同时执行它们。多播委托签名不得使用返回值。

在多播委托上调用"Broadcast()"总是安全的,即使是在没有任何绑定时也是如此。唯一需要注意的是,如果您使用委托来初始化输出变量,通常会带来非常不利的后果。

调用"Broadcast()"时绑定函数的执行顺序尚未定义。执行顺序可能与函数的添加顺序不相同。

函数 说明
“Broadcast()” 将该委托广播给所有绑定的对象,但可能已过期的对象除外。

猜你喜欢

转载自blog.csdn.net/qq_41363459/article/details/111466285
UE4