언리얼 C++ 프로그래밍

[언리얼 C++] 다이내믹 델리게이트

언린이 2021. 6. 30. 23:33

언리얼 엔진에서 다이내믹 델리게이트는 serialize가 가능하면서 리플렉션도 지원하는 델리게이트입니다.

 

언리얼 엔진에서 델리게이트는 C++ 객체에서만 사용할 수 있는 델리게이트와 C++과 블루프린트 객체가 모두 사용할 수 있는 델리게이트로 나뉩니다. 블루프린트 객체는 멤버 함수에 대한 정보를 저장하고 로딩하는 직렬화 매커니즘이 들어있기 때문에 일반 C++ 언어가 관리하는 방법으로 멤버 함수를 관리할 수 없습니다.

그래서 블루프린트와 관련된 C++ 함수는 모두 UFUNCTION 매크로로 선언해서 사용해줘야 합니다.

이렇게 블루프린트 객체와도 연동하는 델리게이트를 다이내믹 델리게이트라고 합니다.

다이내믹 델리게이트는 이러한 동작원리 때문에 일반 델리게이트보다 다소 느릴 수 있습니다.

 

 

1. 다이내믹 델리게이트 선언하기

DECLARE_DYNAMIC_DELEGATE(FDynamicDele) // 다이내믹 델리게이트 선언

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDynamicMultiDele) // 다이내믹 멀티캐스트 델리게이트 선언

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDynamicMultiDele_OneParam, int) // 하나의 인자를 가지는 다이내믹 멀티캐스트 델리게이트 선언

싱글캐스트 델리게이트와 마찬가지로 함수 시그너처를 지정하여 선언할 수 있습니다.

위의 예제 코드에서 DECLARE_DYNAMIC_MULTICAST_DELEGATE 매크로로 선언한 델리게이트는 멀티캐스트 델리게이트의 성질 또한 부여하는 것인데, 멀티캐스트 델리게이트는 여러개의 함수를 바인딩할 수 있으며 바인딩된 모든 함수들을 동시에 호출하는 기능을 제공해줍니다. 그러므로 다이내믹 멀티캐스트 델리게이트는 블루프린트에서도 사용이 가능함과 동시에 여러개의 함수를 바인딩하여 사용할 수 있는 것입니다.

 

 

2. 다이내믹 델리게이트 바인딩하기

함수 설명
BindDynamic(UserObject, FuncName) 다이내믹 델리게이트에서 BindDynamic() 호출을 위한 헬퍼 매크로입니다.
함수 이름 문자열을 자동 생성합니다.
AddDynamic(UserObject, FuncName) 다이내믹 멀티캐스트 델리게이트에서 AddDynamic() 호출을 위한 헬퍼 매크로입니다.
함수 이름 문자열을 자동 생성합니다.
RemoveDynamic(UserObject, FuncName) 다이내믹 멀티캐스트 델리게이트에서 RemoveDynamic() 호출을 위한 헬퍼 매크로입니다.
함수 이름 문자열을 자동 생성합니다.

위의 함수들은 언리얼 엔진에서 제공하는 다이내믹 델리게이트 바인딩 함수들입니다.

BindDynamic() 함수는 다이내믹 싱글캐스트 델리게이트에 함수를 바인딩하는 함수입니다. 당연히 싱글캐스트 델리게이트이기 때문에 한가지 함수밖에 바인딩하지 못합니다.

AddDynamic() 함수는 다이내믹 멀티캐스트 델리게이트에 함수를 바인딩하는 함수입니다. 이는 멀티캐스트 델리게이트이므로 여러개의 함수를 바인딩할 수 있습니다.

마지막으로 RemoveDynamic() 함수는 다이내믹 멀티캐스트 델리게이트에서 바인딩한 함수를 삭제하는 함수입니다.

 

DECLARE_DYNAMIC_DELEGATE(FDynamicDele)
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDynamicMultiDele)

UCLASS()
class TestProject_API ASampleActor : public AActor
{
	GENERATED_BODY()
    
public :
	FDynamicDele OnAttackStartDelegate;
	FDynamicMultiDele OnAttackEndDelegate;
};

액터 클래스를 상속받은 클래스에서 공격을 시작했을때와 공격이 끝날때 호출되는 델리게이트를 생성해주었습니다.

 

USampleAnim::NativeInitializeAnimation()
{
	Super::NativeInitializeAnimation();
    
    ASampleActor* pActor = Cast<ASampleActor>(TryGetPawnOwner());
    
    pActor->OnAttackStartDelegate.BindDynamic(this, &USampleAnim::AttackStart);
    
    pActor->OnAttackEndDelegate.AddDynamic(this, &USampleAnim::AttackEnd);
    pActor->OnAttackEndDelegate.AddDynamic(this, &USampleAnim::UpdatePlayer);
    pActor->OnAttackEndDelegate.AddDynamic(this, &USampleAnim::UpdatePlayerStat);
}

그리고 공격을 시작했을때 호출할 델리게이트는 싱글캐스트 델리게이트이기 때문에 BindDynamic() 함수를 사용하여 하나의 함수를 바인딩해주었습니다.

또한, 공격이 끝날때 호출할 델리게이트는 멀티캐스트 델리게이트이기 때문에 AddDynamic() 함수를 사용하여 여러개의 함수를 바인딩해주었습니다.

이제 해당 델리게이트들의 실행 함수를 호출하면 바인딩된 함수들이 실행될 것입니다.

 

 

3. 다이내믹 델리게이트 실행하기

함수 설명
Execute() 다이내믹 델리게이트에 바인딩된 함수를 실행합니다.
ExecuteIfBound() 다이내믹 델리게이트에 바인딩된 함수를 확인하고 존재하면 함수를 실행합니다.
IsBound() 다이내믹 델리게이트에 바인딩된 함수를 확인합니다.

이 함수들은 다이내믹 싱글캐스트 델리게이트의 실행 함수들이고,

 

함수 설명
Broadcast() 델리게이트를 만료되었을 수도 있는 것을 제외하고, 바인딩된 모든 오브젝트에 뿌립니다.

이 함수는 멀티캐스트 델리게이트의 실행 함수입니다. 다이내믹 멀티캐스트 델리게이트 또한 해당 함수로 실행해줘야 합니다.

 

ASampleActor* pActor = Cast<ASampleActor>(TryGetPawnOwner());
    
pActor->OnAttackStartDelegate.ExecuteIfBound();

pActor->OnAttackEndDelegate.Broadcast();

위 예제 코드처럼 각각의 실행 함수를 사용하여 해당 델리게이트들이 실행되어야 하는 부분에서 실행해주면 됩니다.

 

 

이렇게 다이내믹 델리게이트를 사용하는 방법에 대해 알아보았습니다.

마지막으로 다이내믹 델리게이트는 C++ 객체에서 뿐만아니라 블루프린트 객체에서 또한 멤버 함수를 바인딩할 수 있기때문에 효율적으로 사용한다면 다양한 효과들을 구현할 수 있을 것입니다.