[UE4]委托代理:单播委托,多播委托,动态单播委托,动态多播委托,事件

本文详细介绍了在Unreal Engine中使用不同类型的委托,包括单播、多播、动态单播和动态多播委托的声明、绑定、解绑及调用。通过具体的C++代码示例展示了如何在游戏模式类中声明委托,在Actor类中绑定和解绑委托,以及在触发事件时调用委托,从而实现游戏逻辑间的通信。
摘要由CSDN通过智能技术生成

UE文档参考:

委托https://docs.unrealengine.com/4.26/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Delegates/

事件分发器/委托快速入门指南https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/ActorCommunication/EventDispatcherQuickStart/

注意事项

1.在 声明动态 单播/多播 委托(DECLARE_DYNAMIC_DELEGATE/DECLARE_DYNAMIC_MULTICAST_DELEGATE)时,DelegateName 参数必须以字符 'F' 开头,否则编译无法通过。

 最好时声明所有委托时,DelegateName 参数都以字符 'F' 开头,这样就没有问题了。

报错参考如下:

2.在C++代码中 绑定 动态 单播/多播时,被绑定的函数必须有UFUNCTION宏,如

	UFUNCTION()
	void onEnterTriggerDyMult_00();

C++应用举例

 说明:

为了方便测试,这里新建了 DelegateTest_GameMode 类用来申明与定义所有的委托。新建了ATrggerActor_Test 类来调用所有的委托。而委托的绑定则分类在不同的Actor类中实现。

委托声明与定义

新建 DelegateTest_GameMode 类(继承 GameModeBase 类)声明与定义这次测试的委托类型。

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "DelegateTest_GameMode.generated.h"

// 声明 无参 无返回值 的单播委托
DECLARE_DELEGATE(FOnEnterTrigger_00);
// 声明 1个参数 无返回值 的单播委托
DECLARE_DELEGATE_OneParam(FOnEnterTrigger_01, bool);
// 声明 2个参数 无返回值 的单播委托
DECLARE_DELEGATE_TwoParams(FOnEnterTrigger_02, bool, int32);
// 声明 3个参数 无返回值 的单播委托
DECLARE_DELEGATE_ThreeParams(FOnEnterTrigger_03, bool, int32, float);
// 声明 无参 有返回值 的单播委托
DECLARE_DELEGATE_RetVal(bool, FOnEnterTrigger_10);
// 声明 1个参数 有返回值 的单播委托
DECLARE_DELEGATE_RetVal_OneParam(bool, FOnEnterTrigger_11, FString);
// 声明 5个参数 有返回值 的单播委托
DECLARE_DELEGATE_RetVal_FiveParams(bool, FOnEnterTrigger_15, bool, int32, float, FString, FString);

// 声明 无参 的多播委托
DECLARE_MULTICAST_DELEGATE(FOnEnterTriggerMult_00);
// 声明 3个参数 的多播委托
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnEnterTriggerMult_03, bool, int32, float);

// 声明 无参 的动态单播播委托
DECLARE_DYNAMIC_DELEGATE_RetVal(int32,FOnEnterTriggerDy_10);
// 声明 4个参数 的动态单播播委托
DECLARE_DYNAMIC_DELEGATE_FourParams(FOnEnterTriggerDy_04, bool, bVal, int32, iVal, float, fVal, FString, fStr);

// 声明 无参 的动态多播委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnEnterTriggerDyMult_00);
// 声明 3个参数 的动态多播委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnEnterTriggerDyMult_02, bool, bVal, int32, iVal);

UCLASS()
class CMYGAME_API ADelegateTest_GameMode : public AGameModeBase
{
	GENERATED_BODY()

public:
	// 定义 单播委托
	FOnEnterTrigger_00 onEnterTrigger_00;
	FOnEnterTrigger_01 onEnterTrigger_01;
	FOnEnterTrigger_02 onEnterTrigger_02;
	FOnEnterTrigger_03 onEnterTrigger_03;
	FOnEnterTrigger_10 onEnterTrigger_10;
	FOnEnterTrigger_11 onEnterTrigger_11;
	FOnEnterTrigger_15 onEnterTrigger_15;

