강의 목표 :
- 언리얼 오브젝트의 특징과 리플렉션 시스템의 설명
- 언리얼 오브벡트의 처리 방식의 이해
강의 내용 :
- 언리얼 오브젝트에는 항상 클래스 정보를 담은 UClass 객체가 매칭되어 있다.
- UClass로부터 언리얼 오브젝트의 정보를 파악할 수 있다.
- UClass에는 "클래스 기본 오브젝트(CDO)"가 연결되어 있어 이를 활용해 개발의 생산성을 향상시킬 수 있다.
- 클래스 정보와 CDO는 엔진 초기화 과정에서 생성되기에 게임 개발에서 안전하게 사용 가능
- 헤더 정보를 변경하거나 생성자 정보를 변경하면 언리얼 에디터를 끄고 컴파일하는 것이 안정적임
[ ✔️리플렉션 시스템 ]
refer : https://www.unrealengine.com/ko/blog/unreal-property-system-reflection
📍리플렉션 시스템이란? :
= 프로퍼티 시스템
일반적으로 Reflection은 그래픽을 다루는 사람들에게 있어, 반사를 의미하기에 "프로퍼티 시스템" 이라고 부르기도 한다.
리플렉션은 프로그램이 런타임 도중에 자기 자신을 조하는 기능으로, 이 기능 자체가 언리얼의 근간을 이룬다.
사람이 거울을 보면서 재정비를 하듯이, 프로그램도 실행되면서 리플렉션 시스템을 통해 코드에 문제가 있는지 파악한다.
C++는 지원하지 않기에, 언리얼에서 자체적으로 구축했다.
📍리플렉션 시스템 사용법 :
리플렉션 시스템을 사용하기 위해선 "~.generated.h" 헤더 파일 추가하고, 특수한 매크로를 붙여줘야한다.
매크로 종류 : UCLASS() , UFUNCTION() , UPROPERTY() , UENUM() , UCLASS()
보이고자 하는 유형이나 프로퍼티에 매크로를 달아둔다면 프로젝트를 컴파일할 때 Unreal Header Tool(UHT)에 의해 해당 정보가 수집된다.
📍UPROPERTY() 선언이 없어도 괜찮은가? :
매크로 선언 없이 Raw 하게 선언해도 상관없다.
UPROPERTY() 로 지정된 멤버변수는 "프로퍼티" 라고 부른다.
UPROPERTY() 선언을 해주면 언리얼 엔진이 자동으로 메모리 관리를 해준다.
만약 매크로 선언을 해주지 않으면 언리얼 엔진이 관리 해주지 않기 때문에, 직접 메모리 관리해줘야 한다.
📍프로퍼티 시스템의 계층구조 :
(이후 과정에서 자세하게 다룬다.)
UFiedl → UStruct → UClass 순으로 상속되는 구조
UStruct 부터 언리얼에서 리플렉션을 받을 수 있기에, 이를 상속하는 UClass는 리플렉션을 보장받는다.
GetClass() 또는 StaticClass() 함수를 통해 UHT이 코드를 분석해서 만들어낸 리플렉션 정보가 보관된 특정 객체에 접근할 수 있다.
📍실습 : 리플렉션 정보 접근하기
실습코드 :
// GameInstance.h
UCLASS()
class OBJECTREFLECTION_API UMyGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
// 생성자
UMyGameInstance();
virtual void Init() override;
private:
UPROPERTY()
FString SchoolName; // 언리얼 엔진에 의해 관리되는 프로퍼티
};
// GameInstance.cpp
void UMyGameInstance::Init()
{
Super::Init();
UE_LOG(LogTemp, Log, TEXT("========="));
UClass* ClassRuntime = GetClass();
UClass* ClassCompile = UMyGameInstance::StaticClass();
check(ClassRuntime == ClassCompile);
UE_LOG(LogTemp, Log, TEXT("학교를 담당하는 클래스 이름 : %s"), *(ClassRuntime->GetName()));
UE_LOG(LogTemp, Log, TEXT("학교를 담당하는 클래스 이름 : %s"), *(ClassCompile->GetName()));
}
결과 :
GetClass() 함수와 [클래스이름]::StaticClass() 함수를 통해 UHT에 의해 수집된 클래스의 리플렉션 데이터에 접근
[ ✔️언리얼 오브젝트의 구성 ]
언리얼 오브젝트는 특별한 프로퍼티(변수)와 함수를 지정할 수 있다.
- UPROPERTY
- UFUNCTION
- 메크로 안에는 여러가지 메타 데이터를 심을 수 있다.
모든 언리얼 오브젝트는 "클래스 정보(UClass)"와 함께 한다.
클래스를 사용해 자신이 가진 프로퍼티와 함수 정보를 컴파일 타임과 런타임에 조회 할 수 있다.
언리얼 오브젝트는 NewObject() 함수를 사용해 생성해야 한다.
📍클래스 기본 오브젝트 :
= Class Default Object(CDO)
언리얼 객체가 가진 기본값을 보관하는 템플릿 객체
한 클래스로 다수의 물체를 생성해 게임 콘텐츠에 배치할 때, 일관성 있게 기본 값을 조정하는데 유용하게 사용됨
"클래스 정보(UClass)"로부터 GetDefaultObject() 함수를 통해 얻을 수 있다.
UClass 및 CDO 는 엔진 초기화 과정에서 생성되기에 콘텐츠 제작에서 안심하고 활용할 수 있다.
📍언리얼 오브젝트 처리 :
Unreal Object Handling in Unreal Engine
UObject 시스템의 기능에 대한 개요입니다.
dev.epicgames.com
- 클래스, 프로퍼티(변수), 함수에 적합한 매크로를 마킹해 주면 UClass, UProperty, UFunction 으로 변한다.
- 언리얼 엔진의 관리에 들어가서 다수의 내부적인 처리 기능을 구현할 수 있게된다.
- 일반적인 객체의 경우 가비지 값으로 채워지는데, UObject는 생성자 호출 전 초기화시 자동으로 0으로 채워진다.
- 레퍼런스 자동 업데이트 : 언리얼이 제공하는 메모리 관리 시스템을 보장 받을 수 있다는 의미
- 직렬화 작업 : 객체를 지정된 포맷에 맞게 불러오는 것 (단, UProperty로 선언한 경우에 한함)
- 애다토 통합 : UProperty와 매크로 안에 메타 데이터를 넣어주면 에디터와 통합되면서 유용한 기능을 사용할 수 있다.
- 런타임 유형 정보 및 형변환 : 런타임에서 정보를 얻고 안전한 캐스팅을 보장하는데, 함수 오버라이딩 시 사용하는 Super 키워드 역시 리플렉션 시스템이 있기에 설정이 가능한 것
- 가비지 컬렉션 : 더 이상 사용되지 않는 객체의 경우 자동으로 메모리를 회수한다.
- 네트워크 리플리케이션 : 직렬화와 유사한 기능으로, 네트워크 통신을 통해서 UPROPERTY 를 전송하고 받을 수 있게 설계 되어있다.
📍실습 : 오브젝트 리플렉션
1. 클래스 이름 받아오기
GetClass() 함수와 StaticClass() 함수가 가리키는 대상은 동일하다.
UClass* ClassRuntime = GetClass();
UClass* ClassCompile = UMyGameInstance::StaticClass();
check(ClassRuntime == ClassCompile);
UE_LOG(LogTemp, Log, TEXT("학교를 담당하는 클래스 이름 : %s"), *(ClassRuntime->GetName()));
UE_LOG(LogTemp, Log, TEXT("학교를 담당하는 클래스 이름 : %s"), *(ClassCompile->GetName()));
2. CDO 받아오기
생성자에서 설정한 프로퍼티의 초기값 (CDO)을 이후 수정하더라도 GetDefaultObject<T>() 템플릿 함수를 통해 초기값을 받아올 수 있다.
// 프로퍼티
UPROPERTY()
FString SchoolName; // 언리얼 엔진에 의해 관리되는 프로퍼티
// 구현부_생성자
UMyGameInstance::UMyGameInstance()
{
SchoolName = TEXT("OldSchool");
}
// 구현부_Init
void UMyGameInstance::Init()
{
SchoolName = TEXT("NewSchool");
UE_LOG(LogTemp, Log, TEXT("학교 이름 : %s"), *SchoolName);
FString DefaultSchoolName1 = GetClass()->GetDefaultObject<UMyGameInstance>()->SchoolName;
FString DefaultSchoolName2 = ClassRuntime->GetDefaultObject<UMyGameInstance>()->SchoolName;
FString DefaultSchoolName3 = ClassCompile->GetDefaultObject<UMyGameInstance>()->SchoolName;
UE_LOG(LogTemp, Log, TEXT("학교 이름 기본값1 : %s"), *DefaultSchoolName1);
UE_LOG(LogTemp, Log, TEXT("학교 이름 기본값2 : %s"), *DefaultSchoolName2);
UE_LOG(LogTemp, Log, TEXT("학교 이름 기본값3 : %s"), *DefaultSchoolName3);
}
3. CDO 의 생성 시점 :
헤더 파일을 수정할때와 마찬가지로 클래스 디폴트 오브젝트(CDO)의 값을 변경하는 경우에도 언리얼 에디터를 종료하고 VS에서 빌드를 진행해줘야한다.
그렇지 않으면 변경된 CDO의 값을 인식하지 못할 수 있다.
엔진이 초기화되는 과정에서 CDO 와 UClass 정보등이 만들어진다.
해당 정보들이 온전히 다 만들어진 이후 에디터와 게임과 같은 애플리케이션들이 실행된다.
================================
개인 공부 기록용 포스팅입니다.
댓글, 질문 환영해요~!
Unreal Engine Ver : 5.1.1
Refer : Inflearn_이득우의 언리얼 프로그램
================================
'Unreal > Inflearn' 카테고리의 다른 글
Part1.7 언리얼 C++ 설계 Ⅰ - 인터페이스⭕ (0) | 2024.04.09 |
---|---|
Part1.6 언리얼 오브젝트 리플렉션 시스템 Ⅱ⭕ (0) | 2024.04.08 |
Part1.4 언리얼 오브젝트 소개 ⭕ (0) | 2024.04.08 |
Part1.3 언리얼 C++ 기본 타입과 문자열 ⭕ (0) | 2024.04.08 |
Part1.2 언리얼 C++ 코딩 표준 ⭕ (0) | 2024.04.06 |