언리얼의 Delegate
(델리게이트), multiCastDelegate
(멀티캐스트 델리게이트),DynamicDelegate
(다이나믹 델리게이트)
그리고 Event
(이벤트)에대해 알아보겠습니다.
Delegate
는 C++오브젝트 상의 멤버함수를 안전하게 호출할수 있는 기능이다.
Delegate
로 지정한 오브젝트의 멤버함수를 동적으로 바인딩 시킬수있어 유동적으로 사용가능하다.
Delegate
는 호출하고자하는 함수를 갖고있는 오브젝트의 유형을 알필요가없다.
Delegate
를 사용할때 값 전달이 가능하지만 이때 heap
메모리에 할당하기에 참조 전달 방식이 권장된다.
Delegate
는 싱글 캐스트, 멀티 캐스트 둘다지원한다.
MultiCastDelegate
는 SingleCastDelegate
의 특징을 대부분 갖지만 1대n을 관리할때 사용된다.
MultiCastDelegate
는 반환값을 사용할수없다.(여러 객체마다 반환하는값이 다르기때문에)
DynamicDelegate
는 Delegate
와 일반적으로 비슷하지만
Delegate
는 빌드타임에 바인딩이 이루어지고 런타임에서는 바인딩 수정이 불가능하다.
DynamicDelegate
는 런타임에서도 동적으로 바인딩 시켜줄수있다.
Event
는 MultiCastDelegate
와 일반적으로 비슷하지만
Event
를 선언한 클래스만이 Broadcast
, IsBound
, Clear
함수를 호출할수있다.
그렇기에 외부 클래스에서 Broadcast
, IsBound
, Clear
함수를 제한하며 접근권을 확보할때 사용할수있다.
Delegate
선언은 제공되는 매크로중 하나로 이루어진다, 사용되는 매크로는 Delegate
와 바인딩되는 함수의 시그니처에따라 결정된다.
다음과 같은 타입들은 Delegate
의 시그니처가 지원되는 타입들이다.
- 값을 반환하는 함수
- "페이로드"(payload, 유상) 변수 4 개 까지
- 함수 파라미터 8 개 까지
- 'const' 로 선언된 함수
시그니처 에따른 Delegate
매크로들은 다음과 같다.
함수 시그너처 | 선언 매크로 |
---|---|
void Function() | DECLARE_DELEGATE( DelegateName ) |
void Function( <Param1> ) | DECLARE_DELEGATE_OneParam( DelegateName, Param1Type ) |
void Function( <Param1>, <Param2> ) | DECLARE_DELEGATE_TwoParams( DelegateName, Param1Type, Param2Type ) |
void Function( <Param1>, <Param2>, ... ) | DECLARE_DELEGATE_<Num>Params( DelegateName, Param1Type, Param2Type, ... ) |
<RetVal> Function() | DECLARE_DELEGATE_RetVal( RetValType, DelegateName ) |
<RetVal> Function( <Param1> ) | DECLARE_DELEGATE_RetVal_OneParam( RetValType, DelegateName, Param1Type ) |
<RetVal> Function( <Param1>, <Param2> ) | DECLARE_DELEGATE_RetVal_TwoParams( RetValType, DelegateName, Param1Type, Param2Type ) |
<RetVal> Function( <Param1>, <Param2>, ... ) | DECLARE_DELEGATE_RetVal_<Num>Params( RetValType, DelegateName, Param1Type, Param2Type, ... ) |
Delegate
선언은 글로벌, 네임스페이스 안, 클래스 선언부(함수본문 제외) 영역에서 선언이가능하다.
MultiCastDelegate
또한 표준Delegate
선언과 크게 다르지않으며
MultiCastDelegate
전용 매크로를 사용한다는 차이점이 있다.
설명 | 선언 매크로 |
---|---|
멀티캐스트 델리게이트를 생성합니다. | DECLARE_MULTICAST_DELEGATE[_RetVal, etc.]( DelegateName ) |
다이내믹 멀티-캐스트 델리게이트를 생성합니다. | DECLARE_DYNAMIC_MULTICAST_DELEGATE[RetVal, etc.]( DelegateName ) |
DynamicDelegate
또한 표준Delegate
선언과 크게 다르지않으며
DynamicDelegate
전용 매크로를 사용한다는 차이점이 있다.
설명 | 선언 매크로 |
---|---|
다이나믹 델리게이트를 생성합니다. | DECLARE_DYNAMIC_DELEGATE[_RetVal, etc.]( DelegateName ) |
다이나믹 멀티-캐스트 델리게이트를 생성합니다. | DECLARE_DYNAMIC_MULTICAST_DELEGATE[_RetVal, etc.]( DelegateName ) |
Event
또한 표준Delegate
선언과 크게 다르지않으며
Event
전용 매크로를 사용한다는 차이점이 있다.
설명 | 선언 매크로 |
---|---|
이벤트를 생성합니다. | DECLARE_EVENT( OwningType, EventName ) |
파라미터가 하나인 이벤트를 생성합니다. | DECLARE_EVENT_OneParam( OwningType, EventName, Param1Type ) |
파라미터가 둘인 이벤트를 생성합니다. | DECLARE_EVENT_TwoParams( OwningType, EventName, Param1Type, Param2Type ) |
파라미터가 N 개인 이벤트를 생성합니다. | DECLARE_EVENT_<Num>Params( OwningType, EventName, Param1Type, Param2Type, ... ) |
DECLARE_EVENT
매크로의 첫 파라미터는 이 이벤트를 "소유"(own)하게 될 클래스, 즉 Broadcast()
함수를 호출할 수 있는 클래스이다.Delegate
시스템은 특수한기능도 제공한다, UObject나 공유 포인터 클래스를 바인딩 한경우 약한 레퍼런스를 유지할수있다.
이는 Delegate
치하에서 오브젝트가 소멸한경우 IsBound()
나 ExecuteIfBound()
함수를 처리해준다.
설명 | 함수 |
---|---|
기존 델리게이트 오브젝트에 바인딩합니다. | Bind() |
raw C++ 포인터 글로벌 함수 델리게이트를 바인딩합니다. | BindStatic() |
날(raw) C++ 포인터 델리게이트에 바인딩합니다. 날 포인터는 어떠한 종류의 레퍼런스도 사용하지 않아, 만약 오브젝트가 델리게이트 치하에서 삭제된 경우 호출하기가 안전하지 않을 수도 있습니다. Execute() 호출시에는 조심하세요! | BindRaw() |
공유 포인터-기반 멤버 함수 델리게이트에 바인딩합니다. 공유 포인터 델리게이트는 오브젝트로의 약한 레퍼런스를 유지합니다. ExecuteIfBound() 로 호출할 수 있습니다. | BindSP() |
UObject 기반 멤버 함수 델리게이트를 바인딩합니다. UObject 델리게이트는 오브젝트로의 약한 레퍼런스를 유지합니다. ExecuteIfBound() 로 호출할 수 있습니다. | BindUObject() |
이 델리게이트 바인딩을 해제합니다. | UnBind() |
MultiCastDelegate
는 여러 개의 함수를 바인딩시켜 Delegate
가 발동되면 모두 호출되도록 할 수 있다.
그 결과, 의미론적으로 함수 바인딩이 변수같은 식에 더가깝다.
설명 | 함수 |
---|---|
이 멀티캐스트 델리게이트의 실행 목록에 함수 델리게이트를 추가합니다. | Add() |
raw C++ 포인터 글로벌 함수 델리게이트를 추가합니다. | AddStatic() |
raw C++ 포인터 델리게이트를 추가합니다. raw 포인터는 어떠한 레퍼런스도 사용하지 않기에, 오브젝트가 자신의 델리게이트 하에서 삭제된 경우 호출시 안전하지 않을 수 있습니다. Execute() 호출시 주의하세요! | AddRaw() |
공유 포인터 기반 (빠르지만 스레드 안전성은 떨어지는) 멤버 함수 델리게이트를 추가합니다. 공유 포인터 델리게이트는 자신의 오브젝트에 대한 약 레퍼런스를 유지합니다. | AddSP() |
UObject 기반 멤버 함수 델리게이트를 추가합니다. UObject 델리게이트는 자신의 오브젝트에 대한 약 레퍼런스를 유지합니다. | AddUObject() |
이 멀티캐스트 델리게이트의 실행 목록에서 함수를 제거합니다 (퍼포먼스는 O(N) 입니다). 참고로 델리게이트 순서는 유지되지 않을 수 있습니다! | Remove() |
지정된 UserObject 에 바인딩된 이 멀티캐스트 델리게이트의 실행 목록에서 모든 함수를 제거합니다. 참고로 델리게이트 순서는 유지되지 않을 수 있습니다! | RemoveAll() |
RemoveAll()
은 제공된 포인터에 바인딩된 모든 등록 Delegate
를 제거한다. 오브젝트 포인터에 바인딩되지 않은 raw Delegate
는 이 함수로 제거되지 않는다!설명 | 헬퍼 ㄹ매크로 |
---|---|
다이내믹 델리게이트에서 BindDynamic() 호출을 위한 헬퍼 매크로입니다. 함수 이름 문자열을 자동 생성합니다. | BindDynamic( UserObject, FuncName ) |
다이내믹 멀티-캐스트 델리게이트에서 AddDynamic() 호출을 위한 헬퍼 매크로입니다. 함수 이름 문자열을 자동 생성합니다. | AddDynamic( UserObject, FuncName ) |
다이내믹 멀티-캐스트 델리게이트에서 RemoveDynamic() 호출을 위한 헬퍼 매크로입니다. 함수 이름 문자열을 자동 생성합니다. | RemoveDynamic( UserObject, FuncName ) |
Event
바인딩은 MultiCastDelegate
바인딩과 같은 방식으로 이루어진다. (3-1 참고)
Delegate
를 바인딩할대 페이로드 데이터를 같이 전달해줄수있다.
바인딩 시간에 Delegate
가 파라미터를 보관할수있어 유용하게 사용가능하다.
DynamicDelegate
를 제외한 다른 모든 델리게이트들은 페이로드 변수기능을 자동으로 제공한다.
MyDelegate.BindRaw( &MyFunction, true, 20 ); // bool과 int32값을 전달
위 코드는 bool
과 int32
를 Delegate
에게 전달하는 코드이고, 이파라미터는 바인딩된 Delegate
가 실행될때 전달된다.
Delegate
에 바인딩된 함수는 Excute()
함수를 호출하여 실행한다.
Delegate
를 실행하기전 반드시 바인딩 되어있는지 확인해야한다.
Delegate
를 싱행시키면 일부 인스턴스에서 메모리에 더미데이터를 남길수도있다.IsBound()
함수를 사용해 Delegate
를 실행해도 안전한지 확인할수 있다.ExecuteIfBound()
로 반환값이없는 Delegate
를 호출할수있다, 하지만 호출 파라미터는 초기화하지 않을수 있다.
설명 | 함수 |
---|---|
델리게이트에 바인딩된 함수를 호출한다. | Execute() |
반환값이 없는 델리게이트를 호출한다. | ExecuteIfBound() |
호출할 함수가 델리게이트에 존재하는지 확인한다. | IsBound() |
MultiCastDelegate
를 통해 여러함수 Delegate
를 붙인다음, MultiCastDelegate
의 Broadcast()
함수를 통해 함수들을 호출할수 있다.
MultiCastDelegate
의 Broadcast()
함수는 아무것도 바인딩되어있지 않아도 언제나 안전하다.
하지만 Delegate
를 이용해 출력변수를 초기화하는건 매우 좋지않은 일이다.
Broadcast()
통해 호출된 함수들의 순서는 정의되지않으며, 함수가 추가된순서대로 실행되지 않을수있다.
설명 | 함수 |
---|---|
모든 오브젝트로 호출을 시도한다. | Broadcast() |
DynamicDelegate
실행은 Delegate
실행과 같은 방식으로 이루어진다. (5. 참고)
Enevt
실행은 MultiCastDelegate
실행과 같은 방식으로 이루어진다. (5-1. 참고)
언리얼 공식 홈페이지
언리얼에서 제공하는 Delegate
들에대해 알아보았습니다.
번역이나 바로이해가가지않는 부분은 제나름대로 해석하여 수정해보았습니다
공부를 위해 기술하는만큼 잘못된부분이있다면 댓글로 남겨주시기바랍니다!