참고자료
https://unrealcommunity.wiki/unreal-property-system-(reflection)-36d1e6
Unreal Property System (Reflection) | Unreal Engine Community Wiki
Brief description of the Unreal Property System.
unrealcommunity.wiki
https://dev.epicgames.com/documentation/ko-kr/unreal-engine/reflection-system-in-unreal-engine
1. Reflection이란
- reflection은 프로그램이 런타임에 스스로를 검사할 수 있는 능력이다.
- 그러나 C++ 언어 자체는 이러한 기능이 없기 때문에 언리얼이 자체적인 시스템을 구축하여, 클래스, 구조체, 함수, 멤버변수, 열거형에 대한 정보를 harvest(수집), query(요청), manipulate(조작) 한다.
- 이 기능이 언리얼의 여러 시스템을 구동하게 한다.
- 에디터의 디테일 페널
- Serialization
- 가비지 컬렉
- 네트워크 리플리케이션
- 블루프린트 및 C++ 통신
- 언리얼의 opt-in 방식이므로, 원하는 경우에 사용이 가능하다.
2. Markup
- reflected type을 포함하는 헤더를 만들고 싶다면, 파일 위에 특별한 include를 해주어야 한다.
- 그 결과 언리얼 헤더 툴이 이 파일을 고려해야 한다는 것을 알게 되며, 구현할 때에도 필요하다.
- 아래의 코드와 같은 모습인데, 언리얼 엔진에서 우리가 None이 아닌 다른 클래스를 만들면, 이 헤더가 자동으로 포함되어있는 것을 볼 수 있다.
#include "파일명.generated.h"
- 이 헤더가 정의되어있다면, UENUM(), UCLASS(), USTRUCT(), UFUNCTION(), UPROPERTY() 등의 매크로를 사용해서 다양한 타입과 멤버변수를 작성할 수 있다.
- 또한 이 매크로들을 다양한 추가 지정자를 ( )안에 작성하여, 다양한 동작을 할 수 있다.
- 코드 예시
- 매크로
- UCLASS() 매크로를 통해 이 클래스를 reflected 되었음을 나타낸다.
- GENERATED_UCLASS_BODY() UCLASS()는 쌍을 이뤄서 존재해야 하며, 클래스 안에서 추가 함수 작성과 typedef를 위해 필요하다.
- Super:: 또는 ThisClass:: 와 같은 typedef를 사용 가능하게 한다.
- 추가 지정자(인자) → ObjectBase.h 에 정의되어 있음
- EditAnywhere: 에디터의 디테일 패널에서 수정 가능
- BlueprintCallable: 블루프린트에서 호출 가
- Category = 카테고리명: 카테고리를 통해 검색 및 표시
- reflected되지 않은 변수
- reflected된 변수와 함께 존재해도 괜찮지만, reflection로 동작하는 시스템에서는 해당 변수를 인식하지 못한다.
- 예를 들어 언리얼 GC는 reflected되지 않은 raw 포인터의 참조를 볼 수 없다. (raw 포인트는 위험함)
- 매크로
#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;
};
3. Limitations
- 언리얼 헤더툴은 실제 C++ parser가 아니기 때문에 문제가 발생할 수 있다.
- 해결책) 기존에 존재하는 헤더에 reflected type을 추가할 때
- 단어를 바꾸거나 (reword)
- #if & #endif 로 wrap 하면 된다.
- 해결책) 기존에 존재하는 헤더에 reflected type을 추가할 때
- 대부분의 type은 예상대로 동작하지만, 동작하지 않는 타입이 존재한다.
- 예를 들어 TArray와 TSubclassOf 의 몇 가지 템플릿 타입에만 동작하며,
- 중첩된 템플릿 파라메터는 불가능하다.
4. Using Reflection Data
- 프로퍼티 시스템의 계층구조
- UStruct는 UClass, UScriptStruct, UFunction을 포함하는 기본 유형이다.
- UClass는 함수나 프로퍼티(UPROPERTY로 정의된 멤버 변수)를 자식으로 가질 수 있다.
- UFunction과 UScriptStruct는 프로퍼티로만 제한된다.
UField
UStruct
UClass (C++ class)
UScriptStruct (C++ struct)
UFunction (C++ function)
UEnum (C++ enumeration)
UProperty (C++ member variable or function parameter)
(Many subclasses for different types)
- get
- UStruct는 가져올 수 없다. (공통 base 클래스가 없으므로)
- UTypeName::StaticClass() 또는 FTypeName::StaticStruct()
- UClass와 UScriptStruct 타입을 가져올 수 있다.
- Instance→GetClass()
- UObject 인스턴스를 가져올 수 있다.
- iterator
- TFieldIterator를 통해 UStruct의 멤버를 순회할 수 있다.
- 템플릿 인자 설정
- <UProperty> : 클래스나 구조체에서 멤버변수만 반복
- <UFunction> : 함수만 반복
- <UField> : 멤버변수와 함수 모두 포함하여 반복
- 생성자 두번째 인자 (부모 클래스의 멤버를 포함할지의 여부)
- (GetClass(), true) : 부모 클래스의 멤버도 포함
- (GetClass(), false)
- 단, 템플릿 인자가 UFunction일때는 부모 클래스의 멤버를 항상 포함
for (TFieldIterator<UProperty> PropIt(GetClass()); PropIt; ++PropIt)
{
UProperty* Property = *PropIt;
}
'Unreal Engine' 카테고리의 다른 글
| Unreal Engine Dedicated Server (3) | 2025.01.13 |
|---|---|
| Unreal Engine Garbage Collection (1) | 2025.01.13 |
| Unreal Engine Pointer Types (2) | 2025.01.09 |
| UE_LOG 보충 (+ 과제) (1) | 2025.01.07 |
| Unreal Engine 간단한 로그 찍기 (3) | 2025.01.06 |