[UE] 언리얼 리플렉션 Unreal Reflection II

언리얼 오브젝트 리플렉션 시스템의 활용하여 언리얼 오브젝트 리플렉션 시스템을 사용해 언리얼 오브젝트를 다루는 방법의 학습하자.
인프런 이득우님의 '언리얼 프로그래밍 Part1 - 언리얼 C++의 이해' 강의를 참고하였습니다.
😎 [이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해] 강의 들으러 가기!
목차
언리얼 리플렉션 Unreal Reflection II
예제 클래스 다이어그램
- 어떤 학교에서 학생과 교수가 함께 수업하는 상황을 구현하고 싶다.
- 학교 정보는 GameInstance에서 지정
- 인물 클래스 Person
- 학생 클래스 Student
- 선생 클래스 Teacher

예제 코드
Person.h
더보기
#pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "Person.generated.h" UCLASS() class PRACTICEUNREAL_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; };
Person.cpp
더보기
#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.h
더보기
#pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "Person.h" #include "Student.generated.h" UCLASS() class OBJECTREFLECTION_API UStudent : public UPerson { GENERATED_BODY() public: UStudent(); virtual void DoLesson() override; private: UPROPERTY() int32 Id; };
Student.cpp
더보기
#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); }
Teacher.h
더보기
#pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "Person.h" #include "Teacher.generated.h" UCLASS() class OBJECTREFLECTION_API UTeacher : public UPerson { GENERATED_BODY() public: UTeacher(); virtual void DoLesson() override; private: UPROPERTY() int32 Id; };
Teacher.cpp
더보기
#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); }
MyGameInstance.h
더보기
#pragma once #include "CoreMinimal.h" #include "Engine/GameInstance.h" #include "MyGameInstance.generated.h" UCLASS() class OBJECTREFLECTION_API UMyGameInstance : public UGameInstance { GENERATED_BODY() public: UMyGameInstance(); virtual void Init() override; private: UPROPERTY() FString SchoolName; };
MyGameInstance.cpp
더보기
#include "MyGameInstance.h" // 해당 언리얼 오브젝트에 선언된 헤더가 가장 위에 위치해야 한다. #include "Student.h" #include "Teacher.h" #include 순서도 중요하다. 아래와 같이 다른 언리얼 오브젝트 헤더가 더 위에 위치한 경우 헤더툴이 에러를 띄운다. #include "Student.h" #include "Teacher.h" #include "MyGameInstance.h" UMyGameInstance::UMyGameInstance() { SchoolName = TEXT("기본학교"); } void UMyGameInstance::Init() { Super::Init(); UE_LOG(LogTemp, Log, TEXT("=============================")); UClass* ClassRuntime = GetClass(); UClass* ClassCompile = UMyGameInstance::StaticClass(); UE_LOG(LogTemp, Log, TEXT("학교를 담당하는 클래스 이름 : %s"), *ClassRuntime->GetName()); SchoolName = TEXT("청강문화산업대학교"); UE_LOG(LogTemp, Log, TEXT("학교 이름 : %s"), *SchoolName); UE_LOG(LogTemp, Log, TEXT("학교 이름 기본값 : %s"), *GetClass()->GetDefaultObject<UMyGameInstance>()->SchoolName); UE_LOG(LogTemp, Log, TEXT("=============================")); UStudent* Student = NewObject<UStudent>(); UTeacher* Teacher = NewObject<UTeacher>(); Student->SetName(TEXT("학생1")); UE_LOG(LogTemp, Log, TEXT("새로운 학생 이름 %s"), *Student->GetName()); 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(); UFunction* DoLessonFunc = Teacher->GetClass()->FindFunctionByName(TEXT("DoLesson")); if (DoLessonFunc) { Teacher->ProcessEvent(DoLessonFunc, nullptr); } UE_LOG(LogTemp, Log, TEXT("=============================")); }
실행화면