	// 定义 多播委托
	FOnEnterTriggerMult_00 onEnterTriggerMult_00;
	FOnEnterTriggerMult_03 onEnterTriggerMult_03;

	// 定义 动态 单播委托
	FOnEnterTriggerDy_10 onEnterTriggerDy_10;
	FOnEnterTriggerDy_04 onEnterTriggerDy_04;

	// 定义 动态 多播委托
	FOnEnterTriggerDyMult_00 onEnterTriggerDyMult_00;
	FOnEnterTriggerDyMult_02 onEnterTriggerDyMult_02;
};

单播委托绑定与解绑

DECLARE_DELEGATE

新建类 ALightActor_Test 中声明与实现对应的绑定函数,并在类中实现绑定

protected:
	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason)override;

public:
	UPROPERTY(EditAnywhere)
	class UPointLightComponent* PointLigth;
	UPROPERTY(EditAnywhere)
	class UTextRenderComponent* TextRender;

	UFUNCTION()
	void TestBindDelegate();
	UFUNCTION()
	void TestUnBindDelegate();

	// LightActor_Test 类 声明函数
	UFUNCTION(BlueprintCallable)
	void TestFuncNoParam();
	UFUNCTION(BlueprintCallable)
	void TestFuncThreeParams(bool bVal,int32 iVal,float fVal);
	UFUNCTION(BlueprintCallable)
	bool TestFuncRetValNoParam();
	UFUNCTION(BlueprintCallable)
	bool TestFuncRetValFiveParams(bool bVal, int32 iVal, float fVal, FString fStr1, FString fStr2);
	UFUNCTION(BlueprintCallable)
	void EnablePointLight(bool bEnable);

// Fill out your copyright notice in the Description page of Project Settings.

#include "LightActor_Test.h"
#include <Components/PointLightComponent.h>
#include <Kismet/GameplayStatics.h>
#include "DelegateTest_GameMode.h"
#include <Components/TextRenderComponent.h>

// Sets default values
ALightActor_Test::ALightActor_Test()
{
 	// 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;

	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
	PointLigth = CreateDefaultSubobject<UPointLightComponent>(TEXT("Point"));
	PointLigth->SetupAttachment(RootComponent);
	PointLigth->SetLightColor(FColor::Red);
	PointLigth->SetVisibility(false);

	TextRender = CreateDefaultSubobject<UTextRenderComponent>(TEXT("TextRender"));
	TextRender->SetupAttachment(RootComponent);
	TextRender->SetRelativeLocation(FVector::FVector(0.f, 0.f, 1.f));
	TextRender->SetTextRenderColor(FColor::Red);
	TextRender->SetText(TEXT(""));
	TextRender->SetRelativeRotation(FRotator::FRotator(0.f, 180.f, 0.f));
	TextRender->SetVisibility(false);
}

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

void ALightActor_Test::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	TestUnBindDelegate();
}

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

// 委托绑定
void ALightActor_Test::TestBindDelegate()
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::White, TEXT("-- TestDelegate"));

	UWorld* curWorld = GetWorld();
	if (curWorld)
	{
		AGameModeBase* curGameMode = UGameplayStatics::GetGameMode(curWorld);
		ADelegateTest_GameMode* myGameMode = Cast<ADelegateTest_GameMode>(curGameMode);

		myGameMode->onEnterTrigger_01.BindUObject(this, &ALightActor_Test::EnablePointLight);

		myGameMode->onEnterTrigger_00.BindUObject(this, &ALightActor_Test::TestFuncNoParam);
		myGameMode->onEnterTrigger_03.BindUObject(this, &ALightActor_Test::TestFuncThreeParams);
		myGameMode->onEnterTrigger_10.BindUObject(this, &ALightActor_Test::TestFuncRetValNoParam);
		myGameMode->onEnterTrigger_15.BindUObject(this, &ALightActor_Test::TestFuncRetValFiveParams);
	}
}
// 委托解绑定
void ALightActor_Test::TestUnBindDelegate()
{
	UWorld* curWorld = GetWorld();
	if (curWorld)
	{
		AGameModeBase* gameMode = UGameplayStatics::GetGameMode(curWorld);
		ADelegateTest_GameMode* myGameMode = Cast<ADelegateTest_GameMode>(gameMode);
		if (myGameMode)
		{
			myGameMode->onEnterTrigger_00.Unbind();
			myGameMode->onEnterTrigger_01.Unbind();
			myGameMode->onEnterTrigger_03.Unbind();
			myGameMode->onEnterTrigger_10.Unbind();
			myGameMode->onEnterTrigger_15.Unbind();
		}
	}
}

// 实现LightActor_Test头文件中声明的函数
void ALightActor_Test::TestFuncNoParam()
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::White, TEXT("-- TestFuncNoParam"));
}
// 实现LightActor_Test头文件中声明的函数
void ALightActor_Test::TestFuncThreeParams(bool bVal, int32 iVal, float fVal)
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::White, FString::Printf(TEXT("-- TestFuncThreeParams,%d, %d,%f"), bVal ? 1:0, iVal, fVal));
}
// 实现LightActor_Test头文件中声明的函数
bool ALightActor_Test::TestFuncRetValNoParam()
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::White, TEXT("-- TestFuncRetValNoParam"));
	return false;
}
// 实现LightActor_Test头文件中声明的函数
bool ALightActor_Test::TestFuncRetValFiveParams(bool bVal, int32 iVal, float fVal, FString fStr1, FString fStr2)
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::White, FString::Printf(TEXT("-- TestFuncRetValFiveParams,%d, %d, %f,%s,%s"), bVal?1:0, iVal, fVal, *fStr1, *fStr2));
	return false;
}
// 实现LightActor_Test头文件中声明的函数
void ALightActor_Test::EnablePointLight(bool bEnable)
{
	PointLigth->SetLightColor(FColor::Red);
	PointLigth->SetVisibility(bEnable);
	TextRender->SetVisibility(bEnable);
	if (bEnable)
	{
		TextRender->SetRelativeRotation(FRotator::FRotator(0.f, 180.f, 0.f));
		TextRender->SetText(TEXT("Light"));
	}
	else
	{
		TextRender->SetText(TEXT(""));
	}
}

多播委托绑定与解绑

DECLARE_MULTICAST_DELEGATE

新建 FOnEnterTriggerMult_Actor 类实现绑定与解绑

protected:
	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

public:
	UPROPERTY(EditAnywhere)
	class UTextRenderComponent* TheTextRender;
	UPROPERTY(EditAnywhere)
	class UTextRenderComponent* TheTextRender2;

	UFUNCTION()
	void BindDelegate();
	UFUNCTION()
	void UnBindDelegate();

	int32 count = 0;
	FDelegateHandle delegateHandle;

	UFUNCTION(BlueprintCallable)
	void FOnEnterTriggerMult_00();
	UFUNCTION(BlueprintCallable)
	void FOnEnterTriggerMult_03(bool bVal,int32 iVal,float fVal);
// Fill out your copyright notice in the Description page of Project Settings.

#include "FOnEnterTriggerMult_Actor.h"
#include <Components/TextRenderComponent.h>
#include <Kismet/GameplayStatics.h>
#include "DelegateTest_GameMode.h"

// Sets default values
AFOnEnterTriggerMult_Actor::AFOnEnterTriggerMult_Actor()
{
	// 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;

	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
	TheTextRender = CreateDefaultSubobject<UTextRenderComponent>(TEXT("TextRender01"));
	TheTextRender->SetupAttachment(RootComponent);
	TheTextRender->SetWorldSize(10.f);
	TheTextRender->SetText("DECLARE_MULTICAST_DELEGATE");
	TheTextRender->SetTextRenderColor(FColor::Red);

	TheTextRender2 = CreateDefaultSubobject<UTextRenderComponent>(TEXT("TextRender02"));
	TheTextRender2->SetupAttachment(RootComponent);
	TheTextRender2->SetWorldSize(10.f);
	TheTextRender2->SetRelativeLocation(FVector::FVector(0.f, 0.f, 10.f));
	TheTextRender2->SetText(TEXT("DECLARE_MULTICAST_DELEGATE"));
	TheTextRender2->SetTextRenderColor(FColor::Red);
}

void AFOnEnterTriggerMult_Actor::BeginPlay()
{
	Super::BeginPlay();
	BindDelegate();
}

