UE4/5C++:Delegate(委托or代理?)的使用

目录

DECLARE的使用

单播:

绑定UObject

绑定

调用

无参调用

解除绑定:

绑定Lambda表达式:

绑定c++原生的c++类的函数:

绑定共享指针:

绑定静态函数:

绑定线程安全的共享指针:

绑定一个Function方法:

多播

动态单播代理:

 用在蓝图上:

在c++中如何绑定:

 动态多播代理

 用在蓝图上:

​编辑

c++内绑定:


Delegate有的人说是委托,有的人说是代理。
虚幻引擎中的Delegate通常被翻译为“委托”,但它实际上更接近于C#中的“代理”。在虚幻引擎中,Delegate是一种允许多个函数指针被存储和调用的类型。

虚幻引擎中的Delegate可以分为多播代理(Multicast Delegate)和单播代理(Unicast Delegate)两种类型。

单播代理只能存储一个函数指针,当Delegate被调用时,只会调用该指针所指向的函数。

多播代理则可以存储多个函数指针,当Delegate被调用时,会调用存储的每个函数指针。多播代理还可以使用加法运算符(+=)和减法运算符(-=)来添加或移除函数指针。

【但是多播代理绑定的函数执行是不固定的】

值得注意的是多播代理是没有返回值的。

因此,区别在于单播代理只能存储一个函数指针,而多播代理可以存储多个,并且可以进行添加或移除操作。多播代理常用于实现事件和回调函数的多个注册和注销,而单播代理则常用于只需要单个函数指针的情况。

DECLARE的使用

第一步我们先创建一个简单的Actor类,在有了头文件和cpp文件之后,我们就可以在里面输入这些宏了:

首先是

单播:

绑定UObject

绑定自UObject类的类里面的成员函数

绑定

如图所示 :这就是一个简单的单播代理,单播只能绑定一个委托函数,所绑定的委托函数可以有返回值,也可以没有返回值。 静态委托执行前最好检查是否绑定,否则会导致程序崩溃,如果重复进行绑定,会覆盖上一次的绑定

基本上都是一样的格式,如果有返回值的,则需要将返回值写在最前面:

 看一下cpp文件是如何实现绑定的:

首先是对函数testBind的实现,然后是在beginplay中绑定

绑定时候的参数填写:

	//第一个参数是绑定的方法是哪个类的,因为是在自身所以写this
	//第二个参数就是要绑定的函数,要使用&(引用符号),因为这里传入的是函数指针
	DelegateRetValOneparam.BindUObject(this, &AMyActor::testBind);

这样子就绑定好了,那么该如何调用呢?

调用

在要调用的地方输入下面这个即可 ,比如我在beginplay中这样调用:

if (DelegateRetValOneparam.IsBound())//判断是否绑定
	{
        //输入的是float:10.5【因为这里我绑定的函数要输入值】
		DelegateRetValOneparam.Execute(10.5);
	}

如果学会了上面的操作,那么其他的其实都是一模一样的方法。

无参调用

好了,这样子就调用完毕了,当然如果是无参数的,那么只需要这样即可:

 这里作者并没有进行绑定,但是可以看到ExecuteIfBound(),这个的意思就是上面的如果你绑定了就执行结合了起来(不过这个不能有输入和返回值)。

解除绑定:

在最后写个这个即可。

DelegateRetValOneparam.Unbind();

绑定Lambda表达式:

之前我们讲了正常的绑定,接下来就要讲解对Lambda表达式的绑定:

想必学过lambda表达式的懂的都懂(多的就不讲了):

这样子就做好了一个简单的对lambda表达式的绑定了

绑定c++原生的c++类的函数:

就是说自己做了一个c++类,而不是继承虚幻引擎的类,然后绑定里面的函数:

class FTest
{
public:
	int32 testA(float a)
	{
		return 0;
	}
};
// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
	Super::BeginPlay();

	FTest pTest;
	DelegateRetValOneparam.BindRaw(&pTest, &FTest::testA);

	if (DelegateRetValOneparam.IsBound())
	{
		DelegateRetValOneparam.Execute(10.5);
	}
	//DelegateNo.ExecuteIfBound();
}

绑定共享指针:

 方法都差不多:

绑定静态函数:

如过是在某个类里面的静态函数,和之前的一样,是这样的-> &类的名字::函数名字

绑定线程安全的共享指针:

和绑定共享指针差不多,只不过要做一个更改:

绑定一个Function方法:

里面涉及到了反射,所以在头文件里面,对要绑定的函数,需要做一个UFUNCTION。

多播

多播代理是没有返回值的

//多播代理
DECLARE_MULTICAST_DELEGATE(FTestMulticastDelegateNoparma);
DECLARE_MULTICAST_DELEGATE_OneParam(FTestMulticastDelegateOneparma,float);

和单播代理的一样,放在头文件的类里面

然后在cpp中实现:

值得一提的是我们需要将函数做一个没有返回值的函数,不然是无法添加的:

绑定和调用就如此简单。

	//多播绑定
	MulticastDelegateOneparma.AddUObject(this, &AMyActor::testBind);
	//调用
	MulticastDelegateOneparma.Broadcast(5.2);

动态单播代理:

 用在蓝图上:

动态单播代理 必须以F开头,否则报错

一定要加UFUNCTION,因为他是要在蓝图中暴露的,否则报错

它和上面差不多,好处是可以暴露到蓝图中去使用:

//动态单播代理 必须以F开头,否则报错 相对较慢,耗性能
DECLARE_DYNAMIC_DELEGATE(FTestDynamicDelegate);
//动态代理的参数需要取参数名 因为他们在蓝图中使用需要名字
DECLARE_DYNAMIC_DELEGATE_OneParam(FTestDynamicDelegateOneparam,float,a);
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(int32,FTestDynamicDelegateRetValOneparam,float,a);

 在头文件中这样写:

//动态单播代理,这样就可以暴露到蓝图中去使用
	UFUNCTION(BlueprintCallable)
	void testDYOne(FTestDynamicDelegateRetValOneparam DYDRVOneParam);

 然后我们可以去蓝图中看看是什么情况:这是在蓝图中绑定

在c++中如何绑定:

和之前的绑定方法是一样的 

 动态多播代理

 用在蓝图上:

c++内绑定:

 

猜你喜欢

转载自blog.csdn.net/q244645787/article/details/129874760