리플렉션 시스템 (위의 예제 코드 분석)
NewObject<클래스 이름>()
C++에서의 new 키워드가 언리얼 UObject에서는 NewObject<클래스 이름>() 과 유사하다.
UStudent* Student = NewObject<UStudent>(); UTeacher* Teacher = NewObject<UTeacher>();
리플렉션을 통한 프로퍼티 변경
Get, Set 함수를 사용하는 방법이 아닌, 언리얼 엔진에서 제공하는 리플렉션 시스템을 사용해서 변경
FString CurrentTeacherName; FString NewTeacherName(TEXT("이득우")); FProperty* NameProp = UTeacher::StaticClass()->FindPropertyByName(TEXT("Name")); // 속성 이름("Name")으로 검색해서 포인터를 가져옴 if (NameProp) { NameProp->GetValue_InContainer(Teacher, &CurrentTeacherName); UE_LOG(LogTemp, Log, TEXT("현재 선생님 이름: %s"), *CurrentTeacherName); // "이선생" (CDO 기본값) NameProp->SetValue_InContainer(Teacher, &NewTeacherName); UE_LOG(LogTemp, Log, TEXT("새로운 선생님 이름: %s"), *Teacher->GetName()); // "이득우" }

리플렉션을 통한 함수 호출
런타임에서 동작 중인 객체의 UFUNCTION 프로퍼티 중에서 DoLesson의 함수 포인터를 가져와 실행
Student->DoLesson(); // FindFunctionByName 함수를 통해 DoLesson 함수를 이름으로 검색해서 DoLessonFunc의 포인터를 가져옴 UFunction* DoLessonFunc = Teacher->GetClass()->FindFunctionByName(TEXT("DoLesson")); if (DoLessonFunc) // "DoLesson"이름의 함수를 찾았다면 { Teacher->ProcessEvent(DoLessonFunc, nullptr); // Teacher 인스턴스를 지정하고 ProcessEvent 함수를 이용해서 함수 포인터를 넘겨줌 }
Student.cpp
더보기
#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); }
Teacher.cpp
더보기
#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); }

