UE5--浅析委托原理(Delegate)

委托概述

委托是一种用于事件处理的机制。通过使用委托,可以将一个或多个函数绑定到一个事件上,在事件触发时自动调用这些函数。代理也叫做委托,比如:跳,跑,开枪,伤害等响应,就是注册一个委托回调,其作用就是提供一种消息机制,都知道消息的传递需要发送方和接收方,而代理的过程也可分为这两大部分,我们可以换个名字分别叫做:触发点和执行点,这就是代理的主要部分,记住这个两个点就能记住代理原理。这里面也有很多的类型擦除,类型还原,还有函数签名转换。

委托种类

委托的使用

三个步骤:

1.声明委托代理

2.绑定函数到代理上

3.代理的调用

单播

cpp 复制代码
DECLARE_DELEGATE( FSimpleDelegate ); // 无参、无返回值
DECLARE_DELEGATE_OneParam(FPakEncryptionKeyDelegate, uint8[32]); // 1个参数、无返回值
DECLARE_DELEGATE_TwoParams(FPakSigningKeysDelegate, TArray<uint8>&, TArray<uint8>&); // 2个参数、无返回值
DECLARE_DELEGATE_RetVal_ThreeParams(bool, FOnMountPak, const FString&, int32, IPlatformFile::FDirectoryVisitor*); // 3个参数、bool返回

声明定义单播可以有参数和无参数

单播代理委托,指的是只能绑定一个函数指针的委托,实现一对一的通知。

单播调用方式为 ExecuteIfBound()

单播删除方式为 Unbind()

单播绑定方法为 Bind...(如 BindStatic,BindRaw,BindUObject等)

多播

cpp 复制代码
//多播委托
DECLARE_MULTICAST_DELEGATE(DelegateName);
DECLARE_MULTICAST_DELEGATE_ONEPARAM(DelegateName, Param1Type);
DECLARE_MULTICAST_DELEGATE_XXXPARAMS(DelegateName, Param1Type,...);

多播代理委托,指的是能绑定多个函数指针的委托,实现一对多的通知。

多播调用方式为 BroadCast()

多播的删除方式为 Remove(),RemoveAll()

多播绑定方式为 Add...(如 AddUObject...);

注意

1.只要动态多播才可以被蓝图绑定,通过宏定义BlueprintAsignable

2.看是否有返回值,通过关键字"RetVal",只有单播委托和动态单播委托,才有返回值。

3.多播委托和单播委托都支持多参数传入,最多9个参数

4.委托的开头必须用F,否则无法编译

5.动态委托可以序列化,通过名称查找函数。

动态委托案例

下面是我用来学习动态委托的一个小案例,让自己更清楚的看见委托的使用与过程

新建两个C++对象

然后拖入场景,一下是两个Actor的代码

MyActorA

.h

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActorA.generated.h"

/*
* 让A进行对B的调用,我们就需要在A中声明委托类型
* 我们这里测试动态多播参数
* 必须使用F开头的
*/
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDongTaiDuoBo,bool,OkorNotOk);


UCLASS()
class HOTREPLACE_API AMyActorA : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AMyActorA();

	UPROPERTY(BlueprintAssignable)
	FDongTaiDuoBo DongTaiDuoBo;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	//用来执行触发委托
	UFUNCTION(BlueprintCallable)
	void execute(bool ifSuccess);

};

.cpp

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.


#include "MyActorA.h"

// Sets default values
AMyActorA::AMyActorA()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AMyActorA::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AMyActorA::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AMyActorA::execute(bool ifSuccess)
{
    //这里用来触发委托
    DongTaiDuoBo.Broadcast(ifSuccess);
}

MyActorB

.h

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActorB.generated.h"

UCLASS()
class HOTREPLACE_API AMyActorB : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AMyActorB();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	/*
	* 这里来调用A里面的委托
	* 现在写一个被委托的函数
	*/

	UFUNCTION(BlueprintCallable)
	void Bexecute(bool ifSuccess);
};

.cpp

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.


#include "MyActorB.h"
#include "MyActorA.h"
#include "Kismet\GameplayStatics.h"
// Sets default values
AMyActorB::AMyActorB()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AMyActorB::BeginPlay()
{
	Super::BeginPlay();

	/*
	* 在场景中寻找A
	*/
	TArray<AActor*>Actors;
	
	UGameplayStatics::GetAllActorsOfClass(GetWorld(),AMyActorA::StaticClass(),Actors);
	//在场景中遍历到我我们需要的ActorB,然后把函数绑定到ActorB上面
	for (auto Actor : Actors)
	{
	    AMyActorA* A=Cast<AMyActorA>(Actor);
		if (A!=nullptr)
		{
		    //把找到的AActor转换成A需要的类
		    A->DongTaiDuoBo.AddDynamic(this,&AMyActorB::Bexecute);
		}
	}
}

// Called every frame
void AMyActorB::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AMyActorB::Bexecute(bool ifSuccess)
{
    if (ifSuccess)
    {
	    UE_LOG(LogTemp,Warning,TEXT("Success"));
    }
	else 
	{
		UE_LOG(LogTemp, Warning, TEXT("NotSuccessnnnnnn"));
	}

}

在关卡蓝图中,进行连连看

MyActorA

测试结果

之后你就会发现我们的动态委托测试成功了。

相关推荐
钟离墨笺2 小时前
【c++】四种类型转换形式
开发语言·c++
汤姆和杰瑞在瑞士吃糯米粑粑3 小时前
【C++学习篇】C++11
开发语言·c++
_extraordinary_3 小时前
C++智能指针的使用
c++·智能指针
zjkzjk77113 小时前
C++ 左值引用 & 右值引用 && std::move()左值改右值 移动构造函数()
开发语言·c++
knowledgebao3 小时前
OHOS(HarmonyOS) 编译 C/C++ 库
c语言·c++·harmonyos
HL_LOVE_C3 小时前
全面理解-c++11中的智能指针
开发语言·c++
KAI77384 小时前
2月10日QT
c++
獨枭5 小时前
在 MFC 应用中集成 WebView2
c++·mfc
Bluesonli6 小时前
第 9 天:UE5 物理系统 & 碰撞检测全解析!
开发语言·学习·游戏·ue5·虚幻·unreal engine
Bluesonli6 小时前
第 10 天:UE5 交互系统,拾取物品 & 触发机关!
学习·游戏·ue5·虚幻·unreal engine