UE4 C++ 代理

简介:委托可以以通用、类型安全的方式调用 C++ 对象的成员函数。委托可以动态绑定到任意对象的成员函数,在将来调用对象上的函数,即使调用者不知道对象的类型。代表可以安全地复制。也可以按值传递,但不推荐这样做,因为这个进程会在堆上分配内存;尽可能通过引用传递代表。引擎支持三种类型的委托:单播代理,多播代理,动态代理。

代理声明:

代理绑定:

代理执行:

单播代理应用:

创建一个C++工程,创建一个C++ 的Actor类

.h文件

.h文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyDeletegate.generated.h"
//声明一个无参数的代理
DECLARE_DELEGATE(DelegateNoParam);
//声明带有一个参数的代理,名称为:DelegateOneParam
DECLARE_DELEGATE_OneParam(DelegateOneParam, FString);
//声明带有两个参数的代理,名称为:DelegateTwoParam
DECLARE_DELEGATE_TwoParams(DelegateTwoParam, FString, int32);
//声明带有三个参数的代理,名称为:DelegateThreeParam
DECLARE_DELEGATE_ThreeParams(DelegateThreeParam, FString, int32, float);
//声明一个带有返回值的代理,名称为
DECLARE_DELEGATE_RetVal(FString, DelegateRetVal);
UCLASS()
class TEST_API AMyDeletegate : public AActor
{
GENERATED_BODY()
public:	
// Sets default values for this actor's properties
AMyDeletegate();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:	
// Called every frame
virtual void Tick(float DeltaTime) override;
//创建一个代理对象
DelegateNoParam noparamDeleta;
DelegateOneParam oneparamDeleta;
DelegateTwoParam twoparamDeleta;
DelegateThreeParam threeparamDeleta;
DelegateRetVal revalparamDelegate;

//代理绑定函数
void noparamDeletaFunc();
void oneparamDeletaFunc(FString str);
void twoparamDeletaFunc(FString str,int32 a);
void threeparamDeletaFunc(FString str,int32 a, float b);
FString revalparamDelegateFunc();

void PrintF(FString str);

};
.cpp文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyDeletegate.h"
// Sets default values
AMyDeletegate::AMyDeletegate()
{
// 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;
//添加绑定函数
noparamDeleta.BindUObject(this, &AMyDeletegate::noparamDeletaFunc);
oneparamDeleta.BindUObject(this,&AMyDeletegate::oneparamDeletaFunc);
twoparamDeleta.BindUObject(this, &AMyDeletegate::twoparamDeletaFunc);
threeparamDeleta.BindUObject(this, &AMyDeletegate::threeparamDeletaFunc);
revalparamDelegate.BindUObject(this, &AMyDeletegate::revalparamDelegateFunc);
}
// Called when the game starts or when spawned
void AMyDeletegate::BeginPlay()
{
Super::BeginPlay();
//在BeginPlay()函数执行绑定
noparamDeleta.ExecuteIfBound();
oneparamDeleta.ExecuteIfBound("111");
twoparamDeleta.ExecuteIfBound("222",5.0);
threeparamDeleta.ExecuteIfBound("333",5.0,1);
FString ValDelegate = revalparamDelegate.Execute();
PrintF(ValDelegate);
}
// Called every frame
void AMyDeletegate::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AMyDeletegate::noparamDeletaFunc()
{
}
void AMyDeletegate::oneparamDeletaFunc(FString str)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, str);
}
void AMyDeletegate::twoparamDeletaFunc(FString str, int32 a)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, str);
}
void AMyDeletegate::threeparamDeletaFunc(FString str, int32 a, float b)
{
GEngine->AddOnScreenDebugMessage(-1,5.0f,FColor::Red,str);
}
FString AMyDeletegate::revalparamDelegateFunc()
{
return FString("444");
}
void AMyDeletegate::PrintF(FString str)
{
GEngine->AddOnScreenDebugMessage(-1,5.0f,FColor::Red,str);
}

