다양한 기록

언리얼 오브젝트 리플렉션 시스템 본문

언리얼 엔진/언리얼 엔진 : 기초

언리얼 오브젝트 리플렉션 시스템

라구넹 2024. 12. 18. 19:59

리플렉션 : 프로그램이 실행 시간에 자기 자신을 조사하는 기능

다양한 기능이 리플렉션을 토대로 제공

언리얼이 자체적으로 제공함

 

옵션으로 필요할 때 사용 가능

리플렉션 시스템에 보이도록 했으면 하는 거에 주석을 달아주면

언리얼 헤더 툴이 컴파일 시 해당 정보를 수집

 

헤더에 리플렉션이 있는 유형으로 마킹 시 -> generated.h 인클루드 필요

그 다음 객체에 UENUM(), UCLASS(), USTRUCT(), UFUNCTION(), UPROPERTY()를 앞에다 넣어주면

자동으로 처리해줌

 

멤버 변수 -> UPEROERTY()

함수 -> UFUNCTION()

매크로 추가 시 관련 코드를 INTERMEDIATE 폴더에 자동으로 생성해줌

이때 메타데이터 넣을 수도 있음

 

리플렉션된게 아니면 가비지 컬렉터 작동 안함

-> 알아서 관리하면 됨

 

언리얼 헤더 툴은 c++파서는 아니고, 그냥 필요한 기능만 제공해줌


리플렉션 시스템 계층 구조

UField

- UStruct

-- UClass

-- UScriptStruct

-- UFunction

- UEnum

- UProperty

 

구축된 언리얼 오브젝트 클래스

=> StaticClass() 나 GetClass() 함수로 접근 가능

 

StaticClass같은 건 언리얼 헤더 툴이 generated.h에 생성해줌


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

언리얼 객체가 가진 기본 값을 보관하는 템플릿 객체

기본값 조정할 때 편함

GetDefaultObject()로 얻을 수 있음

엔진 초기화 과정에서 만들어짐

 

UProperty로 선언 시..

- 자동 초기화 됨 (0으로)

- 레퍼런스 자동 업데이트 .. 메모리 자동 관리

- 직렬화됨

- CDO로 값 업데이트해서 관리

- 에디터 통합 (메타데이터 이용)

- 런타임 정보 얻기

- 네트워크 리플리케이션

// Fill out your copyright notice in the Description page of Project Settings.

#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;
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "MyGameInstance.h"

UMyGameInstance::UMyGameInstance()
{
	// CDO에 저장됨
	// CDO를 고치는, 생성자를 바꾸는 경우에도 에디터 다시 켜줘야 함
	// 에디터 켜진 이후에 수정하면 인지 못함 
	SchoolName = TEXT("기본학교");
}

void UMyGameInstance::Init()
{
	Super:: Init();
	UE_LOG(LogTemp, Log, TEXT("==================="));

	// 동일한 객체를 가리킴 
	UClass* ClassRuntime = GetClass();
	UClass* ClassCompile = UMyGameInstance::StaticClass();

	check(ClassRuntime == ClassCompile);
	ensure(ClassRuntime == ClassCompile); // 어설션되어도 에디터 안 뻗음
	ensureMsgf(ClassRuntime == ClassCompile, TEXT("에러 발생"));

	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("==================="));
}

check -> 어설트 시 에디터 종료

ensure -> 어설트 시에도 에디터 종료는 안됨

ensureMsgf -> 어설트 시에 문자 같이 넣어줌

 

생성자에서 코드 변경

-> CDO에 반영됨

에디터 켜지기 이전, 엔진 초기화 중간에 CDO 설정이 이루어짐

=> 생성자 코드 변경 시 에디터 다시 켜야 함


리플렉션 시스템의 활용

리플렉션 시스템을 이용해서 .. 

1. 특정 속성과 함수 검색 가능

2. 접근 지시자와 무관하게 값의 변경이 가능

3. 언리얼 오브젝트의 함수 호출 가능

 

// Fill out your copyright notice in the Description page of Project Settings.


#include "MyGameInstance.h"
#include "Student.h"
#include "Teacher.h"

UMyGameInstance::UMyGameInstance()
{
	// CDO에 저장됨
	// CDO를 고치는, 생성자를 바꾸는 경우에도 에디터 다시 켜줘야 함
	// 에디터 켜진 이후에 수정하면 인지 못함 
	SchoolName = TEXT("기본학교");
}

void UMyGameInstance::Init()
{
	Super:: Init();
	UE_LOG(LogTemp, Log, TEXT("==================="));

	// 동일한 객체를 가리킴 
	UClass* ClassRuntime = GetClass();
	UClass* ClassCompile = UMyGameInstance::StaticClass();

	check(ClassRuntime == ClassCompile);
	ensure(ClassRuntime == ClassCompile); // 어설션되어도 에디터 안 뻗음
	ensureMsgf(ClassRuntime == ClassCompile, TEXT("에러 발생"));

	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("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("DoLesson");
	if (DoLessonFunc)
	{
		Teacher->ProcessEvent(DoLessonFunc, nullptr);
	}
	UE_LOG(LogTemp, Log, TEXT("==================="));
}

리플렉션 시스템으로 속성에 강제로 접근하여 변경

리플렉션 시스템으로 함수를 실행

 

* generated.h는 헤더 파일 중 가장 밑에 와야 함

* 본인 헤더 파일은 가장 위에 와야 함

'언리얼 엔진 > 언리얼 엔진 : 기초' 카테고리의 다른 글

언리얼 오브젝트 기초  (0) 2024.12.18
언리얼 C++ 코딩 규칙  (0) 2024.10.30