본문 바로가기
Unreal5/기본개념

[C++] 델리게이트 사용법

by 위니밍 2025. 6. 2.
반응형

싱글 델리게이트 : 1-? 로 검색

멀티 델리게이트 : 2-? 로 검색

 

 

  • 1번 델리게이트는 보스가 자기 자신에게만 쓰는 내부 호출
  • 2번 델리게이트는 보스가 연결된 모든 미니언에게 동시에 신호를 주는 브로드캐스트 방식

 

📘 1번 순서: 싱글 델리게이트 – 보스 자기 자신 호출

단계설명
1-1 DECLARE_DELEGATE_OneParam(FUseManaDele, float)
→ 보스가 쓸 싱글 델리게이트 정의  
1-2 FUseManaDele OnUseManaDelegate;
→ 보스 클래스 내부에 변수 선언  
1-3 OnUseManaDelegate.BindUObject(this, &ABoss::UseMana);
→ 게임 시작 시, 자기 자신의 UseMana() 함수 바인딩  
1-4 if (OnUseManaDelegate.IsBound())
→ 함수 연결 여부 확인  
1-5 OnUseManaDelegate.Execute(10.0);
→ 보스의 UseMana(10.0) 실행됨  
 

핵심: 보스 내부에서 자기 함수 하나만 연결해 쓰는 싱글 델리게이트


📗 2번 순서: 멀티캐스트 델리게이트 – 여러 미니언에게 명령 전파

단계설명
2-1 DECLARE_MULTICAST_DELEGATE_OneParam(FMinionSendBuffMultiDele, int32)
→ 미니언에게 전파할 멀티캐스트 델리게이트 정의  
2-2 FMinionSendBuffMultiDele OnMinionsSendBuffDelegate;
→ 보스 클래스에 변수 선언  
2-3 미니언이 UGameplayStatics::GetActorOfClass()로 보스 찾음
2-4 Boss->OnMinionsSendBuffDelegate.AddUObject(this, &AMinion::AddBuff);
→ 미니언들이 보스의 델리게이트에 자기 함수 등록  
2-5 if (OnMinionsSendBuffDelegate.IsBound())
→ 보스가 델리게이트에 함수가 바인딩되었는지 확인  
2-6 OnMinionsSendBuffDelegate.Broadcast(Num);
→ 등록된 미니언들의 AddBuff(Num) 전부 호출됨  
 

핵심: 보스가 한 번 Broadcast(Num) 호출하면, 모든 구독한 미니언의 AddBuff() 실행됨

 

// Minion.cpp


#include "Minion.h"
#include "Boss.h"
#include "Kismet/GameplayStatics.h"

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

}

void AMinion::AddBuff(int32 Value)
{
	if (Index == Value)
	{
		UE_LOG(LogTemp, Warning, TEXT("Buff Actor : %s"), *GetActorLabel()); //GetActorNameOrLabel
	}
}

void AMinion::DeadAll()
{
	UE_LOG(LogTemp, Warning, TEXT("Time to Die : %s"), *GetActorLabel());
	Destroy();
}

void AMinion::OtherFuncDead()
{
	UE_LOG(LogTemp, Warning, TEXT("Time to Die2 : %s"), *GetActorLabel());
}

void AMinion::OtherBuff(int32 Value)
{
	if (Index != Value)
	{
		UE_LOG(LogTemp, Warning, TEXT("OtherBuff Actor : %s"), *GetActorLabel());
	}
}

// Called when the game starts or when spawned
void AMinion::BeginPlay()
{
	Super::BeginPlay();
	
	//월드에서 보스액터 찾기
	AActor* FoundActor = UGameplayStatics::GetActorOfClass(GetWorld(), ABoss::StaticClass()); //2-3. 생성시 월드에서 보스액터 찾음
	Boss = Cast<ABoss>(FoundActor);

	//보스가 있으면 보스에게 바인딩
	if (Boss != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Boss Connect"));
		Boss->OnBossDeadDelegate.AddUObject(this, &AMinion::DeadAll);
		Boss->OnMinionsSendBuffDelegate.AddUObject(this, &AMinion::AddBuff); //2-4. 찾은 보스액터를 캐스팅 한 후, OnMinionsSendBuffDelegate를 구독
		Boss->OnOtherMinionsSendBuffDelegate.AddUObject(this, &AMinion::OtherBuff);
	}
}

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

}​
// Boss.cpp

#include "Boss.h"

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

	//보스 마나 초기값 부여
	BossMana = 100.0;
}

