게임 엔진/Unreal

[Unreal Engine] Reflection System

Henzee 2025. 6. 16. 00:27

 

 


 

 

1. Reflection System

문서 링크 : Reflection System / Unreal Object Handling

 

1) 언리얼 오브젝트의 구성

 

  • 언리얼 오브젝트에는 특별한 프로퍼티와 함수를 지정할 수 있음
    • 관리되는 클래스 멤버 변수: UPROPERTY
    • 관리되는 클래스 멤버 함수: UFUNCTION
    • 에디터와 연동되는 메타 데이터를 심을 수 있음
    • 리플렉션 시스템을 사용해 접근 지시자와 무관하게 값을 설정할 수 있음
  • 언리얼 오브젝트에는 항상 클래스 정보를 담은 UClass 객체가 매칭되어 있음
    • 클래스를 사용해 자신이 가진 프로퍼티와 함수 정보를 컴파일 타임과 런타임에서 조회할 수 있음
  • NewObject API를 사용해 생성해야 함

 

 

2) 클래스 기본 오브젝트 (CDO, Class Default Object)

 

  • 언리얼 클래스 정보에는 클래스 기본 오브젝트가 함께 포함되어 있음
  • 클래스 기본 오브젝트는 줄여서 CDO라고 부름
  • CDO는 언리얼 객체가 가진 기본값을 보관하는 템플릿 객체
  • 한 클래스로부터 다수의 물체를 생성해 게임 콘텐츠에 배치할 때 일관성 있게 기본값을 조정하는데 유용하게 사용됨
  • CDO는 클래스 정보로부터 GetDefaultObject() 함수를 통해 얻을 수 있음
  • UClass 및 CDO는 엔진 초기화 과정에서 생성되므로 콘텐츠 제작에서 안심하고 사용할 수 있음 

 

 

3) 언리얼 오브젝트의 특징

  • 클래스 기본 객체(CDO, Class Default Object): 클래스의 기본값과 타입 정보 제공
  • 리플렉션(Reflection): 런타임에서 클래스 정보 참조 기능
  • 인터페이스(Interface): 모던 객체 지향 언어가 제공하는 인터페이스의 제공
  • 향상된 열거형
  • 델리게이트(Delegate): 객체 간의 결합을 낮출 수 있는 델리게이트 기능 제공
  • 가비지 컬렉션(Garbage Collection): 자동 메모리 관리
  • 향상된 구조체(Struct): 리플렉션이 가능한 구조체 지원
  • 직렬화(Serialization): 객체 정보를 바이트 스트림으로 저장, 전송, 로드하는 기능

 

 


 

 

2. Reflection System을 사용한 예제 구현

1) 예제를 위한 클래스 다이어그램

  • 어떤 학교에서 학생과 교수가 함께 수업하는 상황 구현
  • 학교 정보는 GameInstance에서 지정
  • 인물 클래스 (Person)
    • 학생 클래스 (Student)
    • 선생 클래스 (Teacher)

 

 

2) GameInstance 생성

Tools > New C++ Class > GameInstance 선택 후 Next 버튼 클릭

 

Edit > Project Settings > Maps & Modes > Default Maps Clear / MyGameInstance 지정

 

 

3) UCLASS와 CDO의 동작 방식

  • UClass

MyGameInstance.h

 

UClass 정보를 활용한 클래스 이름 출력

 

출력 결과

 

  • CDO

※ 생성자 코드를 변경하는 경우 헤더 파일과 마찬가지로 에디터를 끄고 빌드 진행

CDO에 저장된 기본값과 변경된 값 출력

 

출력 결과

 

 

4) 언리얼 오브젝트의 속성과 함수

 

  • 클래스에 설정할 프로퍼티 정보
  • Person에는 DoLesson이라는 가상 함수가 있음
    • Student의 DoLesson은 수업을 듣는 행동
    • Teacher의 DoLesson은 수업을 가르치는 행동

 

 

5) 클래스 추가 (Person, Student, Teacher)

  • Person 클래스

Person 클래스 : Object 상속

// Header File

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Person.generated.h"

/**
 * 
 */
UCLASS()
class HELLOUNREAL_API UPerson : public UObject
{
	GENERATED_BODY()

public:
	UPerson();

	UFUNCTION()
	virtual void DoLesson();

	const FString& GetName() const;
	void SetName(const FString& InName);

protected:
	UPROPERTY()
	FString Name;

	UPROPERTY()
	int32 Year;

private:

};


// Cpp File

#include "Person.h"

UPerson::UPerson()
{
	Name = TEXT("홍길동");
	Year = 1;
}

