Delegate(델리게이트)란?
어떤 이벤트가 발생했을 때 함수를 바인딩해서 호출할 수 있도록 해줍니다. Observer Pattern (옵저버 패턴) 을 언리얼스럽게 구현한 것이라고 생각하면 이해하기 쉽습니다.
쉽게 말해 "이 일이 일어나면 이 함수들을 호출해줘" 라고 등록하는 것.
예를 들어, 게임에서 캐릭터가 데미지를 입으면 체력값을 업데이트해야 한다. 하지만 캐릭터는 HUD나 UI를 직접 참조할 경우 코드 간 의존성이 높아지게 된다. 그래서 캐릭터 클래스트는 Delegate를 통해 체력값이 변경됨을 Delegate를 통해 Execute(Broadcast)하고 HUD나 UI는 그 Delegate를 바인딩해서 체력을 업데이트한다.
혹은 퀘스트를 완료한다고 해보자. 그럼 퀘스트를 완료를 처리하는 함수, 상호작용을 처리하는 함수, UI를 변경하는 함수 등 한번에 다양한 함수들이 호출될 필요가 있다. 이럴때 상호작용은 단순히 Delegate를 호출하고, 이를 필요로 하는 오브젝트나 시스템에서 이를 바인딩해서 반응하는 구조를 만들면 된다.
이처럼 Delegate를 활용함으로써 코드의 결함을 줄이면서, 유연하고 확장성있는 코드를 만들 수 있다.
Delegate의 종류
언리얼에서 대표적으로 사용가능한 Delegate의 종류는 4가지가 있다.
1. Single-cast Delegate (일반 Delegate) - 하나의 함수만 바인딩 가능.
- 단순한 콜백 처리에 사용.
- C++ 내부에서만 사용.
DECLARE_DELEGATE(FSimpleDelegate);
DECLARE_DELEGATE_OneParam(FOneParamDelegate, int32);2. Multi-cast Delegate (멀티 Delegate)
- 여러 개의 함수(리스너)를 동시에 바인딩 가능.
- 여러 개의 함수에 브로드캐스팅용 (ex: 체력 변경 시 여러 곳에 알림).
- C++ 내부에서만 사용.
DECLARE_MULTICAST_DELEGATE(FSimpleMulticastDelegate);
DECLARE_MULTICAST_DELEGATE_OneParam(FOneParamMulticastDelegate, float);3. Dynamic Delegate (블루프린트 바인딩용 단일 Delegate)
- 블루프린트에서도 바인딩 가능.
- 리플렉션(Reflective) 시스템 사용.
DECLARE_DYNAMIC_DELEGATE(FDynamicDelegate);
DECLARE_DYNAMIC_DELEGATE_OneParam(FDynamicOneParamDelegate, int32, Param);4. Dynamic Multicast Delegate (블루프린트 바인딩용 멀티 Delegate)
- 블루프린트에서도 연결 가능.
- 여러 리스너를 바인딩 가능.
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDynamicMulticastDelegate);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDynamicMulticastOneParamDelegate, float, NewHealth);| 종류 | 바인딩 수 | 블루프린트 함수 연결 | |-|-|-| | Single-cast Delegate | 단일 | ❌ | | Multi-cast Delegate | 다중 | ❌ | | Dynamic Delegate | 단일 | ✅ | | Dynamic Multicast Delegate | 여러 개 | ✅|
Delegate의 사용 방법
1. Delegate 선언하기
// Single-cast Delegate
DECLARE_DELEGATE(FSimpleDelegate);
// Parameter 있는 Delegate
DECLARE_DELEGATE_OneParam(FDamageDelegate, int32);
// Multi-cast Delegate
DECLARE_MULTICAST_DELEGATE(FOnHealthChanged);
// Dynamic Delegate
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnPlayerDeath);2. Delegate 멤버 변수 선언
FSimpleDelegate OnSimpleEvent; // Single-cast Delegate
FDamageDelegate OnDamageEvent; // Parameter 있는 Delegate
FOnHealthChanged OnHealthChanged; // Multi-cast Delegate
UPROPERTY(BlueprintAssignable) // 블루프린트에서 사용가능하도록 설정
FOnPlayerDeath OnPlayerDeath; // Dynamic Delegate3. Delegate 바인딩하기
void AMyActor::BeginPlay()
{
Super::BeginPlay();
// 바인딩 (람다 / 함수 포인터 / 멤버 함수)
OnSimpleEvent.BindUObject(this, &AMyActor::HandleSimpleEvent); // Single-cast Delegate 바인딩
OnDamageEvent.BindUObject(this, &AMyActor::HandleDamageEvent); // Parameter 있는 Delegate 바인딩
OnHealthChanged.AddUObject(this, &AMyActor::NotifyHealthChanged); // Multi-cast Delegate 바인딩
}
void AMyActor::HandleSimpleEvent()
{
UE_LOG(LogTemp, Warning, TEXT("Simple Event Triggered!"));
}
void AMyActor::HandleDamageEvent(int32 Damage)
{
UE_LOG(LogTemp, Warning, TEXT("Received Damage: %d"), Damage);
}
void AMyActor::NotifyHealthChanged()
{
UE_LOG(LogTemp, Warning, TEXT("Health Changed!"));
}블루프린트 내부에서 바인딩 시: 
- Bind Event to "DelegateName" - Create Event(Blueprint에서 실행시킬 Event 선택)
Delegate 호출하기
void AMyActor::DelegateExecuteFunction()
{
if (OnSimpleEvent.IsBound())
{
OnSimpleEvent.Execute(); // Single-cast Delegate 호출
}
if (OnDamageEvent.IsBound())
{
OnDamageEvent.Execute(50); // Parameter 있는 Delegate 호출
}
OnHealthChanged.Broadcast(); // Multi-cast Delegate 호출
}