델리게이트는 언리얼 엔진의 타입 안전 함수 포인터 시스템
함수를 변수처럼 저장하고 나중에 호출할 수 있으며 여러 객체 간 통신을 가능하게 함
C++ 전용, 블루프린트 노출 불가능한 가장 빠른 델리게이트
DECLARE_DELEGATE(FSimpleDelegate);
DECLARE_DELEGATE_OneParam(FIntDelegate, int32, Value);
여러 함수를 바인딩할 수 있는 정적 델리게이트
DECLARE_MULTICAST_DELEGATE(FSimpleMulticast);
DECLARE_MULTICAST_DELEGATE_TwoParams(FScoreDelegate, int32, Score, FString, PlayerName);
블루프린트 노출 가능한 단일 바인딩 델리게이트
DECLARE_DYNAMIC_DELEGATE(FOnComplete);
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnResult, bool, bSuccess);
블루프린트 노출 가능한 다중 바인딩 델리게이트
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnEvent);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHealthChanged, float, NewHealth, float, MaxHealth);
| 타입 | 바인딩 개수 | 블루프린트 지원 | 직렬화 | 속도 | 주요 용도 |
|---|---|---|---|---|---|
| Static Single | 1개 | 불가 | 불가 | 가장 빠름 | C++ 콜백 |
| Static Multicast | 여러 개 | 불가 | 불가 | 빠름 | C++ 이벤트 |
| Dynamic Single | 1개 | 가능 | 가능 | 느림 | BP 콜백 |
| Dynamic Multicast | 여러 개 | 가능 | 가능 | 느림 | BP 이벤트 |
하나의 함수만 바인딩 가능하며 새로운 함수를 바인딩하면 이전 함수는 제거
FOnComplete OnComplete;
OnComplete.BindDynamic(this, &AMyActor::Function1); // Function1 바인딩
OnComplete.BindDynamic(this, &AMyActor::Function2); // Function1 제거, Function2로 교체
OnComplete.Execute(); // Function2만 실행
여러 함수를 누적해서 바인딩 가능하며 Broadcast 시 모두 실행
FOnEvent OnEvent;
OnEvent.AddDynamic(this, &AMyActor::Function1); // Function1 추가
OnEvent.AddDynamic(this, &AMyActor::Function2); // Function2 추가
OnEvent.Broadcast(); // Function1, Function2 모두 실행
| 구분 | Single Delegate | Multicast Delegate |
|---|---|---|
| 반환 값 | 가능 | 불가 |
| 사용 케이스 | 타이머 콜백, 비동기 작업 완료 | 게임 이벤트, UI 업데이트, 상태 알림 |
| 실행 방식 | Execute() | Broadcast() |
| 바인딩 방식 | Bind (교체) | Add (누적) |
| 함수 | 용도 | Single | Multicast |
|---|---|---|---|
| BindDynamic | 함수 바인딩 (교체) | 가능 | 불가 |
| AddDynamic | 함수 추가 (누적) | 불가 | 가능 |
| RemoveDynamic | 함수 제거 | 불가 | 가능 |
| Execute | 델리게이트 실행 | 가능 | 불가 |
| Broadcast | 모든 함수 실행 | 불가 | 가능 |
| IsBound | 바인딩 여부 확인 | 가능 | 가능 |
| Clear | 모든 바인딩 제거 | 가능 | 가능 |
Static Delegate는 함수 포인터(메모리 주소)를 직접 저장
DECLARE_MULTICAST_DELEGATE(FStaticEvent);
FStaticEvent OnEvent;
OnEvent.Add(this, &AMyActor::HandleEvent); // 함수 포인터 저장
Dynamic Delegate는 함수 이름(문자열)을 저장하고 리플렉션으로 런타임에 검색
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDynamicEvent);
FDynamicEvent OnEvent;
OnEvent.AddDynamic(this, &AMyActor::HandleEvent); // 함수 이름 저장
AddDynamic은 매크로이며 함수 이름을 자동으로 추출
// 작성한 코드
OnEvent.AddDynamic(this, &AMyActor::HandleEvent);
// 실제로 확장되는 코드
OnEvent.__Internal_AddDynamic(this, &AMyActor::HandleEvent, FName("HandleEvent"));
런타임에 "HandleEvent"라는 이름으로 함수를 검색해서 호출하므로 해당 함수가 리플렉션 시스템에 등록되어 있어야 함
| 항목 | Add | AddDynamic |
|---|---|---|
| 대상 델리게이트 | Static Delegate | Dynamic Delegate |
| 저장 방식 | 함수 포인터 (메모리 주소) | 함수 이름 (FName 문자열) |
| 호출 방식 | 포인터로 직접 호출 | 이름으로 검색 후 호출 |
| 속도 | 빠름 | 느림 (리플렉션 오버헤드) |
| UFUNCTION 필요 | 불필요 | 필수 |
| 바인딩 가능 대상 | 모든 함수, 람다, 일반 함수 | UFUNCTION만 |
| 직렬화 | 불가 | 가능 |
| 블루프린트 노출 | 불가 | 가능 |
C++에서 UPROPERTY(BlueprintAssignable)로 선언한 Dynamic Delegate는 블루프린트에서 Event Dispatcher로 표시됨
// BlueprintAssignable 있음 - 블루프린트에서 보임
UPROPERTY(BlueprintAssignable)
FOnHealthChanged OnHealthChanged;
// BlueprintAssignable 없음 - 블루프린트에서 안 보임
UPROPERTY()
FOnHealthChanged OnHealthChangedInternal;
UE4에는 DECLARE_EVENT 매크로가 존재했고 이는 소유 클래스만 Broadcast를 호출하도록 의도된 델리게이트
DECLARE_EVENT(UHealthComponent, FOnHealthChanged)
첫 번째 파라미터로 소유 클래스를 지정하여 해당 클래스만 이벤트를 발생시키도록 설계
언리얼 엔진 4 델리게이트 소스코드의 주석
/**
* NOTE: This behavior is not enforced and this type should be
* considered deprecated for new delegates, use normal multicast instead
*/
C#에서 가져온 개념이라 C++에서는 접근 제한이 실제로 강제되지 않아 Multicast Delegate와 기능상 차이가 없다.
DECLARE_EVENT는 deprecated되었으며 DECLARE_MULTICAST_DELEGATE 사용이 권장됨
이벤트로 사용하고 싶다면 델리게이트를 private으로 선언하고 접근을 제한해야 함
Broadcast는 내부에서 호출
UCLASS()
class UHealthComponent : public UActorComponent
{
public:
void SubscribeToHealthChanged(UObject* Object, FName FunctionName)
{
OnHealthChanged.AddDynamic(Object, FunctionName);
}
void TakeDamage(float Damage)
{
CurrentHealth -= Damage;
OnHealthChanged.Broadcast(CurrentHealth, MaxHealth);
}
private:
UPROPERTY(BlueprintAssignable, meta = (AllowPrivateAccess = "true"))
FOnHealthChanged OnHealthChanged;
};
| 항목 | 델리게이트 | 이벤트 |
|---|---|---|
| 실체 | DECLARE_MULTICAST_DELEGATE | 동일한 델리게이트 |
| Broadcast 접근 | Public (누구나 가능) | Private (소유자만) |
| 사용 목적 | 콜백, 함수 저장 | 이벤트 알림, 옵저버 패턴 |