본문 바로가기
개발 (Game)/Unreal 5

[Unreal] 언리얼 오브젝트, 리플렉션 시스템, Assertion

by 진현개발일기 2024. 5. 2.

■ 프로젝트이름_API

(헤더파일에 보면 클래스 선언문에 존함 ex. class HELLOUNREAL_API UMyObject : public UObject)

위 예시의 UMyObject라는 언리얼 오브젝트가 다른 모듈(dll)에서도 사용될 수 있게 개방시켜주는 기능임.

 

이를 없애면 MyObject는 다른 모듈에서 참조를 하지 못하고 VS의 솔루션 탐색기를 보면 Source/프로젝트이름 (ex. Source/HelloUnreal) 모듈 내에서 밖에 사용을 못한다.

 

■ GENERATED_BODY

generated.h에 있는 헤더 파일의 특정 부분을 사용한다는 표시이다.

UMyObject.generated.h의 일부분

이 안에 매핑되어있는 코드를 사용하는 것이다.

 

■ UHT(Unreal Header Tool)

복잡한 경로에 genearted.h 파일이 존재하는데 이를 제거해도 Rebuild Solution을 한다면 언리얼이 알아서 UHT(Unreal Header Tool)을 통해 자동 생성을 하게 된다. 


UHT는 언리얼에서 사용하는 매크로를 사용할 수 있게 해주는 프로그램으로 매크로를 이용하여 자동으로 코드를 추가 생성해준다.

[주의할 점]
UHT는 C++ Parser 가 아니다. 이건 언리얼 엔진에서 코드 자동 생성을 할 때 필요한 기능을 제공하기만 하는 것이지 실제 C++ 코드를 UHT가 분석해서 컴파일을 진행하지 않는다.


그래서 너무 복잡한 유형은 UHT가 읽어들이지 못할 수 있다. 이럴 경우 런타임에 나타낼 수 없는 유형을 붙이려하여 오류 메세지를 띄우게 된다.

 

■ 언리얼 프로퍼티 시스템 (리플렉션 시스템)

※ 원래대로라면 리플렉션 시스템으로 이야기 하는 것이 보통인데, 모든 사람을 대상으로 글을 작성하다보니 '리플렉션'은 그래픽 용어이기도 하기 때문에 '프로퍼티 시스템'이라고도 부르게 되었다.

리플렉션(Reflection)은 프로그램이 실행 시간[런타임]에 자기 자신을 조사하는 기능이다.


이는 엄청나게 유용한 데다 언리얼 엔진 테크놀로지의 근간을 이루는 것으로,

(1) 에디터의 디테일 패널, (2) 시리얼라이제이션, (3) 가비지 컬렉션, (4) 네트워크 리플리케이션, (5) 블루프린트/C++ 커뮤니케이션 등 다수의 시스템에 탑재된 것이다.

C++언어는 어떠한 형태의 리플렉션을 지원하지 않아서 언리얼에서는 자체적으로 C++ 클래스, 구조체, 함수, 멤버 변수, 열거형 관련 정보를 수집, 질의, 조작하는 별도의 시스템이 구축되어 있다. 즉, 언리얼 오브젝트만이 가질 수 있는 독특한 시스템이다.


리플리케이션 시스템은 옵션이다. 리플렉션 시스템에 보이도록 했으면 하는 유형이나 프로퍼티에 주석을 달아주면, Unreal Header Tool (UHT)가 그 프로젝트를 컴파일 할 때 해당 정보를 수집한다.
(#include "FileName.generated.h")

※ UPROPERTY, UFUNCTION 등의 매크로를 통해 리플렉션된 프로퍼티 지정 가능

 

리플렉션된 프로퍼티가 아닌 것은 해당 리플렉션에 의존하는 시스템 전부에 보이지 않는 다는 점만 주의하면 된다. 즉, 사용자가 직접 처리해줘야 한다. 

※ 즉, 리플렉션 되지 않은 UObject 포인터를 그대로 저장한다면 보통 가비지 컬렉터가 레퍼런스를 확인할 수 없기 때문에 위험한 일이다

그러므로 아래와 같이 포인터를 선언해줘야 한다. 혹은 UPROPERTY를 사용하지 않을 경우 본인이 직접 메모리 관리를 해줘야 한다.


(ex. 포인터 선언 예시)
UPROPERTY()
UMyPointer* MyPointerThing;

 

[참고1]

https://www.unrealengine.com/ko/blog/unreal-property-system-reflection

 

[참고2]

https://ikrima.dev/ue4guide/engine-programming/uobject-reflection/uobject-reflection/

 

UE4 Reflection Overview - Gamedev Guide

UE4 Reflection Overview https://www.unrealengine.com/blog/unreal-property-system-reflection The type hierarchy for the property system looks like this: UField UStruct UClass (C++ class) UScriptStruct (C++ struct) UFunction (C++ function) UEnum (C++ enumera

ikrima.dev

 

■ 프로퍼티 시스템 유형 계층 구조

  • 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)

위를 보면 알 수 있듯이 UStruct는 C++ 클래스, 구조체, 함수와 같이 다른 멤버를 포함하는 기본적인 종합 구조체이며, UScriptStruct인 C++ Struct와는 헷갈리지 말아야 한다.


UClass는 자식으로 함수나 프로퍼티를 포함할 수 있는 반면, UFunction과 UScriptStruct는 프로퍼티로만 제한된다.

 

■ 리플렉션 정보 접근

UTypeName::StaticClass(), FTypeName::StaticStruct(), 혹은 Instance->GetClass() 로 특정 리플렉션된 C++유형에 대한 UClass 혹은 UScriptStruct에 접근할 수 있다.


위와 같은 접근은 UHT가 분석해서 만들어 놓은 리플렉션 정보들을 보관하는 특정 개체에 접근할 수 있다는 뜻이다.
(이는 generated.h에 UHT가 자동으로 생성해준다)

각 유형은 고유의 플래그 세트 및 부가 정보가 있기 때문에 우리가 필요한 것들만 필터링해서 얻을 수 있다.
이를 통해 리플렉션 데이터를 사용한다면 언리얼 내에서 여러가지 많은 작업을 할 수 있게 된다.

■ 언리얼 오브젝트 구성

언리얼 오브젝트에는 특별한 프로퍼티와 함수를 지정할 수 있음.
     · 관리 되는 클래스 멤버 변수 : UPROPERTY
     · 관리 되는 클래스 멤버 함수 : UFUNCTION
     · 에디터와 연동되는 메타데이터를 심을 수 있음

모든 언리얼 오브젝트는 클래스 정보와 함께 함.
     · 클래스를 사용해 자신이 가진 프로퍼티와 함수 정보를 컴파일 타임과 런타임에서 조회할 수 있음.

이렇게 다양한 기능을 제공하는 언리얼 오브젝트는 기존 C++의 new() 방식이 아닌 NewObject API를 사용해 생성해야 한다.

■ 클래스 기본 오브젝트 (CDO; Class Default Object)

언리얼 클래스 정보엔 클래스 기본 오브젝트가 포함되어 있다.
CDO는 언리얼 객체가 가진 기본 값을 보관하는 탬플릿 객체이다.
한 클래스로부터 다수의 물체를 생성해 게임 콘텐츠에 배치할 때 일관성 있게 기본 값을 조정하는데 유용하게 사용되어짐.

CDO는 클래스 정보로부터 GetDefaultObject 함수를 통해 얻을 수 있음
UClass 및 CDO는 엔진 초기화 과정에서 생성이 되므로 콘텐츠 제작 단계에서 안심하고 사용할 수 있음.

 

■ 언리얼 오브젝트 처리 

[자동 프로퍼티 초기화]

기존에 C++ 같은 경우에는 생성자나 기본 이니셜라이저를 통해 초기화를 하지 않으면, 가비지 값 (Garbage Value)이 들어가는데 UPROPERTY, UCLASS, UFUNCTION 등으로 마킹할 경우 '생성자 호출 전'에 자동으로 0으로 초기화 해준다.
그 이후 멤버는 클래스 생성자의 커스텀 값으로 초기화가 가능해진다.


[직렬화 (Serialization)]

UObject 객체를 지정된 포맷에 맞게 저장하거나 불러들일 때 저장되길 원하는 정보들은 'UPROPERTY'라는 것으로 명시를 해줘야 한다.


[안정적인 형변환]

UObjet는 언리얼 엔진의 리플렉션 시스템의 일부이므로, 항상 자신이 무슨 UClass인지 알고 있으며, 형변환을 실시간으로 할 수 있다.
이러한 리플렉션 시스템이 있기에 우리가 Super라는 typedef를 이용하여 부모에 접근할 수 있게 된 것이다.


[가비지 컬렉션]

더이상 사용되지 않는 오브젝트는 언리얼 시스템이 자동으로 회수해서 메모리에서 소멸시켜 준다.


[네트워크 리플리케이션]

위 직렬화와 비슷한 느낌으로 네트워크 통신에서도 해당 UPROPERTY를 자동으로 송수신하는 시스템이 언리얼 내부에서 구축되어 있다.

 

[참고]

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/unreal-object-handling-in-unreal-engine?application_version=5.4

 

Unreal Object Handling In Unreal Engine | 언리얼 엔진 5.4 문서 | Epic Developer Community

UObject 시스템의 기능에 대한 개요입니다.

dev.epicgames.com

 

■ Assertion

(1) check

언리얼에선 C++의 Assert를 대신해 사용할 수 있는 기능을 제공한다
check()함수를 이용하면 된다.

check(A == B) // A == B라면 다음  코드 진행. 아니라면 크래쉬를 내버린다.

※ 실제 게임을 빌드 할 때는 check 구문들은 자동으로 없어지게 된다.

(2) ensure

만약 에디터가 꺼지는 것을 원치 않는다면, ensure()함수로 대체하면 된다. 만약 구문 안에 코드가 false라면 다량의 에러를 내뿜는다. 


(ex. Ensure Condition Failed : 코드 내용)

(3) ensureMsgf

ensure과 기능은 동일하나 커스텀 메세지를 남기고 싶을 때 사용. 두번째 파라미터로 TEXT("내용")과 같이 추가해주면 된다.

 

[참고]

https://www.inflearn.com/course/%EC%9D%B4%EB%93%9D%EC%9A%B0-%EC%96%B8%EB%A6%AC%EC%96%BC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-part-1/dashboard

 

이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해 | 이득우 - 인프런

이득우 | 대기업 현업자들이 수강하는 언리얼 C++ 프로그래밍 전문 과정입니다. 언리얼 엔진 프로그래머라면 게임 개발전에 반드시 알아야 하는 언리얼 C++ 기초에 대해 알려드립니다., [사진] 언

www.inflearn.com

 

728x90

'개발 (Game) > Unreal 5' 카테고리의 다른 글

[Unreal5] Mini Project : Arena Battle  (0) 2024.05.13
[Unreal] TArray, TSet  (0) 2024.05.05
[Unreal5] Mini Project : Simple Shooter  (0) 2024.04.25
[Unreal5] Nanite  (0) 2024.04.22
[Unreal5] Mini Project : Toon Tanks  (0) 2024.04.21