정리: 언리얼 리플렉션 시스템의 활용
- 리플렉션 시스템을 사용해 언리얼 오브젝트의 특정 속성과 함수를 이름으로 검색할 수 있다.
- 리플렉션 시스템을 사용해 접근 지시자와 무관하게 속성값을 설정할 수 있다.
- 리플렉션 시스템을 사용해 언리얼 오브젝트의 함수를 호출할 수 있다.
언리얼 엔진의 기본 프레임웍은 리플렉션을 활용해 구축되어 있으므로,
언리얼 엔진을 이해하기 위해서는 리플렉션 시스템을 이해하는 것이 필요함.
'⭐ Unreal Engine > UE 개념정리 - 언리얼의 이해' 카테고리의 다른 글
[UE] 언리얼 C++ 설계 2 - 컴포지션 (0) | 2024.04.05 |
---|---|
[UE] 언리얼 C++ 설계 1 - 인터페이스 (0) | 2024.04.05 |
[UE] 언리얼 리플렉션 Unreal Reflection I (0) | 2024.03.18 |
[UE] 언리얼 오브젝트 시스템 (0) | 2024.03.18 |
[UE] 문자타입, 문자열 FString, FText, FString (0) | 2024.03.13 |
댓글
이 글 공유하기
다른 글
-
[UE] 언리얼 C++ 설계 2 - 컴포지션
[UE] 언리얼 C++ 설계 2 - 컴포지션
2024.04.05언리얼 C++만의 컴포지션 기법을 사용해 복잡한 언리얼 오브젝트를 효과적으로 생성하자언리얼 C++ 컴포지션 기법을 사용해 오브젝트의 포함 관계를 설계하는 방법의 학습언리얼 C++이 제공하는 확장 열거형 타입의 선언과 활용 방법의 학습 인프런 이득우님의 '언리얼 프로그래밍 Part1 - 언리얼 C++의 이해' 강의를 참고하였습니다. 😎 [이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해] 강의 들으러 가기! 목차 언리얼 오브젝트의 컴포지션 컴포지션 ( Composition ) 객체 지향 프로그래밍의 설계는 상속과 컴포지션으로 나눌 수 있다.상속이란 같은 성질을 가진 부모, 자식 객체 간의 Is-A 관계만 의존해서는 설계와 유지보수가 어려움.컴포지션은 객체 지향 설계에서 Has-A … -
[UE] 언리얼 C++ 설계 1 - 인터페이스
[UE] 언리얼 C++ 설계 1 - 인터페이스
2024.04.05언리얼 C++ 인터페이스 클래스를 사용해 보다 안정적으로 클래스를 설계하는 기법을 학습하자. 목차 언리얼 C++ - 인터페이스 언리얼 C++ 인터페이스 인터페이스란?객체가 반드시 구현해야 할 행동을 지정하는데 활용되는 타입다형성(Polymorphism)의 구현, 의존성이 분리(Decouple)된 설계에 유용하게 활용 언리얼 엔진에서 게임 콘텐츠를 구성하는 오브젝트의 설계 예시언리얼 엔진 월드에 배치되는 모든 오브젝트.월드에 배치되는 모든 오브젝트를 액터라고 한다. 액터(Actor)는 움직이는 물체와 안 움직않는 물체를 모두 통틀은 상위 개념이다. 움직이지 오브젝트 ( Pawn )길찾기 시스템을 반드시 사용하면서 움직이는 오브젝트 ( INavAgentInterface 인터페이스를 구현한 Paw… -
[UE] 언리얼 리플렉션 Unreal Reflection I
[UE] 언리얼 리플렉션 Unreal Reflection I
2024.03.18언리얼 오브젝트의 특징과 리플렉션 시스템의 동작원리를 이해하자. 언리얼 오브젝트의 처리 방식을 이해하고 사용예시를 분석하자. 인프런 이득우님의 '언리얼 프로그래밍 Part1 - 언리얼 C++의 이해' 강의를 참고하였습니다. 😎 [이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해] 강의 들으러 가기! 목차 언리얼 오브젝트 리플렉션 리플렉션(Reflection)은 프로그램이 실행시간에 자기 자신을 조사하는 기능이다. UPROPERTY()를 붙이는 기준 리플렉션 프로퍼티 변수는 언리얼 엔진의 시스템의 관리(=Garbage Collector)를 받는다. 반면에, 리플렉션 프로퍼티가 아닌 것은 해당 리플렉션에 의존하는 시스템 전부에 보이지 않는다.즉, 리플렉션 되지 않은 UObject … -
[UE] 언리얼 오브젝트 시스템
[UE] 언리얼 오브젝트 시스템
2024.03.18언리얼 오브젝트의 소개와 선언방법게임 프로그래밍이 가지는 특수성과 언리얼 오브젝트의 필요성의 이해언리얼 오브젝트의 선언과 엔진 내부 컴파일 과정의 학습 인프런 이득우님의 '언리얼 프로그래밍 Part1 - 언리얼 C++의 이해' 강의를 참고하였습니다. 😎 [이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해] 강의 들으러 가기! 목차 C++ 언어 게임 프로그래밍의 특수성 사용자: 쾌적한 경험을 위해 단일 컴퓨터에서 최대 성능을 뽑아내야 한다.개발자: 게임의 규모가 커질수록 방대하고 복잡한 기능을 안정적으로 관리해야 한다. C++ 언어의 단점 C++1970년대 개발하여 오래됨객체 지향 프로그래밍의 선두 주자현재까지 지속적으로 개선해왔지만, 익혀야 할 내용이 많음하드웨어에 직접 접근하…
댓글을 사용할 수 없습니다.