[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 -
[UE] 언리얼 C++ 설계 1 - 인터페이스
[UE] 언리얼 C++ 설계 1 - 인터페이스
2024.04.05 -
[UE] 언리얼 리플렉션 Unreal Reflection I
[UE] 언리얼 리플렉션 Unreal Reflection I
2024.03.18 -
[UE] 언리얼 오브젝트 시스템
[UE] 언리얼 오브젝트 시스템
2024.03.18