일단 리플렉션 시스템을 알아보기 위해 문서 먼저 확인해보자
https://www.unrealengine.com/ko/blog/unreal-property-system-reflection
언리얼 프로퍼티 시스템 (리플렉션)
리플렉션(Reflection)은 프로그램이 실행시간에 자기 자신을 조사하는 기능입니다. 이는 엄청나게 유용한 데다 언리얼 엔진 테크놀로지의 근간을 이루는 것으로, 에디터의 디테일 패널, 시리얼라
www.unrealengine.com
처음에 보면 프로퍼티 시스템이라고 돼있다. 모든 사람들을 위해 리플렉션과 프로퍼티 시스템으로 부르기도 한다.
리플리케이션 시스템은 옵션입니다.
리플렉션 시스템에 보이도록 했으면 하는 유형이나 프로퍼티에 주석을 달아주면,
Unreal Header Tool (UHT)가 그 프로젝트를 컴파일할 때 해당 정보를 수집합니다.
이 기능을 사용하려면, 특수한 include를 추가해야 된다.
#include "FileName.generated.h"
기본적으로 언리얼 C++ 클래스를 만들면 같이 오는 include 이다.
//////////////////////////////////////////////////////////////////////////
// Base class for mobile units (soldiers)
#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;
[이하 코드 생략]
};
(14년도 코드이다. 현재 사용하고 있는 기능과 조금 차이가 있을 수 있다.)
GENERATED_UCLASS_BODY()을 사용하고 있지만, 이제는 GENERATED_BODY() 로 통합 되었다.
UFUNCTION(BlueprintCallable, Category=Attachment) 을 사용하면 자동으로 intermedia 폴더에 생성이 된다
UPROPERTY(EditAnywhere, Category=Pawn) 의 괄호 안에 있는 메타 데이터는 에디터와 연결돼서 게임 제작할때 유용하게 활용되는 기능이다.
uint8 MyTeamNum; 이런식으로 모든 변수가 UPROPERTY로 선언할 필요는 없다. 하지만, 자동으로 메모리 관리를 해주지 않는다.
UHT(Unreal Header Tool)은 실제로 C++ 파서가 아니다. 이 말은 언리얼 엔진에서 코드를 자동으로 생성하는 기능만 제공한다. 자동으로 분석해서 컴파일을 진행해주는것이 아니다. 따라서 너무 복잡한 내용은 UHT이 읽지 못한다.
다음은 프로퍼티 시스템의 계층구조이다.
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)
UClass는 UStruct를 상속받아 함수정보를 추가해 전체 클래스 정보를 구축한다. 이렇게 구축된 UClass는 UTypeName::StaticClass() 나 FTypeName::StaticStruct() 를 작성하여 리플렉션된 C++ 유형에 대한 UClass 또는 UScriptStruct 를 구할 수 있으며, Instance->GetClass() 를 사용해서 UObejct 인스턴스에 대한 유형을 구할 수 있다.
for (TFieldIterator<UProperty> PropIt(GetClass()); PropIt; ++PropIt)
{
UProperty* Property = *PropIt;
// Do something with the property
}
UProperty를 사용해서 순회를 하면, UnrealObject의 속성들을 조회하면서 값, 정보들을 빼내올 수 있다.
이런 기능은 현재 C++에서 지원하지 않는 기능이다. 이러한 시스템은 Unreal엔진의 근간을 이루고 있다.
- 이런 리플렉션 데이터를 사용하면 다양한 작업이 가능하다.
UTypeName::StaticClass() 이런 함수 generated헤더파일에 미리 선언된다.
언리얼 오브젝트의 구성 - 언리얼 오브젝트에는 특별한 프로퍼티와 함수를 지정할 수 있음.
- 관리되는 클래스 멤버 변수 : UPROPERTY
- 관리되는 클래스 멤버 함수 : UFUNCTION
- 에디터와 연동되는 메타데이터를 심을 수 있음
- 모든 언리얼 오브젝트는 캘릇 정보와 함꼐 함.
- 클래스를 사용해 자신이 가직ㄴ 프로퍼티와 함수 정보를 컴파일 타임과 런타임에서 조회할 수 있음.
- 이렇게 다양한 기능을 제공하는 언리얼 오브젝트는 NewObjectAPI를 사용해 생헝해야 함.
일반 C++ 객체는 F로 시작 하는것으로 네이밍을 하고 new()로 생성한다.
언리얼 C++ 객체는 U로 시작하고 NewObject()로 생성한다.
- 언리얼 클래스 정보에는 클래스 기본 오브젝트(Class Default Object)가 함께 포함되어 있음.
- 클래스 기본 오브젝트는 줄여서 CDO라고 부름.
- CDO는 언리얼 객체가 가진 기본값을 보관하는 템플릿 객체임.
- 한 클래스로부터 다수의 물체를 생성해 게임 콘텐츠에 배치할 때 일관성 있게 기본 값을 조정하는데 유용하게 사용됨.
- COD는 클래스 정보로부터 GetDefaultObject 함수를 통해 얻을 수 있음.
- UClass 및 CDO는 엔진 초기화 과정에서 생성므로 콘텐츠 제작에서 안심하고 사용할 수 있음.
언리얼C++ 객체에서 GetClass() or StaticClass()로 UClass를 얻어오고, GetDefaultObject()로 CDO를 얻어옴.
언리얼 오브젝트 처리
언리얼 오브젝트 처리
UObject 시스템의 기능에 대한 개요입니다.
docs.unrealengine.com
언리얼 오브젝트 처리 이다.
UProperty를 마킹한 변수는 자동으로 기본값으로 채워진다.
레퍼런스 자동 업데이트
메모리 관리를 효율적이게 할수 있다.
Serialization(직렬화)
언리얼 오브젝트 객체를 지정된 포멧에 맞게 저장하거나 불러들이는것을 일관적으로 할수 있다.
저장되는 변수는 UProperty값으로 마킹 해야 된다.
프로퍼티 값 업데이트하기
CDO를 사용해서 게임에서 여러가지 오브젝트를 배치했을 때, 기본값을 CDO를 활용해서 효과적으로 만들 수 있다.
런타임 유형 정보 및 형변환
런타임에서 정보를 얻고 안전하게 형변환이 가능해진다. 또한 함수를 override 할때 사용하는 Super 매크로도 가능하다.
class ALegendaryWeapon : public AWeapon
{
void SlayMegaBoss()
{
TArray<AEnemy> EnemyList = GetEnemyListFromSomewhere();
// The legendary weapon is only effective against the MegaBoss
for (AEnemy Enemy : EnemyList)
{
AMegaBoss* MegaBoss = Cast<AMegaBoss>(Enemy);
if (MegaBoss)
{
Incinerate(MegaBoss);
}
}
}
};
형변환시 제대로 변환이 안됐을 경우 Null을 반환하기 때문에 안전하게 사용 가능하다.
가비지 컬렉션
더이상 참조되지 않는 오브젝트를 자동으로 해제시켜준다. (추후 다시 설명)
'Unreal' 카테고리의 다른 글
5. 컴포지션 (0) | 2023.09.11 |
---|---|
4. 인터페이스 (0) | 2023.08.31 |
3-2. 언리얼 오브젝트 리플렉션 시스템 (0) | 2023.08.07 |
1. 코딩 규칙 (0) | 2023.07.03 |
0. 서론 (0) | 2023.07.03 |