델리게이트는 할당된 기능을 모른 채 함수를 호출할 수 있다.

델리게이트는 ray함수 포인터보다 안전한 버전이다.

다음 레시피에서는 UFUNCTION을 델리게이트와 연결해 델리게이트가 실행될 때 호출되도록 하는 방법을 보여준다.

 

 

1.GameModeBase를 부모로 C++클래스를 생성하고 헤더에 다음을 추가한다.

더보기

 

#pragma once

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

/**
 * 
 */

 //매크로 델리게이트를 선언한다.
DECLARE_DELEGATE(FStandardDelegateSignature)

UCLASS()
class WILLIAM_API AGameModeBase_05 : public AGameModeBase
{
GENERATED_BODY()

public:

//매크로로 선언된 델리게이트형 함수를 만든다.
FStandardDelegateSignature MyStandardDelegate;

};

2.DelegterListener 라고 하는 Actor를 부모로 상속받아 C++클래스를 생성하고 다음과 같은 코드를 추가한다,.

 

Hedder

더보기

 

#pragma once

#include "CoreMinimal.h"
#include "Components/PointLightComponent.h"
#include "GameFramework/Actor.h"
#include "DelegateListener.generated.h"

UCLASS()
class WILLIAM_API ADelegateListener : public AActor
{
GENERATED_BODY()

//UPROPERTY
public:
UPROPERTY()
UPointLightComponent* PointLight;

//UFUNCTION
public:
UFUNCTION()
void EnableLight();


public:
ADelegateListener();

protected:
virtual void BeginPlay() override;

public:
virtual void Tick(float DeltaTime) override;

};

Cpp

더보기


#include "DelegateListener.h"
#include "GameModeBase_05.h"
#include "Kismet/GameplayStatics.h"


ADelegateListener::ADelegateListener()
{
PrimaryActorTick.bCanEverTick = true;

//PointLight 컴포넌트를 생성한다.
PointLight = CreateDefaultSubobject<UPointLightComponent>("PointLight");
//RootComponent를 PointLight로 설정한다.
RootComponent = PointLight;
PointLight->SetLightColor(FLinearColor::Red);
//생성 시에 보이지 않게 해준다.
PointLight->SetVisibility(false);

}

void ADelegateListener::BeginPlay()
{
Super::BeginPlay();


UWorld* TheWorld = GetWorld();

if(TheWorld !=nullptr)
{
AGameModeBase* GameMode = UGameplayStatics::GetGameMode(TheWorld);
AGameModeBase_05* MyGameMode = Cast<AGameModeBase_05>(GameMode);

if(MyGameMode!=nullptr)
{
MyGameMode->MyStandardDelegate.BindUObject(this, &ADelegateListener::EnableLight);
}
}

}

void ADelegateListener::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

}

void ADelegateListener::EnableLight()
{

PointLight->SetVisibility(true);
}

3.전장에서 만들었던 TriggerVloume 클래스에 다음과 같은 코드를 추가한다.

 

더보기




#include "MyTriggetrVolume.h"
#include "GameModeBase_05.h"
#include "Kismet/GameplayStatics.h"


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

TriggerZone = CreateDefaultSubobject<UBoxComponent>("TriggetZone");
TriggerZone->SetBoxExtent(FVector(200, 200, 10));

}

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

}

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

}

void AMyTriggetrVolume::NotifyActorBeginOverlap(AActor* OtherActor)
{
Super::NotifyActorBeginOverlap(OtherActor);
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, FString::Printf(TEXT("%s Entered Me"), *(OtherActor->GetName())));

UWorld* TheWorld = GetWorld();
if (TheWorld != nullptr)
{
AGameModeBase* GameMode = UGameplayStatics::GetGameMode(TheWorld);
AGameModeBase_05* MyGameMode = Cast<AGameModeBase_05>(GameMode);
if (MyGameMode != nullptr)
{
MyGameMode->MyStandardDelegate.ExecuteIfBound();
}
}

}

void AMyTriggetrVolume::NotifyActorEndOverlap(AActor* OtherActor)
{
Super::NotifyActorEndOverlap(OtherActor);
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, FString::Printf(TEXT("%s Left Me"), *(OtherActor->GetName())));

}

 

실행결과

 

 

델리게이트 등록 해제하기

 

때에 따라 델리게이트 바인딩을 제거해야할 수도 있다. 델리게이트바인딩 제거는 삭제된 객체를 더 이상 참조되지 않도록 함수 포인터를 nullptr로 설정하는 것과 같다.

 

 

1.이전의 DelegateListener 클래스의 헤더에 다음과 같은 코드를 추가한다.

 

더보기

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

 

1.이전의 DelegateListener 클래스의 CPP에 다음과 같은 코드를 추가한다.

 

더보기

void ADelegateListener::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);


UWorld* TheWorld = GetWorld();
if(TheWorld != nullptr)
{
AGameModeBase* GameMode = UGameplayStatics::GetGameMode(TheWorld);
AGameModeBase_05* MyGameMode = Cast<AGameModeBase_05>(GameMode);

if(MyGameMode!=nullptr)
{
MyGameMode->MyStandardDelegate.Unbind();
}

}

}

+ Recent posts