공식문서의 내용
C++ 는 어떠한 형태의 리플렉션도 지원하지 않아, 언리얼에는 자체적으로 C++ 클래스, 구조체, 함수, 멤버 변수, 열거형 관련 정보를 수집, 질의, 조작하는 별도의 시스템이 구축되어 있다. 전형적으로 이러한 리플렉션은 '프로퍼티 시스템'이라고 부르는데, '리플렉션'은 그래픽 용어이기도 하기 때문.
리플리케이션 시스템은 옵션입이다. 리플렉션 시스템에 보이도록 했으면 하는 유형이나 프로퍼티에 주석을 달아주면, Unreal Header Tool (UHT)가 그 프로젝트를 컴파일할 때 해당 정보를 수집한다.
헤더에 리플렉션이 있는 유형으로 마킹을 하려면, 파일 상단에 특수한 include 를 추가해 줘야 한다. 그러면 리플렉션이 있는 유형은 이 파일을 고려해야 함을, 시스템 구현에도 필요함을 UHT 에 알려준다.
#include "FileName.generated.h"
UENUM(), UCLASS(), USTRUCT(), UFUNCTION(), UPROPERTY() 를 사용하여 헤더의 다양한 유형과 멤버 변수 주석을 달 수 있다.
ex)
#include "StrategyTypes.h"
#include "StrategyChar.generated.h"
UCLASS(Abstract)
class AStrategyChar : public ACharacter, public IStrategyTeamInterface
{
GENERATED_UCLASS_BODY()
/** How many resources this pawn is worth when it dies. */
UPROPERTY(EditAnywhere, Category=Pawn)
int32 ResourcesToGather;
/** set attachment for weapon slot */
UFUNCTION(BlueprintCallable, Category=Attachment)
void SetWeaponAttachment(class UStrategyAttachment* Weapon);
UFUNCTION(BlueprintCallable, Category=Attachment)
bool IsWeaponAttached();
protected:
/** melee anim */
UPROPERTY(EditDefaultsOnly, Category=Pawn)
UAnimMontage* MeleeAnim;
/** Armor attachment slot */
UPROPERTY()
UStrategyAttachment* ArmorSlot;
/** team number */
uint8 MyTeamNum;
[이하 코드 생략]
};
Unreal Build Tool (UBT) 와 Unreal Header Tool (UHT) 가 함께하여 실행시간 리플렉션을 강화시키는 데 필요한 데이터를 생성한다. UBT 는 그 역할을 위해 헤더를 스캔한 다음 리플렉션된 유형이 최소 하나 있는 헤더가 들어있는 모듈을 기억한다. 그 헤더 중 어떤 것이든 지난 번 컴파일 이후 변경되었다면, UHT 를 실행하여 리플렉션 데이터를 수집하고 업데이트한다. UHT 는 헤더를 파싱하고, 리플렉션 데이터 세트를 빌드한 다음, (모듈별.generated.inl 에 기여하는) 리플렉션 데이터가 들어있는 C++ 코드를 생성할 뿐만 아니라, (헤더별 .generated.h 인) 다양한 헬퍼 및 thunk 함수도 생성한다.
리플렉션 데이터를 C++ generated 코드로 저장하는 것의 한 가지 주요 장점은, 바이너리와의 동기화가 보장된다는 점이다. 오래되거나 버전이 맞지 않는 리플렉션 데이터를 로드할 일은 없는데, 나머지 엔진 코드와 함께 컴파일되기 때문이다. 그리고 특정 플랫폼/컴파일러/최적화 콤보의 패킹 작동방식을 역엔지니어링하려 하기 보다는, C++ 표현식을 사용해서 시작시 멤버 오프셋/등등을 계산하기 때문. UHT 역시도 generated 헤더를 소모하지 않는 독립형 프로그램으로 만들어졌기에, UE3 의 스크립트 컴파일러에서 흔히 발생했던 닭이냐 계란이냐 문제가 생기지 않는다.
generated 함수에는 StaticClass() / StaticStruct() 같은 것이 포함되어 있어, 유형에 대한 리플렉션 데이터를 구하는 것이 쉬워질 뿐만 아니라, 블루프린트나 네트워크 리플레키에션에서 C++ 함수를 호출하는 데 사용되는 thunk 를 구하는 것도 쉬워진다. 이는 클래스나 구조체의 일부로 선언되어야 하며, GENERATED_UCLASS_BODY() 또는 GENERATED_USTRUCT_BODY() 매크로가 리플렉션된 유형에 포함되어야 하는지에 대한 이유가 된다. 이 매크로를 정의하는 #include 'TypeName.generated.h' 는 물론이다.
'Unreal Engine' 카테고리의 다른 글
Unreal Build Tool (UBT) & Unreal Header Tool (UHT) (0) | 2023.10.05 |
---|---|
Delegate(언리얼 엔진) (1) | 2023.10.04 |
Foot Ik(Control Rig) (0) | 2023.09.30 |
Material Function(Outline Shader에 사용) (0) | 2023.09.30 |
Outline Shader - 2 (0) | 2023.09.29 |