编译成功后将MyDelegate拖入场景中,播放运行

 其他绑定方法:

//lambda表达式

DelegateBindLambda.BindLambda([=](FString str)

{

if (GEngine) {

GEngine->AddOnScreenDebugMessage(-1, 30, FColor::Red, str);

}

});

//绑定原生C++指针,先创建一个类MyClass,创建一个类函数void BindRawFunc( FString str)

DelegateBindRaw.BindRaw(&myClass,&MyClass::BindRawFunc);

//绑定智能指针

NewmyClassPtr = MakeShareable(new MyClass());

DelegateBindSP.BindSP(NewmyClassPtr.ToSharedRef(),&MyClass::BindRawFunc);

//绑定static函数 创建一个函数static void staticFunc(FString str)

DelegateBindStatic.BindStatic(staticFunc);

//绑定UFUNCTION 

DelegateBindUFunction.BindUFunction(this,"UFuncTest");

}

源码如下:

.h文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyDeletegate.generated.h"


//声明带有一个参数的代理,名称为:DelegateOneParam
DECLARE_DELEGATE_OneParam(DelegateOneParam, FString);

class MyClass
{
public:
	void BindRawFunc(FString str)
	{
		if (GEngine) {
			GEngine->AddOnScreenDebugMessage(-1, 30, FColor::Red, str);
		}
	}

private:

};

static void staticFunc(FString str)
{
	if (GEngine) {
		GEngine->AddOnScreenDebugMessage(-1, 30, FColor::Red, str);
	}
}
UCLASS()
class TEST_API AMyDeletegate : public AActor
{
	GENERATED_BODY()
public:
	// Sets default values for this actor's properties
	AMyDeletegate();
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;
	//创建一个代理对象
	DelegateOneParam DelegateBindLambda;
	DelegateOneParam DelegateBindRaw;
	DelegateOneParam DelegateBindSP;
	DelegateOneParam DelegateBindStatic;
	DelegateOneParam DelegateBindUFunction;

	
	//代理绑定函数
	UFUNCTION()
	void UFuncTest(FString str);

	MyClass myClass;
	TSharedPtr<MyClass> NewmyClassPtr;
	void PrintF(FString str);

};
.cpp文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyDeletegate.h"
// Sets default values
AMyDeletegate::AMyDeletegate()
{
	// 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;
	//添加绑定函数
	//lambda表达式
	DelegateBindLambda.BindLambda([=](FString str)
		{
			if (GEngine) {
				GEngine->AddOnScreenDebugMessage(-1, 30, FColor::Red, str);
			}
		});
	//绑定原生C++指针
	DelegateBindRaw.BindRaw(&myClass, &MyClass::BindRawFunc);
	//绑定智能指针
	NewmyClassPtr = MakeShareable(new MyClass());
	DelegateBindSP.BindSP(NewmyClassPtr.ToSharedRef(), &MyClass::BindRawFunc);
	//绑定static函数
	DelegateBindStatic.BindStatic(staticFunc);
	//绑定UFUNCTION
	DelegateBindUFunction.BindUFunction(this, "UFuncTest");
}
// Called when the game starts or when spawned
void AMyDeletegate::BeginPlay()
{
	Super::BeginPlay();
	//在BeginPlay()函数执行绑定
	DelegateBindLambda.ExecuteIfBound("Lambda");
	DelegateBindRaw.ExecuteIfBound("Raw");
	DelegateBindSP.ExecuteIfBound("SP");
	DelegateBindStatic.ExecuteIfBound("Static");
	DelegateBindUFunction.ExecuteIfBound("UFunc");
}
// Called every frame
void AMyDeletegate::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}
void AMyDeletegate::UFuncTest(FString str)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, str);
}
void AMyDeletegate::PrintF(FString str)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, str);
}

编译运行

多播代理:

多播代理可以绑定多个函数,代理运行时将触发所有绑定的函数,多播代理没有返回值。多播代理的声明与单播代理相似
定义一个参数的多播代理类型
DECLARE_MULTICAST_DELEGATE_OneParam(MultiDelegate, FString);
定义多播代理变量
MultiDelegate multiDelegate;

绑定函数

 multiDelegate.AddUObject(this,&AMyDeletegate::UFuncTest1);
 multiDelegate.AddUObject(this, &AMyDeletegate::UFuncTest2);
 multiDelegate.AddUObject(this, &AMyDeletegate::UFuncTest3);

函数执行:

multiDelegate.Broadcast("MultiDelegate");

源码如下:

.h文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyDeletegate.generated.h"


//多播代理
DECLARE_MULTICAST_DELEGATE_OneParam(MultiDelegate, FString);

UCLASS()
class TEST_API AMyDeletegate : public AActor
{
	GENERATED_BODY()
public:
	// Sets default values for this actor's properties
	AMyDeletegate();
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;
	//创建一个代理对象
	MultiDelegate multiDelegate;
	
	//代理绑定函数
	UFUNCTION()
		void UFuncTest1(FString str);
	UFUNCTION()
	    void UFuncTest2(FString str);
	UFUNCTION()
	    void UFuncTest3(FString str);


	void PrintF(FString str);

};

.cpp文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyDeletegate.h"
// Sets default values
AMyDeletegate::AMyDeletegate()
{
	// 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;
	//添加绑定函数
	multiDelegate.AddUObject(this,&AMyDeletegate::UFuncTest1);
	multiDelegate.AddUObject(this, &AMyDeletegate::UFuncTest2);
	multiDelegate.AddUObject(this, &AMyDeletegate::UFuncTest3);
}
// Called when the game starts or when spawned
void AMyDeletegate::BeginPlay()
{
	Super::BeginPlay();
	//在BeginPlay()函数执行绑定
	multiDelegate.Broadcast("MultiDelegate");
}
// Called every frame
void AMyDeletegate::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}
void AMyDeletegate::UFuncTest1(FString str)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, str);
}
void AMyDeletegate::UFuncTest2(FString str)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, str);
}
void AMyDeletegate::UFuncTest3(FString str)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, str);
}
void AMyDeletegate::PrintF(FString str)
{
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, str);
}

编译成功后拖进场景运行

 动态多播代理:

动态代理
动态代理的使用方法和普通代理相似,动态多播代理可以暴露给蓝图,在蓝图中动态绑定相关的函数,而普通的代理和动态单播代理则不行。
定义动态多播代理类型
参数分别为多播代理名称,参数类型,参数名称
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDynamicDelegate, FString, param1);
注意:动态多播代理的名称开头须为F,否则会编译报错
定义动态多播代理变量,并添加宏标记,并设置为BlueprintAssignable
UPROPERTY(BlueprintAssignable);

源码如下:

.h文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyDeletegate.generated.h"
//动态多播代理 代理名称 参数类型 参数名
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDynamicDelegate, FString, param1);
UCLASS()
class TEST_API AMyDeletegate : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyDeletegate();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
//创建一个代理对象
UPROPERTY(BlueprintAssignable)
FDynamicDelegate NewDynamicDelegate;
//代理绑定函数


void PrintF(FString str);

};
.cpp文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyDeletegate.h"
// Sets default values
AMyDeletegate::AMyDeletegate()
{
// 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 AMyDeletegate::BeginPlay()
{
Super::BeginPlay();
//在BeginPlay()函数执行绑定
NewDynamicDelegate.Broadcast("NewDynamic BeginPlay");
}
// Called every frame
void AMyDeletegate::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AMyDeletegate::PrintF(FString str)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, str);
}

编译成功后,创建蓝图

 打开创建的蓝图绑定:

 运行结果如下:

猜你喜欢

转载自blog.csdn.net/qq_43021038/article/details/125040689