void AFOnEnterTriggerMult_Actor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);
	UnBindDelegate();
}

void AFOnEnterTriggerMult_Actor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

// 委托绑定
void AFOnEnterTriggerMult_Actor::BindDelegate()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}

	delegateHandle = curGameMode->onEnterTriggerMult_00.AddUObject(this, &AFOnEnterTriggerMult_Actor::FOnEnterTriggerMult_00);
	curGameMode->onEnterTriggerMult_03.AddUObject(this, &AFOnEnterTriggerMult_Actor::FOnEnterTriggerMult_03);
}

// 委托解绑
void AFOnEnterTriggerMult_Actor::UnBindDelegate()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}

	curGameMode->onEnterTriggerMult_00.Remove(delegateHandle);
	curGameMode->onEnterTriggerMult_00.RemoveAll(this);
	curGameMode->onEnterTriggerMult_03.RemoveAll(this);
}

void AFOnEnterTriggerMult_Actor::FOnEnterTriggerMult_00()
{
	TheTextRender->SetText("FOnEnterTriggerMult_00");
	count++;
	if (count % 2 == 1)
	{
		TheTextRender->SetTextRenderColor(FColor::Black);
	}
	else
	{
		TheTextRender->SetTextRenderColor(FColor::Red);
	}
}

void AFOnEnterTriggerMult_Actor::FOnEnterTriggerMult_03(bool bVal, int32 iVal, float fVal)
{
	TheTextRender2->SetText("FOnEnterTriggerMult_03");
	if (bVal)
	{
		TheTextRender2->SetTextRenderColor(FColor::Black);
	}
	else
	{
		TheTextRender2->SetTextRenderColor(FColor::FColor(255,0,255));
	}
}

动态单播委托绑定与解绑

DECLARE_DYNAMIC_DELEGATE

新建 FOnEnterTriggerDy_Actor 类实现委托绑定与解绑,注意:动态单播/多播委托绑定的函数必须带有宏 UFUNCTION()

protected:
	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

public:
	UPROPERTY(EditAnyWhere)
	class UTextRenderComponent* theTextRender01;
	UPROPERTY(EditAnywhere)
	class UTextRenderComponent* theTextRender02;

	int32 count = 0;

	UFUNCTION()
	void BindDelegate();
	UFUNCTION()
	void UnBindDelegate();

	UFUNCTION(BlueprintCallable)
	int32 onEnterTriggerDy_10();
	UFUNCTION(BlueprintCallable)
	void onEnterTriggerDy_04(bool bVal,int32 iVal,float fVal,FString fStr);
// Fill out your copyright notice in the Description page of Project Settings.

#include "FOnEnterTriggerDy_Actor.h"
#include <Kismet/GameplayStatics.h>
#include "DelegateTest_GameMode.h"
#include <Components/TextRenderComponent.h>

// Sets default values
AFOnEnterTriggerDy_Actor::AFOnEnterTriggerDy_Actor()
{
	// 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;

	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
	theTextRender01 = CreateDefaultSubobject<UTextRenderComponent>(TEXT("theTextRender01"));
	theTextRender01->SetupAttachment(RootComponent);
	theTextRender01->SetText("DECLARE_DYNAMIC_DELEGATE");
	theTextRender01->SetTextRenderColor(FColor::Blue);
	theTextRender01->SetWorldSize(10.f);

	theTextRender02 = CreateDefaultSubobject<UTextRenderComponent>(TEXT("theTextRender02"));
	theTextRender02->SetupAttachment(RootComponent);
	theTextRender02->SetText("DECLARE_DYNAMIC_DELEGATE");
	theTextRender02->SetTextRenderColor(FColor::Blue);
	theTextRender02->SetWorldSize(10.f);
	theTextRender02->SetRelativeLocation(FVector(0.f, 0.f, 10.f));
}

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

void AFOnEnterTriggerDy_Actor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);
	UnBindDelegate();
}

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

