게임 엔진/Unreal

[Unreal] 언리얼 리플렉션

겜도리도리 2023. 12. 24. 11:21
반응형

앞서

이 포스팅은 이득우의 언리얼 프로그래밍 Part1을 수강하고 작성한 내용입니다.

 

개요

리플렉션은 프로램이 실행시간에 자기 자신을 조사하는 것이다. 시리얼라이제이션, 가비지 컬렉션, 네트워크 리플리케이션 등이 리플렉션을 토대로 만들어졌다. 리플렉션 시스템에 보이도록 했으면 하는 유형이나 프로퍼티에 주석을 달아주면, Unreal Header Tool이 프로젝트 컴파일 시에 해당 정보를 수집해 소스 코드를 생성해준다.

 

예시로, 멤버 변수에는 UPROPERTY(), 멤버 함수에는 UFUNCTION()라는 매크로를 사용하면 UHT가 이것들을 확인한 뒤 Intermediate 폴더 내부에 필요한 코드를 생성해준다.

 

UPROPERTY를 선언해주면 다음과 같은 기능을 갖는다.

1. 특정 속성들의 기본값을 설정해주지 않으면 0을 기본값으로 갖는다. (비교 : C++ 클래스에서는 기본값을 설정해주지 않으면 가비지 값이 들어간다)

2. 언리얼 엔진이 자동으로 메모리를 관리해준다.

3. Serialization을 사용할 수 있다.

4. 메타데이터를 사용하면 에디터와 통합되면서 유용한 기능을 사용할 수 있다.

5. 런타임에 캐스팅을 안전하게 할 수 있다. SUPER 같은 시스템도 그 예이다.

6. 네트워크 리플리케이션을 사용할 수 있다.

 

모든 언리얼 오브젝트는 클래스 정보와 함께하는데, UCLASS를 사용해서 자신이 가진 다양한 정보를 컴파일 타임과 런 타임에서 조회할 수 있다. 언리얼 오브젝트를 생성할 때는 new 키워드가 아니라 NewObject API를 사용해서 생성해줘야 한다. 한편, 클래스 정보에는 Class Default Object가 함께 포함되어 있다. CDO는 객체가 가진 기본값을 보관한다. CDO는 클래스 정보로부터 GetDefaultObject()함수를 통해 가져올 수 있다.

 

헤더파일의 리플렉션 정보나 CDO를 변경하는 경우에는 에디터를 끄고 컴파일 해주는 것이 권장된다. 엔진이 초기화되는 과정에서 UObject라든지, UCLASS정보가 만들어지기 때문에, 에디터를 끄지 않으면 변경사항이 반영되지 않을 수 있다.

 

언리얼에서 header에서 다른 header를 include할 때, generated.h 파일은 가장 밑에 있어야 한다.

한편, example.cpp파일에서 example.h는 제일 위에 include 되어야 한다. 두 개의 케이스 모두 header 순서를 제대로 지켜주지 않으면 UHT에서 에러를 띄운다.

 

Unreal Objcet를 생성할 때는 new가 아닌 newObject API를 사용해 생성해줘야 한다.

 

아래는 리플렉션을 활용해 변수와 함수를 가져오는 예시이다.

 

 

FProperty에 UTeacher 클래스의 Name이라는 프로퍼티에 대한 포인터를 가져와 GetValue_InContainer를 활용해 CurrentTeacherName에 저장하는 예시이다.

이 때 Name 프로퍼티의 보호 수준은 protected이지만, 이렇게 리플렉션을 사용하면 보호 수준을 무시하고 가져올 수 있다.

 

 

UFunction에 UTeacher의 DoLesson 함수를 가져와 실행하는 예시이다.

실행할 때는 인스턴스의 ProcessEvent를 활용해 실행하면 된다. 이 때 DoLessonFunc는 인자가 없기 때문에 , ProcessEvent 함수에서 인자가 들어가는 항목에 nullptr을 넣어준 것을 볼 수 있다.

 

 

반응형