Delegate
언리얼 엔진에서도 delegate을 이용할 수 있다. 먼저 delegate의 시그니쳐를 정의하여한다. 시그니쳐는 언리얼에서 제공하는 메크로를 통해 정의할 수 있는데, 싱글 delegate와 멀티 delegate가 있다. 싱글 delegate에는 함수를 한 개만 bind 가능하지만, 멀티 delegate에는 여러개의 함수를 bind 할 수 있다. 그리고 메크로에 몇개의 파라메터를 넣을 것인지까지 메크로 이름으로 구분되어 있다. 일반 delegate와 달리 다이나믹 delegate가 있는데 이는 블루프린트에서도 이용이 가능한 delegate이다.
// 싱글 일반 delegate, 파라메터 x
DECLARE_DELEGATE(FDelegateSingleSignature);
// 싱글 일반 delegate, 파라메터 int32
DECLARE_DELEGATE_OneParam(FDelegateSingleOneParamSignature, int32);
// 멀티 일반 delegate, 파라메터 int32
DECLARE_MULTICAST_DELEGATE_OneParam(FDelegateMultiOneParamSignature, int32);
// 멀티 다이나믹 delegate, 파라메터 int32
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDelegateDynamicOneParamSignature, int32, InValue);
시그니쳐가 정의되었다면, 시그니쳐를 이용하여 delegate 변수를 정의하여야 한다. 다음과 같이 정의한다.
다이나믹 delegate의 경우 블루프린트에서 add, remove가 가능하기 때문에 UPROPERTY로 인터페이스를 열어둔다.
참고로 다이나믹 delegate에 바인딩 될 함수는 UFUNCTION() 메크로를 붙여주어야 한다.
// define delegate signature here
class UMovementSpeedComponent : public UActorComponent
{
GENERATED_BODY()
// ..
public:
FDelegateSingleSignature OnTriggerSingle;
FDelegateSingleOneParamSignature OnTriggerSingleOneParam;
FDelegateMultiOneParamSignature OnTriggerMultiOneParam;
UPROPERTY(BlueprintAssignable)
FDelegateDynamicOneParamSignature OnTriggerDynamicOneParam;
void SomeMethod();
UFUNCTION()
void SomeMethodOneParam(int32 InValue);
void TriggerAllEvents()
};
변수까지 정의된 후에는 delegate에 함수를 bind 해야한다. BeginPlay 함수에서 바인딩을 수행한다. 싱글 타입의 경우 Bind로 시작하는 바인딩 함수를 이용하고, 멀티 타입의 경우 Add로 시작하는 바인딩 함수를 이용한다. 다이나믹 타입의 경우는 Dynamic으로 끝나는 바인딩 함수를 이용한다. 바인딩 함수에도 여러 종류가 있는데, 여기서는 UObject를 이용하여 this까지 넘겨주는 형태의 바인딩 함수만 이용하도록 한다.
그리고 사용 후, 객체가 제거되기 전에 바인드된 모든 delegate들을 제거해주어야 한다. EndPlay 함수에서 언바인딩을 수행한다.
Delegate을 사용할 때에는 delegate의 Execute, Broadcast와 같은 함수를 이용하면 된다. TriggerAllEvents 함수에서 delegate을 호출시킨다.
void UMovementSpeedComponent::BeginPlay()
{
Super::BeginPlay();
this->OnTriggerSingle.BindUObject(this, &UMovementSpeedComponent::SomeMethod);
this->OnTriggerSingleOneParam.BindUObject(this, &UMovementSpeedComponent::SomeMethodOneParam);
this->OnTriggerMultiOneParam.AddUObject(this, &UMovementSpeedComponent::SomeMethodOneParam);
this->OnTriggerDynamicOneParam.AddDynamic(this, &UMovementSpeedComponent::SomeMethodOneParam);
}
void UMovementSpeedComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
this->OnTriggerSingle.Unbind();
this->OnTriggerSingleOneParam.Unbind();
this->OnTriggerMultiOneParam.Clear();
this->OnTriggerDynamicOneParam.Clear();
}
void UMovementSpeedComponent::SomeMethod()
{
// do something
}
void UMovementSpeedComponent::SomeMethodOneParam(int32 InValue)
{
// do something
}
void UMovementSpeedComponent::TriggerAllEvents()
{
if(this->OnTriggerSingle.IsBound())
this->OnTriggerSingle.Execute();
if(this->OnTriggerSingleOneParam.IsBound())
this->OnTriggerSingleOneParam.Execute(13);
if(this->OnTriggerMultiOneParam.IsBound())
this->OnTriggerMultiOneParam.Broadcast(12);
if(this->OnTriggerDynamicOneParam.IsBound())
this->OnTriggerDynamicOneParam.Broadcast(456);
}
기타
AddDynamic
Dynamic delegate에 함수를 추가할 수 있다.
AddUniqueDynamic
Dynamic delegate에 함수를 unique하게 추가할 수 있다.
Unique의 예로, 이미 추가된 함수는 다시 추가되지 않는다.
Delegate의 레퍼런스 정리
Actor1에서 다른 Actor2의 Delegate에 자신의 함수를 추가하는 상황을 가정해보자.
Actor1이 파괴될 때 Actor2의 Delegate에 함수가 계속 남아있다면 문제가 생길 수 있을 것이다.
하지만 이는 언리얼 내부에서 레퍼런스 관리를 통해 제거해주므로 문제없이 동작한다.
Delegate에 넣은 함수를 override 하는 경우
부모 클래스의 함수를 Delegate에 추가한 후, 자식 클래스가 그 함수를 override하는 경우
Delegate가 Broadcast될 떄 자식 클래스의 함수가 호출된다.
'게임 엔진 > Unreal' 카테고리의 다른 글
[Unreal] [Example] 인공지능 에이전트 (AISense) (0) | 2021.01.10 |
---|---|
[Unreal] 테이블 데이터 이용 방법 (DataTable) (0) | 2020.12.30 |
[Unreal] [Example] 타이머 이용 방법 (Timer) (0) | 2020.12.15 |
[Unreal] [Example] C++에서 Blueprint 호출, Blueprint에서 C++ 호출 (0) | 2020.11.16 |
[Unreal] 인공지능 에이전트 개발 방법 (AIController, BehaviorTree, Blackboard, Decorator, Service, Task) (0) | 2020.10.22 |