// 委托绑定
void AFOnEnterTriggerDy_Actor::BindDelegate()
{
	GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, TEXT("AFOnEnterTriggerDy_Actor::BindDelegate()"));

	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}

	// BindUFunction 与 BindDynamic 同样可以实现委托的绑定
	curGameMode->onEnterTriggerDy_10.BindUFunction(this, STATIC_FUNCTION_FNAME(TEXT("AFOnEnterTriggerDy_Actor::onEnterTriggerDy_10")));
	//curGameMode->onEnterTriggerDy_10.BindDynamic(this, &AFOnEnterTriggerDy_Actor::onEnterTriggerDy_10);

	// BindUFunction 与 BindDynamic 同样可以实现委托的绑定
	//curGameMode->onEnterTriggerDy_04.BindUFunction(this, STATIC_FUNCTION_FNAME(TEXT("AFOnEnterTriggerDy_Actor::onEnterTriggerDy_04")));
	curGameMode->onEnterTriggerDy_04.BindDynamic(this, &AFOnEnterTriggerDy_Actor::onEnterTriggerDy_04);
	//curGameMode->onEnterTriggerDy_04.__Internal_BindDynamic()
}

// 委托解绑定
void AFOnEnterTriggerDy_Actor::UnBindDelegate()
{
	GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, TEXT("AFOnEnterTriggerDy_Actor::BindDelegate()"));

	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}

	curGameMode->onEnterTriggerDy_10.Clear();
	curGameMode->onEnterTriggerDy_04.Unbind();
}

int32 AFOnEnterTriggerDy_Actor::onEnterTriggerDy_10()
{
	theTextRender01->SetText(TEXT("onEnterTriggerDy_10"));
	count++;
	if (count % 2 == 1)
	{
		theTextRender01->SetTextRenderColor(FColor::Green);
	}
	else
	{
		theTextRender01->SetTextRenderColor(FColor::Blue);
	}
	return 9;
}

void AFOnEnterTriggerDy_Actor::onEnterTriggerDy_04(bool bVal, int32 iVal, float fVal, FString fStr)
{
	theTextRender02->SetText(TEXT("onEnterTriggerDy_04"));
	if (bVal)
	{
		theTextRender02->SetTextRenderColor(FColor::Green);
	}
	else
	{
		theTextRender02->SetTextRenderColor(FColor::Black);
	}
}

动态多播委托绑定与解绑

DECLARE_DYNAMIC_MULTICAST_DELEGATE

新建 FOnEnterTriggerDyMult_Actor 类实现委托绑定与解绑,注意:动态单播/多播委托绑定的函数必须带有宏 UFUNCTION()

protected:
	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

public:
	UPROPERTY(EditAnywhere)
	class UTextRenderComponent* TheTextRender01;
	UPROPERTY(EditAnywhere)
	class UTextRenderComponent* TheTextRender02;
	int32 count = 0;

	UFUNCTION()
	void BindDelegate();
	UFUNCTION()
	void UnBindDelegate();
	
	UFUNCTION()
	void onEnterTriggerDyMult_00();
	UFUNCTION()
	void onEnterTriggerDyMult_02(bool bVal,int32 iVal);

// Fill out your copyright notice in the Description page of Project Settings.


#include "FOnEnterTriggerDyMult_Actor.h"
#include <Kismet/GameplayStatics.h>
#include "DelegateTest_GameMode.h"
#include <Components/TextRenderComponent.h>

// Sets default values
AFOnEnterTriggerDyMult_Actor::AFOnEnterTriggerDyMult_Actor()
{
 	// 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;

	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
	

	TheTextRender01 = CreateDefaultSubobject<UTextRenderComponent>(TEXT("TheText"));
	TheTextRender01->SetupAttachment(RootComponent);
	TheTextRender01->SetText(TEXT("DECLARE_DYNAMIC_MULTICAST_DELEGATE"));
	TheTextRender01->SetWorldSize(10.f);
	TheTextRender01->SetTextRenderColor(FColor::Green);
	TheTextRender01->SetWorldRotation(FRotator::FRotator(0.0f, 180.f, 0.f));

	TheTextRender02 = CreateDefaultSubobject<UTextRenderComponent>(TEXT("TheText2"));
	TheTextRender02->SetupAttachment(RootComponent);
	TheTextRender02->SetText(TEXT("DECLARE_DYNAMIC_MULTICAST_DELEGATE"));
	TheTextRender02->SetWorldSize(10.f);
	TheTextRender02->SetTextRenderColor(FColor::Green);
	TheTextRender02->SetRelativeLocation(FVector::FVector(0.f, 0.f, 10.f));
	TheTextRender02->SetWorldRotation(FRotator::FRotator(0.0f, 180.f, 0.f));
}

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