// Called when the game starts or when spawned
void ABoss::BeginPlay()
{
	Super::BeginPlay();
	
	//델리게이트 자기자신에게 바인딩
	OnUseManaDelegate.BindUObject(this, &ABoss::UseMana); //1-3. 바인딩
}

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

	//보스가 소멸하면 델리게이트 제거
	OnBossDeadDelegate.Clear();
	OnMinionsSendBuffDelegate.Clear();
	OnOtherMinionsSendBuffDelegate.Clear();
	OnUseManaDelegate.Unbind();
}

void ABoss::CallDie()
{
	//연결된 객체에서 이벤트(델리게이트) 전달
	if (OnBossDeadDelegate.IsBound())
	{
		OnBossDeadDelegate.Broadcast();
	}

	//소멸
	Destroy();
}

void ABoss::SendBuff(int32 Num)
{
	if (OnUseManaDelegate.IsBound())//1-4. OnUseManaDelegate를 바인딩하고 있는게 있는지 체크
	{
		OnUseManaDelegate.Execute(10.0);//1-5. Execute로 이전에 지정한 &ABoss::UseMana 호출(끝)
	}

	if (OnMinionsSendBuffDelegate.IsBound())//2-5. OnMinionsSendBuffDelegate를 바인딩하고 있는게 있는지 체크
	{
		OnMinionsSendBuffDelegate.Broadcast(Num);//2-6. Broadcast로 구독하고있는 클래스의 지정된 함수를 호출(끝)
	}

	//마나가 0이되면 자폭
	if (IsEmptyMana())
	{
		CallDie();
	}
}

void ABoss::SendToOtherBuff(int32 Num)
{
	if (OnUseManaDelegate.IsBound())
	{
		OnUseManaDelegate.Execute(20.0);
	}

	if (OnOtherMinionsSendBuffDelegate.IsBound())
	{
		OnOtherMinionsSendBuffDelegate.Broadcast(Num);
	}

	//마나가 0이되면 자폭
	if (IsEmptyMana())
	{
		CallDie();
	}
}

void ABoss::UseMana(float UsedManaValue)
{
	if (BossMana <= 0)
	{
		BossMana = 0;
	}
	else
	{
		BossMana -= UsedManaValue;
	}

	UE_LOG(LogTemp, Warning, TEXT("Remained Mana : %f"), BossMana);
}

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

}​
// Minion.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Minion.generated.h"

class ABoss;

UCLASS()
class UNREALCPP5_API AMinion : public AActor
{
	GENERATED_BODY()

protected:
	ABoss* Boss;

private:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"));
	int32 Index;

public:
	// Sets default values for this actor's properties
	AMinion();

public:
	UFUNCTION()
	void AddBuff(int32 Value);

	UFUNCTION()
	void DeadAll();

	UFUNCTION()
	void OtherFuncDead();

	UFUNCTION()
	void OtherBuff(int32 Value);

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;

};
// Boss.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Boss.generated.h"

DECLARE_MULTICAST_DELEGATE(FBossDeadMultiDele) //
DECLARE_MULTICAST_DELEGATE_OneParam(FMinonSendBuffMultiDele, int32) //2-1. 멀티델리게이트 지정
DECLARE_MULTICAST_DELEGATE_OneParam(FOtherMinonSendBuffMultiDele, int32)
DECLARE_DELEGATE_OneParam(FUseManaDele, float) //1-1. 싱글델리게이트 지정

UCLASS()
class UNREALCPP5_API ABoss : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ABoss();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

private:
	float BossMana;

public:
	FBossDeadMultiDele OnBossDeadDelegate;
	FMinonSendBuffMultiDele OnMinionsSendBuffDelegate; //2-2. 변수 지정
	FOtherMinonSendBuffMultiDele OnOtherMinionsSendBuffDelegate;
	FUseManaDele OnUseManaDelegate; //1-2. 변수 지정

public:
	UFUNCTION(BlueprintCallable)
	void CallDie();

	UFUNCTION(BlueprintCallable)
	void SendBuff(int32 Num);

	UFUNCTION(BlueprintCallable)
	void SendToOtherBuff(int32 Num);

	UFUNCTION(BlueprintCallable)
	void UseMana(float UsedManaValue);

	FORCEINLINE bool IsEmptyMana()
	{
		return BossMana <= 0;
	}

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

};
반응형

'Unreal5 > 기본개념' 카테고리의 다른 글

[최적화] 오브젝트 풀링  (6) 2025.08.02
[설계] BP vs C++  (2) 2025.06.08
[언리얼5] BP 아이콘  (0) 2025.02.24
[언리얼5] 라이팅모드  (0) 2025.02.12
[언리얼5] 기본 최적화 방안  (0) 2025.02.08