본문 바로가기
Unreal Engine

UPROPERTY는 어떻게 동작하는가?

by PainDiver 2022. 11. 25.

 

 

언리얼엔진을 보면 에디터에서 디테일한 정보들을 수정하거나 우리 육안으로 직접 볼 수 있다.

 

직렬화나 가비지콜렉션, 네트워크 리플리케이션 등 옵션들을 에디터 패널을 이용해서 블루프린트에서도 설정할 수 있지 않은가?

 

우리가 이 시스템들을 에디터상에서 볼 수 있고 동작시킬 수 있는 이유가 Reflection 기능이다.

 

그러나 C++은 이런 Reflection개념은 없고 언리얼엔진이 따로 만든거다.

 

그래서 언리얼엔진이 우리가 작성하는 C++클래스에서 어떤 것이 리플렉션되어야 하는지 추출해 내야 한다.

C++로 아무 클래스(빈 깡통말고)를 만들어 보면 UCLASS() 이런게 클래스위에 착 붙어있다.

 

바로 이게 Reflection 시스템을 사용하기 위한 지정자 U매크로라는 것 이다.

 

찾아보면 UCLASS()말고도 많다, UPROPERTY(), UFUNCTION(), UENUM(), USTRUCT() 죄다 U시리즈로 되어있다.

 

뭐 여기까지는 언리얼엔진을 조금이라도 쓴 사람이라면 다 알 것이다.

 

그런데 이 U매크로들이 어떻게 작동하는지는 딱히 알아본 적이 없던 것 같아서 게시물로 올린다.

 

우선 이 U매크로들은 언리얼헤더툴이 컴파일을 할 때 추출해서 프로젝트에 적용시킨다.

 

U매크로의 이름에 맞게 뒤에나오는 타입들을 쏙 추출하는 거고 타입명과 U매크로가 일치해야된다 

(UCLASS면 class를 정의할 때 사용해야된다.)

 

자,  다음 코드를 보면

#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;

	[more code omitted]
};

 

이 헤더에서는 AStrategyChar라고 불리는 새로운 클래스가 ACharacter에서 상속받고 있다.

여기선 UCLASS가 쓰였고, 바디에는 GENERATED_UCLASS_BODY()가 쓰였다.

(이 코드는 5.0 이전이고, 5.0 부턴 GENERATED_BODY로 통일해서 짝을 알아서 맞춰줌)

 

여기서 GENERATED_UCLASS_BODY()가 하는 일은 매크로를 이용해서 바디안에 UCLASS로서 필요한 함수나 타입명들을 그대로 써버리는 것이다.

 

StaticClass() / StaticStruct() 같이 내가 만들지도 않았는데, 생성된 함수들이 이 GENERATED_BODY()에서 온 것이라 보면 된다. 얘내가 나중에 Reflection 시스템을 위해 사용되기 때문,

 

그럼 이 친구들은 어떻게 생성되나?

 

언리얼 빌드 툴(UBT)과 언리얼 헤더툴(UHT)이 Reflection을 적용받아야하는 데이터들을 생성시키는 것이다.

 

언리얼 빌드 툴은 소스 코드의 빌드 프로세스를 관리하고, 

언리얼 헤더툴은 헤더를 파싱하고 Reflection 데이터들을 생성하여 리플렉션 데이터를 포함하는 C++ 코드를 생성한다.

 

여기서 언리얼 빌드 툴은 헤더파일을 스캔하고 파일안에 하나라도 U매크로가 있으면 그 헤더파일를 기억하게 된다.

그리고 만약 나중에 이 헤더들 중 마지막 컴파일 이후에 하나라도 코드가 수정된 사항이 있다면 언리얼 헤더툴이 Reflection된 데이터들만 쏙쏙 뽑아서 업데이트하는 것이다.

 

그 결과가 ~~.generated.h(다양한 헬퍼함수들), ~~.generated.ini (Reflection 데이터) 파일들의 생성이다.

 

 

 

[Reference]

Unreal Property System (Reflection) (unrealengine.com)