void AFOnEnterTriggerDyMult_Actor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);
	UnBindDelegate();
}

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

}

// 委托绑定
void AFOnEnterTriggerDyMult_Actor::BindDelegate()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr) {
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}

	//curGameMode->onEnterTriggerDyMult_00.__Internal_AddDynamic
	curGameMode->onEnterTriggerDyMult_00.AddDynamic(this, &AFOnEnterTriggerDyMult_Actor::onEnterTriggerDyMult_00);
	curGameMode->onEnterTriggerDyMult_02.AddDynamic(this, &AFOnEnterTriggerDyMult_Actor::onEnterTriggerDyMult_02);
}

// 委托解除绑定
void AFOnEnterTriggerDyMult_Actor::UnBindDelegate()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr) {
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}
	curGameMode->onEnterTriggerDyMult_00.RemoveAll(this);
	curGameMode->onEnterTriggerDyMult_02.RemoveAll(this);
}

void AFOnEnterTriggerDyMult_Actor::onEnterTriggerDyMult_00()
{
	TheTextRender01->SetText("onEnterTriggerDyMult_00");
	if (count/2==1)
	{
		TheTextRender01->SetTextRenderColor(FColor::FColor(255, 0, 255));

	}
	else
	{
		TheTextRender01->SetTextRenderColor(FColor::Green);
	}
}

void AFOnEnterTriggerDyMult_Actor::onEnterTriggerDyMult_02(bool bVal, int32 iVal)
{
	TheTextRender02->SetText("onEnterTriggerDyMult_02");
	if (bVal)
	{
		TheTextRender02->SetTextRenderColor(FColor::FColor(255, 0, 255));
	}
	else
	{
		TheTextRender02->SetTextRenderColor(FColor::Green);
	}
}

 委托调用 

新建 TrggerActor_Test 类来触发委托事件的调用

public:
	virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;
	virtual void NotifyActorEndOverlap(AActor* OtherActor) override;

	UPROPERTY(EditAnywhere)
	class UBoxComponent* BoxTrigger;

	// 调用 单播委托
	void call_BeginOverlap_DECLARE_DELEGATE();
	void call_EndOverlap_DECLARE_DELEGATE();

	// 调用 多播委托
	void call_BeginOverlap_DECLARE_MULTICAST_DELEGATE();
	void call_EndOverlap_DECLARE_MULTICAST_DELEGATE();

	// 调用 动态单播委托
	void call_BeginOverlap_DECLARE_DYNAMIC_DELEGATE();
	void call_EndOverlap_DECLARE_DYNAMIC_DELEGATE();

	// 调用 动态多播委托
	void call_BeginOverlap_DECLARE_DYNAMIC_MULTICAST_DELEGATE();
	void call_EndOverlap_DECLARE_DYNAMIC_MULTICAST_DELEGATE();

// Fill out your copyright notice in the Description page of Project Settings.


#include "TrggerActor_Test.h"
#include <Components/BoxComponent.h>
#include <GameFramework/GameMode.h>
#include <Kismet/GameplayStatics.h>
#include "DelegateTest_GameMode.h"
#include <Components/TextRenderComponent.h>

// Sets default values
ATrggerActor_Test::ATrggerActor_Test()
{
	PrimaryActorTick.bCanEverTick = false;

	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
	// create 1个触发器,重写 NotifyActorBeginOverlap 与 NotifyActorEndOverlap 函数
	BoxTrigger = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxTrigger"));
	BoxTrigger->SetupAttachment(RootComponent);
	BoxTrigger->SetWorldScale3D(FVector::FVector(5.f, 5.f, 5.f));
}

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

}

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

}

void ATrggerActor_Test::NotifyActorBeginOverlap(AActor* OtherActor)
{
	Super::NotifyActorBeginOverlap(OtherActor);
	// 单播委托调用
	call_BeginOverlap_DECLARE_DELEGATE();
	// 多播委托调用
	call_BeginOverlap_DECLARE_MULTICAST_DELEGATE();
	// 动态 单播委托调用
	call_BeginOverlap_DECLARE_DYNAMIC_DELEGATE();
	// 动态 多播委托调用
	call_BeginOverlap_DECLARE_DYNAMIC_MULTICAST_DELEGATE();
}