void UPerson::DoLesson()
{
	UE_LOG(LogTemp, Log, TEXT("%s님이 수업에 참여합니다."), *Name);
}

const FString& UPerson::GetName() const
{
	return Name;
}

void UPerson::SetName(const FString& InName)
{
	Name = InName;
}

 

  • Student, Teacher 클래스

Student, Teacher 클래스 : Person 상속

 

※ 헤더 파일에서 ObjectName.generated.h 헤더가 맨 밑으로 와야 함

// Header File

#pragma once

#include "CoreMinimal.h"
#include "Person.h"
#include "Student.generated.h" // 해당 헤더 파일이 맨 밑으로 와야 함

/**
 * 
 */
UCLASS()
class HELLOUNREAL_API UStudent : public UPerson
{
	GENERATED_BODY()
	
public:
	UStudent();

	virtual void DoLesson() override;

private:
	UPROPERTY()
	int32 Id;

};


// Cpp File

#include "Student.h"

UStudent::UStudent()
{
	Name = TEXT("이학생");
	Year = 1;
	Id = 1;
}

void UStudent::DoLesson()
{
	Super::DoLesson();

	UE_LOG(LogTemp, Log, TEXT("%d학년 %d번 %s님이 수업을 듣습니다."), Year, Id, *Name);
}
// Header File

#pragma once

#include "CoreMinimal.h"
#include "Person.h"
#include "Teacher.generated.h"

/**
 * 
 */
UCLASS()
class HELLOUNREAL_API UTeacher : public UPerson
{
	GENERATED_BODY()

public:
	UTeacher();

	virtual void DoLesson() override;

private:
	UPROPERTY()
	int32 Id;
	
};


// Cpp File

#include "Teacher.h"

UTeacher::UTeacher()
{
	Name = TEXT("이선생");
	Year = 3;
	Id = 1;
}

void UTeacher::DoLesson()
{
	Super::DoLesson();

	UE_LOG(LogTemp, Log, TEXT("%d년차 선생님 %s님이 수업을 강의합니다."), Year, *Name);
}

 

 

6) MyGameInstance에 언리얼 오브젝트 객체 생성

※ 소스 파일에서 해당 오브젝트가 선언된 헤더가 맨 위로 와야 함

// Cpp File

#include "MyGameInstance.h" // 해당 오브젝트가 선언된 헤더가 맨 위에 있어야 함
#include "Student.h"
#include "Teacher.h"

UMyGameInstance::UMyGameInstance()
{
	SchoolName = TEXT("기본학교"); // CDO에 기본값으로 저장됨
}

void UMyGameInstance::Init()
{
	Super::Init();

	UE_LOG(LogTemp, Log, TEXT("===================================="));
	
	UStudent* Student = NewObject<UStudent>();
	UTeacher* Teacher = NewObject<UTeacher>();

	// getter, setter 함수를 이용해 멤버 변수 값 사용
	Student->SetName(TEXT("학생1"));
	UE_LOG(LogTemp, Log, TEXT("새로운 학생 이름 : %s"), *Student->GetName());

	// Reflection System을 이용해 멤버 변수 값 사용
	FString CurrentTeacherName;
	FString NewTeacherName(TEXT("김선생"));
	FProperty* NameProp = UTeacher::StaticClass()->FindPropertyByName(TEXT("Name"));
	if (NameProp)
	{
		NameProp->GetValue_InContainer(Teacher, &CurrentTeacherName);
		UE_LOG(LogTemp, Log, TEXT("현재 선생님 이름 : %s"), *CurrentTeacherName);

		NameProp->SetValue_InContainer(Teacher, &NewTeacherName);
		UE_LOG(LogTemp, Log, TEXT("새로운 선생님 이름 : %s"), *Teacher->GetName());
	}

	UE_LOG(LogTemp, Log, TEXT("===================================="));

	Student->DoLesson();

	// Reflection System 사용해 멤버 함수 값 사용
	UFunction* DoLessonFunc = Teacher->GetClass()->FindFunctionByName(TEXT("DoLesson"));
	if (DoLessonFunc)
	{
		Teacher->ProcessEvent(DoLessonFunc, nullptr);
	}

	UE_LOG(LogTemp, Log, TEXT("===================================="));
}

 

출력 결과

 

 

 


 

 

 

'게임 엔진 > Unreal' 카테고리의 다른 글

[Unreal Engine] Composition  (0) 2025.06.16
[Unreal Engine] Interface  (3) 2025.06.16
[Unreal Engine] Object  (4) 2025.06.15
[Unreal Engine] 기본 타입과 문자열  (1) 2025.06.14
[Unreal Engine] GameInstance로 Hello Unreal! 출력하기  (0) 2025.06.14