UE5

언리얼 오브젝트 리플렉션 시스템

뽀또치즈맛 2025. 3. 18. 23:09

 
 

언리얼 리플렉션 시스템이란?

 
리플렉션 시스템은 프로그램이 실행시간에 자기 자신을 조사하는 기능이다.
이는 언리얼 엔진 테크놀로지의 근간을 이루는 것으로,
에디터의 디테일 패널, 시리얼라이제이션, 가비지 콜렉션, 네트워크 리플렉션,
블프/C++ 커뮤니케이션 등 다수의 시스템에 탑재된 것이다.
 
그러나 C++는 어떠한 형태의 리플렉션도 지원하지 않아,
언리얼에는 자체적으로 C++ 클래스, 구조체, 함수, 멤버 변수, 열거형 관련 정보를
수집, 질의, 조작하는 별도의 시스템이 구축되어 있다.
전형적으로 이러한 리플렉션은 '프로퍼티 시스템'이라고 부르는데,
'리플렉션'은 그래픽 용어이기도 하기 때문이다.
 
즉 리플렉션과 프로퍼티 시스템은 같은 뜻을 가리키는
동의어이다.
 
리플리케이션 시스템은 옵션이다.
리플렉션 시스템에 보이도록 했으면 하는 유형이나 프로퍼티에 주석을 달아주면,
Ureal Header Tool [UHT]가 그 프로젝트를 컴파일할 때 해당 정보를 수집한다.
 

마크업

이러한 리플렉션을 실행시키기 위해서,
헤더에 리플렉셔닝 있는 유형으로 마킹하려면,
파일 상단에 특수한 include 를 추가해 줘야 한다.
그러면 리플렉션이 있는 유형은 이 파일을 고려해야 함과
시스템 구현에도 필요하다는 것을 UHT에 알려준다.
 
예시 코드

#include "FileName.generated.h"

 
또한
관련타입에 맞게
UENUM(),UCLASS(),USTRUCT(),UFUNCTION() 등
관련 프로퍼티를 붙여주게 되면 사용할 수 있다.
 
 

프로퍼티 시스템(=리플렉션)에 대한 유형 계층 구조

UField
UStruct
UClass (C++ class)
UScriptStruct (C++ struct)
UFunction (C++ function)
UEnum (C++ enumeration)
UProperty (C++ member variable or function parameter)
 

 
언리얼에서 UStruct는
기본적인 종합 구조체(C++ 클래스, 구조체, 함수 등 다른 멤버를 포함하는 모든 것)이며,
UClass는 그 자손으로 함수나 프로퍼티를 포함할 수 있는 반면
UFunction과 UScriptStruct는 프로퍼티만 제한된다.
 
이렇게 구축된 언리얼 오브젝트 클래스는,
 
UTypeName::StaticClass()나 FTypeName::StaticStruct()를 작성하여
리플렉션된 C++유형에 대한 정보는
UClass또는 UScriptStruct를 구할 수 있으며,
Instance->GetClass()를 사용해서
인스턴스에 대한 유형을 구할 수 있다.
 
이 말은 GetClass 함수를 통해
언리얼 헤더툴이 만들어 놓은 리플렉션 정보들을 보관한
특정 객체에 접근할 수 있다는 것이다.
 
이 언리얼 오브젝트에 접근하면서
거기에 대한 값들이라든지
정보들을 빼내올 수 있다는 뜻이다.
 
이러한 기능은 기존 C++에서 지원하지 않던 기능이다.
따라서 언리얼에서 제작하여 쓰이는 기능이며
이 기능은 언리얼 엔진 게임 시스템의 근간을 이루는 기능이다.
 
또한 이러한 기능에 필요한 UBT와 UHT는 다음과 같다.
UBT는 언리얼에 구축한 독특한 빌드 시스템이다.
UHT는 언리얼 빌드에 필요한 헤더 툴이다.
 

언리얼 오브젝트의 구성

 
언리얼 오브젝트이 구성에는 특별한 프로퍼티와 함수를 지정할 수 있다.

  • 관리되는 클래스 멤버 변수 : UPROPERTY
  • 관리되는 클래스 멤버 함수 : UFUNCTION
  • 특징 : 에디터와 연동되는 메타데이터를 심을 수 있다.

모든 언리얼 오브젝트는 클래스 정보와 함께 한다.
이 말은 즉,
클래스를 사용해 자신이 가진 프로퍼티와 함수 정보를
컴파일 타임과 런타임에서 조회할 수 있다는 것을 의미한다.
 
이렇게 다양한 기능을 제공하는 언리얼 오브젝트는
NewObjectAPI를 사용해 생성해야 한다.

 
앞서 언리얼 오브젝트에는 특별한 프로퍼티와 함수를 지정할 수 있다고 했다.
언리얼 시스템에 의해서 관리되는 클래스 멤버 변수에는 UPROPERTY 매크로를
언리얼 시스템에 의해서 관리되는 클래스 멤버 함수에는 UFUNCTION 매크로를
을 지정해준다고 했다.
이 매크로 안에 여러가지 메타 데이타를 심을 수 있다.
이는 게임 콘텐츠를 제작할 때, 
에디터와 연동되어서 여러가지 유용한 기능을 만들 수 있다.
 
이러한 모든 언리얼 오브젝트는
항상 클래스 정보와 함께 한다.
이러한 것을 UClass라는
별도의 클래스 정보를 담은 클래스가 있다.
 