void ATrggerActor_Test::NotifyActorEndOverlap(AActor* OtherActor)
{
	Super::NotifyActorEndOverlap(OtherActor);
	// 单播委托调用
	call_EndOverlap_DECLARE_DELEGATE();
	// 多播委托调用
	call_EndOverlap_DECLARE_MULTICAST_DELEGATE();
	// 动态 单播委托调用
	call_EndOverlap_DECLARE_DYNAMIC_DELEGATE();
	// 动态 多播委托调用
	call_EndOverlap_DECLARE_DYNAMIC_MULTICAST_DELEGATE();
}

// 单播委托调用
void ATrggerActor_Test::call_BeginOverlap_DECLARE_DELEGATE()
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Blue, TEXT("-- NotifyActorBeginOverlap"));

	UWorld* curWorld = GetWorld();
	if (curWorld != nullptr)
	{
		AGameModeBase* GameMode = Cast<AGameModeBase>(UGameplayStatics::GetGameMode(curWorld));
		ADelegateTest_GameMode* myGameMode = Cast<ADelegateTest_GameMode>(GameMode);
		if (myGameMode == nullptr)
		{
			GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("-- myGameMode == nullptr"));
			return;
		}
		if (myGameMode->onEnterTrigger_00.IsBound())
		{
			myGameMode->onEnterTrigger_00.Execute();
		}
		myGameMode->onEnterTrigger_01.ExecuteIfBound(true);
		myGameMode->onEnterTrigger_02.ExecuteIfBound(true, 11);
		myGameMode->onEnterTrigger_03.ExecuteIfBound(true, 11, 11.f);
		if (myGameMode->onEnterTrigger_10.IsBound())
		{
			bool bValue = myGameMode->onEnterTrigger_10.Execute();
		}
		if (myGameMode->onEnterTrigger_11.IsBound())
		{
			bool bValue = myGameMode->onEnterTrigger_11.Execute(TEXT("test - 11"));
		}
		if (myGameMode->onEnterTrigger_15.IsBound())
		{
			bool bValue = myGameMode->onEnterTrigger_15.Execute(true, 11, 11.f, TEXT("test - 11"), TEXT("test - 11"));
		}
	}
}
// 单播委托调用
void ATrggerActor_Test::call_EndOverlap_DECLARE_DELEGATE()
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Black, TEXT("-- NotifyActorEndOverlap"));

	UWorld* curWorld = GetWorld();
	if (curWorld != nullptr)
	{
		AGameModeBase* gameMode = Cast<AGameModeBase>(UGameplayStatics::GetGameMode(curWorld));
		ADelegateTest_GameMode* myGameMode = Cast<ADelegateTest_GameMode>(gameMode);
		if (myGameMode == nullptr)
		{
			GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("-- myGameMode == nullptr"));
			return;
		}
		myGameMode->onEnterTrigger_00.ExecuteIfBound();
		myGameMode->onEnterTrigger_01.ExecuteIfBound(false);
		myGameMode->onEnterTrigger_02.ExecuteIfBound(false, 22);
		myGameMode->onEnterTrigger_03.ExecuteIfBound(false, 22, 22.f);
		if (myGameMode->onEnterTrigger_10.IsBound())
		{
			bool bValue = myGameMode->onEnterTrigger_10.Execute();
		}
		if (myGameMode->onEnterTrigger_11.IsBound())
		{
			bool bValue = myGameMode->onEnterTrigger_11.Execute(TEXT("Test - 22"));
		}
		if (myGameMode->onEnterTrigger_15.IsBound())
		{
			bool bValue = myGameMode->onEnterTrigger_15.Execute(false, 22, 22.f, TEXT("Test - 22"), TEXT("Test - 22"));
		}
	}
}

