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

测试结果

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

相关推荐
..过云雨7 分钟前
09.【C++】list链表(STL中的列表容器,C++封装的带头双向链表,可实现指定类型的增删查改,迭代器操作等功能)
开发语言·c++
阿巴~阿巴~8 分钟前
C/C++蓝桥杯算法真题打卡(Day6)
c语言·c++·蓝桥杯·动态规划
幼安22911 分钟前
日志统计(C++,模拟,双指针)
开发语言·c++·spring
爱编码的傅同学2 小时前
C++从入门到入土(八)——多态的原理
java·jvm·c++
挺6的还2 小时前
21.多态
c++
心态与习惯2 小时前
c++ 中的可变参数模板与折叠表达式
前端·c++·可变参数模板·折叠表达式
一匹电信狗3 小时前
【Linux我做主】基础命令完全指南上篇
linux·服务器·开发语言·c++·开源·ssh·unix
daily_23333 小时前
coding ability 展开第四幕(滑动指针——巩固篇)超详细!!!!
c++·算法·字符串·哈希算法·滑动窗口
倔强的石头1063 小时前
【C++经典例题】反转字符串中单词的字符顺序:两种实现方法详解
java·c++·算法
enyp804 小时前
C++抽象与类的核心概念解析
java·开发语言·c++