이 UClass를 사용하여 자신이 가진
프로퍼티,클래스 이름, 함수 정보아 같은 다양한 정보를 
컴파일 타임, 런타임에 조회할 수 있다.
 
이렇듯 언리얼 오브젝트는 
다양한 기능을 제공하기 때문에
일반적인 C++ 객체를 생성할 때 사용되는 new()키워드가 아닌,
별도의 newObject() 라는 API를 사용해서 생성해야한다.

 
 
 

 

언리얼 오브젝트의 클래스 기본 오브젝트

 
언리얼 클래스 정보에는 클래스 기본 오브젝트 (Class Default Object)가 함께 포함되어 있다.
언리얼 기본 오브젝트는 줄여서 CDO라고 부른다.
이 CDO는 언리얼 객체가 가지는 기본값을
보관하는 템플릿 객체라고 볼 수 있다.
 
한 클래스로부터 다수의 물체를 생성해
게임 콘텐츠에 배치할 때 일관성 있게 기본 값을 조정하는데
유용하게 사용된다.
 
이에 대한 예시로는
게임 콘텐츠를 만들 때
하나의 콘텐츠로 다수의 물체를 생성해서 배치할 때
그 다수의 물체의 설정된 기본값들을 
일관성 있게 조정다하는데 유용하게 사용되는 개념이다.
 
이 CDO는 GetClass()혹은 StatcClass()를 통해 
GetDefaultObject()로 얻어올 수 있다.

 
이러한 Uclass와 CDO는
엔진 초기화 과정에서 이루어지기 때문에
엔진 초기화 과정이 다 끝난 이후
즉 사용자가 실질적으로 사용하는 콘텐츠 제작 과정에서는
안심하고 이러한 정보를 사용할 수 있다.
 
 

언리얼 오브젝트 시스템의 특징

 

  1. 언리얼 오브젝트에는 항상 클래스 정보를 담은 UClass 객체가 매칭되어 있다.
  2. UClass로부터 언리얼 오브젝트의 정보를 파악할 수 있다.
  3. UClass에는 클래스 기본 오브젝트(CDO)가 연결되어 있어
    이를 활용해 개발의 생산성을 향상시킬 수 있다.
  4. 클래스 정보와 CDO는 엔진 초기화 과정에서
    생성되므로 게임 개발에서 안전하게 사용 가능하다.
  5. 헤더 정보를 변경하거나 생성자 정보를 변경하면 에디터를 끄고
    컴파일하는 것이 안정적이다.

 

내가 생각하는 리플렉션 시스템 정의

 
리플렉션 시스템은 프로퍼티 시스템과 동의어이며,
CDO에 의존적이고 CDO는 UHT이 정보를 수집한다.
 
즉 이를 반대로 하면,
1) UHT이 정보를 수집하고
2) 이 정보를 CDO에 저장한다.
3) 이 정보를 프로퍼티 시스템(=리플렉션 시스템)을 이용해 스스로의 값을 조사할 수 있는 것이다.
 
즉 리플렉션 시스템은 CDO에 의존하고 CDO는 UHT에 의존한다.
 
UBT, UHT와 리플렉션의 관계
 
Unreal Build Tool (UBT)와 Unreal Header Tool(UHT) 둘 다
런타임 리플렉션에 필요한 데이터를 생성하는데 유관하다.
UBT는 헤더를 스캔한 다음
리플렉션된 유형이 최소 하나 있는 헤더가 들어있는 모듈을 기억해둔다.
그 헤더 중 어떤 것이든 지난 컴파일 이후 변경되었다면,
UHT를 실행하여 리플렉션 데이터를 수집하고 업데이트한다.
UHT는 헤더를 파싱하고,
리플렉션 데이터 세트를 빌드한다음
리플렉션 데이터가 들어있는 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' 를
클래스 #include 문 가장 하단에 추가해주자
 
 

언리얼 리플렉션 시스템의 활용

  1. 리플렉션 시스템을 사용해
    언리얼 오브젝트의 특정 속성과 함수를 이름으로 검색할 수 있다.
  2. 리플렉션 시스템을 사용해 접근 지시자와
    무관하게 값을 설정할 수 있다.
  3. 리플렉션 시스템을 사용해 언리얼 오브젝트의 함수를 호출할 수 있다.

 
활용 코드
 

FProperty* NameProp = UClass(임의의 자료형)::StaticClass->FindPropertyByName(Text("Name"));
if(NameProp)
{
	// 프로퍼티를 통한 접근으로 값 읽어오기
	NameProp->GetValue_InContainer(임의의 자료형 포인터, &임의의 자료형의 이름을 담을 변수);
    // 프로퍼티를 통한 접근으로 값 세팅하기
    NameProp->GetValue_InContainer(임의의 자료형 포인터, &임의의 자료형의 이름을 바꿀 변수);
}




참고 문서
https://www.unrealengine.com/ko/blog/unreal-property-system-reflection

'UE5' 카테고리의 다른 글

언리얼 컴포지션  (1) 2025.03.22
언리얼 문자열 처리 FString과 FName, FText 사용 이유  (0) 2025.03.08
Unreal Object Handling  (3) 2024.12.19
언리얼 내부 - 모듈 (Modules) 2  (0) 2024.11.25
언리얼 내부 - 모듈 (Modules)  (0) 2024.11.25