// 多播委托调用
void ATrggerActor_Test::call_BeginOverlap_DECLARE_MULTICAST_DELEGATE()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld)) ;
	if (curGameMode == nullptr)
	{
		return;
	}
	curGameMode->onEnterTriggerMult_00.Broadcast();
	curGameMode->onEnterTriggerMult_03.Broadcast(true,3,3.f);
}
// 多播委托调用
void ATrggerActor_Test::call_EndOverlap_DECLARE_MULTICAST_DELEGATE()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}
	curGameMode->onEnterTriggerMult_00.Broadcast();
	curGameMode->onEnterTriggerMult_03.Broadcast(false, 3, 3.f);
}

// 动态 单播委托调用
void ATrggerActor_Test::call_BeginOverlap_DECLARE_DYNAMIC_DELEGATE()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}
	if (curGameMode->onEnterTriggerDy_10.IsBound())
	{
		curGameMode->onEnterTriggerDy_10.Execute();
	}
	curGameMode->onEnterTriggerDy_04.ExecuteIfBound(true, 4, 4.f, TEXT("onEnterTriggerDy_04"));
}
// 动态 单播委托调用
void ATrggerActor_Test::call_EndOverlap_DECLARE_DYNAMIC_DELEGATE()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}

	//GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, TEXT("ATrggerActor_Test::call_EndOverlap_DECLARE_DYNAMIC_DELEGATE()"));
	if (curGameMode->onEnterTriggerDy_10.IsBound())
	{
		//GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, TEXT("ATrggerActor_Test::call_EndOverlap_DECLARE_DYNAMIC_DELEGATE()"));
		curGameMode->onEnterTriggerDy_10.Execute();
	}
	curGameMode->onEnterTriggerDy_04.ExecuteIfBound(false, 4, 4.f, TEXT("onEnterTriggerDy_04"));
}

// 动态 多播委托调用
void ATrggerActor_Test::call_BeginOverlap_DECLARE_DYNAMIC_MULTICAST_DELEGATE()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}
	curGameMode->onEnterTriggerDyMult_00.Broadcast();
	curGameMode->onEnterTriggerDyMult_02.Broadcast(true, 2);
}
// 动态 多播委托调用
void ATrggerActor_Test::call_EndOverlap_DECLARE_DYNAMIC_MULTICAST_DELEGATE()
{
	UWorld* curWorld = GetWorld();
	if (curWorld == nullptr)
	{
		return;
	}
	ADelegateTest_GameMode* curGameMode = Cast<ADelegateTest_GameMode>(UGameplayStatics::GetGameMode(curWorld));
	if (curGameMode == nullptr)
	{
		return;
	}
	curGameMode->onEnterTriggerDyMult_00.Broadcast();
	curGameMode->onEnterTriggerDyMult_02.Broadcast(false, 2);
}

事件暂时留个坑

有时间在补齐

UE4中,您可以使用单播委托(Unicast Delegate)来实现事件的触发和处理。单播委托允许将一个或多个方法注册为事件的处理程序,并且可以使用payload参数传递数据。 以下是在UE4中使用单播委托和payload参数的示例: 1. 在您的类声明中定义委托类型和委托实例。例如: ```cpp DECLARE_DELEGATE_OneParam(FMyDelegate, const FString&); FMyDelegate MyDelegate; ``` 2. 在需要触发事件的地方,调用委托实例并传递payload参数。例如: ```cpp FString Payload = "Hello, World!"; MyDelegate.Execute(Payload); ``` 3. 在其他地方注册方法作为事件的处理程序,并定义方法的签名与委托类型一致。例如: ```cpp void MyClass::MyMethod(const FString& Payload) { UE_LOG(LogTemp, Warning, TEXT("MyMethod executed with payload: %s"), *Payload); } // 注册方法作为处理程序 MyDelegate.BindUObject(this, &MyClass::MyMethod); ``` 在上面的示例中,我们声明了FMyDelegate作为委托类型,并创建了一个委托实例MyDelegate。然后,在需要触发事件的地方,我们调用MyDelegate的Execute方法,并传递Payload参数。 在另一个类(例如MyClass)中,我们定义了一个名为MyMethod的方法,并使用BindUObject将其注册为处理程序。当事件触发时,MyMethod方法将被执行,并且可以访问传递的payload参数。 请注意,上述示例中的代码仅为演示目的,实际使用时您需要根据您的需求和代码结构进行适当的修改和调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值