B站教学链接:https://space.bilibili.com/449549424?spm_id_from=333.1007.0.0
简介:委托可以以通用、类型安全的方式调用 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);
}
编译成功后,创建蓝图
打开创建的蓝图绑定:
运行结果如下: