- Add a new delegate declaration to GameMode:
DECLARE_DELEGATE(FStandardDelegateSignature)
DECLARE_DELEGATE_OneParam(FParamDelegateSignature, FLinearColor)
UCLASS()
class CHAPTER_05_API AChapter_05GameModeBase : public AGameModeBase
- Add a new member to GameMode:
DECLARE_DELEGATE(FStandardDelegateSignature)
DECLARE_DELEGATE_OneParam(FParamDelegateSignature, FLinearColor)
UCLASS()
class CHAPTER_05_API AChapter_05GameModeBase : public AGameModeBase
{
GENERATED_BODY()
public:
FStandardDelegateSignature MyStandardDelegate;
FParamDelegateSignature MyParameterDelegate;
};
- Create a new Actor class called ParamDelegateListener. Add the following to the declaration:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/PointLightComponent.h"
#include "ParamDelegateListener.generated.h"
UCLASS()
class CHAPTER_05_API AParamDelegateListener : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AParamDelegateListener();
UFUNCTION()
void SetLightColor(FLinearColor LightColor);
UPROPERTY()
UPointLightComponent* PointLight;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
- In the class implementation, add the following to the constructor:
// Sets default values
AParamDelegateListener::AParamDelegateListener()
{
// 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;
PointLight = CreateDefaultSubobject<UPointLightComponent>("PointLight");
RootComponent = PointLight;
}
- In the ParamDelegateListener.cpp file, add the following #includes:
#include "ParamDelegateListener.h"
#include "Chapter_05GameModeBase.h"
#include "Kismet/GameplayStatics.h"
- Inside the AParamDelegateListener::BeginPlay implementation, add the following code:
// Called when the game starts or when spawned
void AParamDelegateListener::BeginPlay()
{
Super::BeginPlay();
UWorld* TheWorld = GetWorld();
if (TheWorld != nullptr)
{
AGameModeBase* GameMode =
UGameplayStatics::GetGameMode(TheWorld);
AChapter_05GameModeBase * MyGameMode =
Cast<AChapter_05GameModeBase>(GameMode);
if (MyGameMode != nullptr)
{
MyGameMode->MyParameterDelegate.BindUObject(this,
&AParamDelegateListener::SetLightColor);
}
}
}
- Lastly, implement SetLightColor:
void AParamDelegateListener::SetLightColor(FLinearColor LightColor)
{
PointLight->SetLightColor(LightColor);
}
- Inside our TriggerVolume, in NotifyActorBeginOverlap, add the following new code:
void AMyTriggerVolume::NotifyActorBeginOverlap(AActor* OtherActor)
{
auto Message = FString::Printf(TEXT("%s entered me"),
*(OtherActor->GetName()));
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, Message);
// Call our delegate
UWorld* TheWorld = GetWorld();
if (TheWorld != nullptr)
{
AGameModeBase* GameMode =
UGameplayStatics::GetGameMode(TheWorld);
AChapter_05GameModeBase * MyGameMode =
Cast<AChapter_05GameModeBase>(GameMode);
if(MyGameMode != nullptr)
{
MyGameMode->MyStandardDelegate.ExecuteIfBound();
// Call the function using a parameter
auto Color = FLinearColor(1, 0, 0, 1);
MyGameMode->MyParameterDelegate.ExecuteIfBound(Color);
}
}
}
- Save your script and then go back to the Unreal Editor and compile your code. Add the MyTriggerVolume and ParamDelegateListener objects to your scene and then run the game and confirm that the light starts off as white and, upon collision, changes to red: