언리얼 엔진 공부하기 #9 [UE5]

신지한·2024년 4월 29일
0

개발노트

목록 보기
15/15
post-thumbnail

📢 개발노트에 앞서서

본 개발노트는 혼자서 언리얼 게임개발 독학하는 과정에서
공부한 내용들을 기록&공유하는 게시글이며
부족한점이 있을 수 있어 참고해서 봐주시면 감사하겠습니다

👉 이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해

❗ 본 게시글은 위 강의의 내용을 정리 및 실습한 게시글로 모든 내용은 대부분의 내용은 책이 출처입니다


📚 스터디 내용

4강에서는 언리얼 C++에서의 오브젝트에 대한 학습을 진행했습니다. 아래는 필기를 한 강의 노트입니다

📖 4강 필기 노트

게임 프로그래밍의 특수성

  • 사용자: 쾌적한 경험을 위해 단일 컴퓨터에서 최대 성능을 뽑아 내야 한다
  • 개발자: 게임의 규모가 커질수록 방대하고 복잡한 기능을 안정적으로 관리해야 한다

C++ 언어의 단점

  • 하드웨어에 직접 접근하기 때문에, 잘못 사용하면 프로그램에 큰 영향을 미침
  • (후발 언어의 등장: Java, C#) 불필요한 기능 걷어내고 최대한 명확하고 간결하게 설계, 성능보다 안정성과 생산성을 중요시, 하드웨어 직접 접근x, 가상 머신을 통해 간접적으로 접근

모던 객체 지향 설계 원칙

  • 유지보수와 유연함, 확장성 향상을 위한 객체 지향 프로그래밍 원칙 (SOLID 원칙)

언리얼 엔진의 선택

  • 성능을 위해 C++언어를 포기할 수 없음
  • 기존 C++언어를 확장해 모던 객체 지향 설계를 가능하도록 만듬
  • 모던 객체 지향 설계를 위한 새로운 시스템을 구축

언리얼 오브젝트

  • 언리얼 엔진이 설계한 새로운 시스템의 단위 오브젝트(객체)
    - 일반 C++ 오브젝트와 언리얼 오브젝트의 두 객체를 모두 사용 가능
    - 구분을 위해 C++앞에는 F, 언리얼 오브젝트는 접두사 U 를 사용
  • C++ 오브젝트: 저수준의 빠른 처리를 위한 기능 구현에 사용
  • 언리얼 오브젝트: 콘텐츠 제작과 관련된 복잡한 설계에 이용

언리얼 오브젝트의 이해

  • 게임이 대형화되면서 성능과 유지보수 두 가지가 모두 중요해짐
  • 언리얼 엔진은 C++ 언어를 확장한 언리얼 오브젝트라는 객체 구조를 고안함
  • 지정된 매크로를 사용해 빌드를 수행하면, 추가 코드가 자동으로 만들어지는 구조를 가짐
  • 언리얼 오브젝트를 사용해 대규모 게임 제작을 안정적으로 설계하고 구현할 수 있음

5강에서는 언리얼 오브젝트 리플렉션 시스템 설명 및 오브젝트의 구성에 대해서 학습했습니다. 아래는 필기를 한 강의 노트입니다

📖 5강 필기 노트

언리얼 오브젝트 시스템

  • 언리얼 오브젝트에는 항상 클래스 정보를 담은 UClass 객체가 매칭되어 있다
  • UClass로부터 언리얼 오브젝트의 정보를 파악할 수 있음
  • UClass에는 클래스 기본 오브젝트(CDO)가 연결되어 있어 이를 활용해 개발의 생산성을 향상시킬 수 있음
  • 클래스 정보와 CDO는 엔진 초기화 과정에서 생성되므로 게임 개발에서 안전하게 사용 가능
  • 헤더 정보를 변경하거나 생성자 정보를 변경하면 에디터를 끄고 컴파일하는것이 안정적임
  • 포인터를 선언할때 UPROPERTY()를 선언해야 언리얼에서 자동으로 메모리를 관리해줌

언리얼 오브젝트의 구성

  • 언리얼 오브젝트는 특별한 프로퍼티와 함수를 지정할 수 있음
    - 관리되는 클래스 멤버 변수: UPROPERTY
    - 관리되는 클래스 멤버 함수: UFUNCTION
  • 모든 언리얼 오브젝트는 클래스 정보와 함께 함
  • 언리얼 오브젝트는 NewObject API를 사용해 생성해야 함

언리얼 오브젝트의 클래스 기본 오브젝트

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

6강에서는 언리얼 오브젝트 리플렉션 시스템에 대한 실습을 위주로 학습했습니다. 아래는 필기를 한 강의 노트입니다

📖 6강 필기 노트

  • generated.h 헤더가 가장 밑에 오도록 해야함
  • cpp 파일의 include 순서도 해당 언리얼 오브젝트에 선언된 헤더가 가장 위쪽에 위치해 있어야 함
  • MyGameInstance.h 가 가장 위

언리얼 리플렉션 시스템의 활용

  1. 리플렉션 시스템을 사용해 언리얼 오브젝트의 특정 속성과 함수를 이름으로 검색할 수 있다
  2. 리플렉션 시스템을 사용해 접근 지시자와 무관하게 값을 설정할 수 있다
  3. 리플렉션 시스템을 사용해 언리얼 오브젝트의 함수를 호출할 수 있다
    언리얼 엔진의 기본 프레임웍은 리플렉션을 활용해 구축되어 있으므로 언리얼 엔진을 이해하기 위해서는 리플렉션 시스템을 이해하는 것이 필요함

👉 실습코드

//MyGameInstance.h
UCLASS()
class OBJECTREFLECTION_API UMyGameInstance : public UGameInstance
{
	GENERATED_BODY()
	
public:
	UMyGameInstance();

	virtual void Init() override;

private:
	UPROPERTY()
	FString SchoolName;

};

//MyGameInstance.cpp
UMyGameInstance::UMyGameInstance()
{
	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(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);
	}
}

//Person.h
UCLASS()
class OBJECTREFLECTION_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:

};

//Person.cpp
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
UCLASS()
class OBJECTREFLECTION_API UStudent : public UPerson
{
	GENERATED_BODY()
public:
	UStudent();
    
	virtual void DoLesson() override;
    
private:
	UPROPERTY()
	int32 Id;

};

//Student.cpp
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
UCLASS()
class OBJECTREFLECTION_API UTeacher : public UPerson
{
	GENERATED_BODY()
public:
	UTeacher();
    
	virtual void DoLesson() override;

private:
	UPROPERTY()
	int32 Id;

};

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

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

😅 강의 들으면서 필기한거라 급하게 작성해서 내용이 중구난방일 수 있습니다..!

📌 공부 후기

지난 강의에 이어 4~6강을 수강하였다

이번 수업에선 C++을 통해 오브젝트에 대해서 학습하고 이를 실습 구조에 맞게 구현해보는 실습을 진행하였다

이번 강의에서 느낀건 확실히 이득우 강사님이 자세히 설명해주시다보니 내가 책으로 혼자 공부했을때
'이건 무슨 함수지?', '이게 어떻게 동작하는거지?' 라고 생각하며 무작정 따라하며 학습했을때보단

강의를 수강하면서 학습함으로써 좀더 언리얼 C++ 프로젝트뿐만 아니라 C++에 대한 이해도도 높아진다는걸 느낄 수 있었다

기초부터 학습하다보니 언리얼C++은 꽤 흥미로운 분야라는 생각도 들었다

profile
게임 개발자 지망생

0개의 댓글