최적화(성능)와 프로그래머의 실수방지(유지보수)
게임을 플레이 하는 사람들을 위해서는 최대한 최적화되서 누구나 플레이 가능해야함.
게임을 만드는 사람들을 위해서는 규모가 커져도 실수 없이 관리할 수 있어야 함.
언매니지드 언어
C++는 언매니지드 언어임. 즉, 메모리를 직접 관리 가능하기에 최적화 가능.
다만 잘못 접근하면 메모리 누수 혹은 크래시로 인해 유지보수가 까다로움.
이를 해결하기 위해 후발 언어(C#, …)들은 실수를 줄이기 위한 기능(가비지 컬렉션)과
생산성을 높혀주는 기능(리플렉션, …)들이 언어에 내장되어 있음.
언리얼 C++
특유의 매크로 문법을 통해서 기존 C++에 후발 언어 기능들을 구현함.
이 기능들이 지원되는 클래스가 언리얼 오브젝트 클래스.
// SUnrealObject.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "SUnrealObject.generated.h"
/**
*
*/
UCLASS()
class STUDYPROJECT_API USUnrealObject : public UObject
{
GENERATED_BODY()
};
// SUnrealObject.cpp
#include "SUnrealObject.h"
그냥 클래스만 만들었을 땐 에디터에 뜨지 않다가, 이렇게 수정후 컴파일 하면 언리얼 에디터에 해당 클래스가 뜸.
Include What You Use
UE4 초반 버전에서는 #include “EngineMinimal.h” 구문을 사용했었음.
개발에 필요한 대부분의 헤더 파일을 참조하는 파일.
비교적 최신 UE4와 UE5에서는 IWYU에 따라 #include “CoreMinimal.h” 구문을 사용함.
사용하는 헤더 파일만 참조해서 빌드 속도와 인텔리센스 부하를 줄임.
#Include “UObject/NoExportTypes.h”
이 자리에는 추후 부모 클래스의 헤더 파일을 작성함.
UObject 클래스를 상속 받으므로 위 헤더 파일을 상속.
#include “SUnrealObject.generated.h”
UHT을 통해 .h 파일이 .generated.h 파일로 변환됨.
소스코드 작성 시점에는 이 파일이 존재하지 않지만, 컴파일 과정에서 무조건 생성됨.
따라서 필요로하는 헤더 파일들을 모두 include 한 뒤에 .generated.h 파일을 include
UCLASS() 매크로
언리얼 클래스를 선언하기 전 작성해야 하는 매크로.
구조체 전에는 USTRUCT(), 공용체 전에는 UENUM() 매크로를 작성함.
PROJECT_API
윈도우의 DLL 시스템은 DLL 내 클래스 정보를 외부에 공개할 지 말지 결정하는
__declspec(dllexport)라는 키워드를 제공함. 언리얼 엔진에서 이 키워드를 사용하려면
“모듈명_API” 키워드를 클래스 선언 앞에 추가해야 함.
이 키워드가 없으면 다른 모듈에서 해당 클래스에 접근할 수 없음.
언리얼 오브젝트 클래스 접두사 U
UObject 클래스를 상속 받는 클래스는 접두사 U가 붙음.
AActor 클래스를 상속 받은 클래스는 A-
Interface를 상속 받은 클래스는 I-
템플릿 클래스는 T-
그외 구조체는 F-
UObject 클래스 상속
언리얼 오브젝트 클래스는 UObject 클래스를 상속 받아야 함.
상속 받지 않는다면 스마트 포인터를 사용해서라도 메모리 관리를 해야함.
GENERATED_BODY() 매크로
해당 매크로를 타고 들어가면 수 많은 매크로 코드를 볼 수 있음.
이는 컴파일 진행 전에 Unreal Header Tool에 의해 분석되고, .generated.h 파일을 만들어 냄.
Unreal Header Tool
언리얼 오브젝트 클래스의 헤더 파일에 작성된 언리얼 C++ 매크로를 분석하는 툴.
분석한 결과로 클래스명.generated.h 파일을 생성함.
언리얼 오브젝트의 장점들을 제공하기 위한 전처리 작업을 진행해줌.
GENERATED_BODY() 매크로 말고도 UCLASS(), UPROPERTY(), UFUNCTION() 등 많음.
// SGameInstance.h
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.h" // SUnrealObject와 다른 이유를 생각해보자.
#include "SGameInstance.generated.h"
/**
*
*/
UCLASS()
class STUDYPROJECT_API USGameInstance : public UGameInstance
{
GENERATED_BODY()
};
// SGameInstance.cpp
#include "Game/SGameInstance.h"