언리얼 엔진 델리게이트와 이벤트

민트맛치킨·2025년 10월 28일

Unreal

목록 보기
14/26

델리게이트

델리게이트는 언리얼 엔진의 타입 안전 함수 포인터 시스템
함수를 변수처럼 저장하고 나중에 호출할 수 있으며 여러 객체 간 통신을 가능하게 함

델리게이트의 역할

  • 옵저버 패턴 구현 : 하나의 이벤트 발생 시 여러 리스너에게 알림
  • 느슨한 결합 : 클래스 간 직접 참조 없이 통신
  • 콜백 시스템 : 비동기 작업 완료, 타이머, UI 이벤트 처리
  • 멀티캐스트 통신 : 1개의 발신자가 N개의 수신자에게 알림

델리게이트 타입

1. Static Delegate (정적 델리게이트)

C++ 전용, 블루프린트 노출 불가능한 가장 빠른 델리게이트

DECLARE_DELEGATE(FSimpleDelegate);
DECLARE_DELEGATE_OneParam(FIntDelegate, int32, Value);

2. Static Multicast Delegate

여러 함수를 바인딩할 수 있는 정적 델리게이트

DECLARE_MULTICAST_DELEGATE(FSimpleMulticast);
DECLARE_MULTICAST_DELEGATE_TwoParams(FScoreDelegate, int32, Score, FString, PlayerName);

3. Dynamic Delegate

블루프린트 노출 가능한 단일 바인딩 델리게이트

DECLARE_DYNAMIC_DELEGATE(FOnComplete);
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnResult, bool, bSuccess);

4. Dynamic Multicast Delegate

블루프린트 노출 가능한 다중 바인딩 델리게이트

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnEvent);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHealthChanged, float, NewHealth, float, MaxHealth);

델리게이트 타입 비교

타입바인딩 개수블루프린트 지원직렬화속도주요 용도
Static Single1개불가불가가장 빠름C++ 콜백
Static Multicast여러 개불가불가빠름C++ 이벤트
Dynamic Single1개가능가능느림BP 콜백
Dynamic Multicast여러 개가능가능느림BP 이벤트

Single vs Multicast 차이

Single Delegate (단일 바인딩)

하나의 함수만 바인딩 가능하며 새로운 함수를 바인딩하면 이전 함수는 제거

FOnComplete OnComplete;
OnComplete.BindDynamic(this, &AMyActor::Function1);  // Function1 바인딩
OnComplete.BindDynamic(this, &AMyActor::Function2);  // Function1 제거, Function2로 교체
OnComplete.Execute();  // Function2만 실행

Multicast Delegate (다중 바인딩)

여러 함수를 누적해서 바인딩 가능하며 Broadcast 시 모두 실행

FOnEvent OnEvent;
OnEvent.AddDynamic(this, &AMyActor::Function1);  // Function1 추가
OnEvent.AddDynamic(this, &AMyActor::Function2);  // Function2 추가
OnEvent.Broadcast();  // Function1, Function2 모두 실행

사용 시점 비교

구분Single DelegateMulticast Delegate
반환 값가능불가
사용 케이스타이머 콜백, 비동기 작업 완료게임 이벤트, UI 업데이트, 상태 알림
실행 방식Execute()Broadcast()
바인딩 방식Bind (교체)Add (누적)

C++ 델리게이트 함수

함수용도SingleMulticast
BindDynamic함수 바인딩 (교체)가능불가
AddDynamic함수 추가 (누적)불가가능
RemoveDynamic함수 제거불가가능
Execute델리게이트 실행가능불가
Broadcast모든 함수 실행불가가능
IsBound바인딩 여부 확인가능가능
Clear모든 바인딩 제거가능가능

Add vs AddDynamic 차이

Add - Static Delegate용

Static Delegate는 함수 포인터(메모리 주소)를 직접 저장

DECLARE_MULTICAST_DELEGATE(FStaticEvent);
FStaticEvent OnEvent;
OnEvent.Add(this, &AMyActor::HandleEvent);  // 함수 포인터 저장

AddDynamic - Dynamic Delegate용

Dynamic Delegate는 함수 이름(문자열)을 저장하고 리플렉션으로 런타임에 검색

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDynamicEvent);
FDynamicEvent OnEvent;
OnEvent.AddDynamic(this, &AMyActor::HandleEvent);  // 함수 이름 저장

AddDynamic의 내부 동작

AddDynamic은 매크로이며 함수 이름을 자동으로 추출

// 작성한 코드
OnEvent.AddDynamic(this, &AMyActor::HandleEvent);

// 실제로 확장되는 코드
OnEvent.__Internal_AddDynamic(this, &AMyActor::HandleEvent, FName("HandleEvent"));

런타임에 "HandleEvent"라는 이름으로 함수를 검색해서 호출하므로 해당 함수가 리플렉션 시스템에 등록되어 있어야 함

Add vs AddDynamic 비교

항목AddAddDynamic
대상 델리게이트Static DelegateDynamic Delegate
저장 방식함수 포인터 (메모리 주소)함수 이름 (FName 문자열)
호출 방식포인터로 직접 호출이름으로 검색 후 호출
속도빠름느림 (리플렉션 오버헤드)
UFUNCTION 필요불필요필수
바인딩 가능 대상모든 함수, 람다, 일반 함수UFUNCTION만
직렬화불가가능
블루프린트 노출불가가능

블루프린트 Event Dispatcher

C++에서 UPROPERTY(BlueprintAssignable)로 선언한 Dynamic Delegate는 블루프린트에서 Event Dispatcher로 표시됨

BlueprintAssignable의 역할

// BlueprintAssignable 있음 - 블루프린트에서 보임
UPROPERTY(BlueprintAssignable)
FOnHealthChanged OnHealthChanged;

// BlueprintAssignable 없음 - 블루프린트에서 안 보임
UPROPERTY()
FOnHealthChanged OnHealthChangedInternal;

델리게이트와 이벤트의 차이

과거 언리얼 엔진 4

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와 기능상 차이가 없다.

현재 언리얼 엔진 5

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 (소유자만)
사용 목적콜백, 함수 저장이벤트 알림, 옵저버 패턴

0개의 댓글