icon안동민 개발노트

언리얼 엔진과 C++의 통합


 언리얼 엔진은 C++를 기반으로 구축되었으며, 개발자들에게 강력하고 유연한 C++ 프로그래밍 환경을 제공합니다.

 이 절에서는 언리얼 엔진이 C++ 코드를 어떻게 처리하고 통합하는지에 대한 전반적인 프로세스를 살펴보겠습니다.

언리얼 헤더 툴 (UHT)

 언리얼 헤더 툴(Unreal Header Tool, UHT)은 C++ 헤더 파일을 분석하고 처리하여 언리얼 엔진의 리플렉션 시스템에 필요한 메타데이터를 생성합니다.

  1. 역할
  • UCLASS(), UPROPERTY(), UFUNCTION() 등의 매크로를 해석
  • 리플렉션 데이터 생성
  • 직렬화, 네트워크 복제, 블루프린트 연동 등을 위한 보일러플레이트 코드 생성
  1. 처리 과정
UCLASS()
class AMyActor : public AActor
{
      GENERATED_BODY()
 
public:
      UPROPERTY(EditAnywhere, BlueprintReadWrite)
      float MyFloat;
 
      UFUNCTION(BlueprintCallable)
      void MyFunction();
};

 이 코드에 대해 UHT는 다음과 같은 작업을 수행합니다.

  • AMyActor 클래스에 대한 리플렉션 정보 생성
  • MyFloat 속성을 에디터와 블루프린트에 노출
  • MyFunction을 블루프린트에서 호출 가능하게 만듦

언리얼 빌드 툴 (UBT)

 언리얼 빌드 툴(Unreal Build Tool, UBT)은 프로젝트의 빌드 프로세스를 관리합니다.

  1. 주요 기능
  • 모듈 의존성 분석
  • 플랫폼별 빌드 설정 관리
  • 빌드 스크립트(.Build.cs 파일) 실행
  1. 빌드 프로세스
  • 소스 파일 수집
  • 컴파일 명령 생성
  • 링크 과정 관리
  • 최종 바이너리 생성

 예시 (.Build.cs 파일)

public class MyProject : ModuleRules
{
    public MyProject(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    
        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
    }
}

언리얼 오브젝트

 언리얼 오브젝트는 언리얼 엔진의 핵심 개념으로, UObject 클래스로부터 파생된 모든 클래스를 말합니다.

  1. 특징
  • 가비지 컬렉션
  • 리플렉션
  • 직렬화
  • 네트워크 복제
  1. 예시
UCLASS()
class UMyObject : public UObject
{
    GENERATED_BODY()
 
public:
    UPROPERTY()
    int32 MyInteger;
 
    UFUNCTION()
    void MyFunction() { /* ... */ }
};

모듈 시스템

 언리얼 엔진은 모듈식 아키텍처를 사용하여 코드를 구성합니다.

  1. 모듈 정의
// MyModule.h
class FMyModule : public IModuleInterface
{
public:
    virtual void StartupModule() override;
    virtual void ShutdownModule() override;
};
 
// MyModule.cpp
IMPLEMENT_MODULE(FMyModule, MyModule)
 
void FMyModule::StartupModule()
{
    // 모듈 초기화 코드
}
 
void FMyModule::ShutdownModule()
{
    // 모듈 정리 코드
}
  1. 모듈 로딩
  • 엔진 시작 시 자동으로 로드
  • 필요에 따라 동적으로 로드 / 언로드 가능

리플렉션 시스템

 리플렉션 시스템은 런타임에 타입 정보에 접근할 수 있게 해주는 메커니즘입니다.

  1. 주요 기능
  • 속성과 함수에 대한 메타데이터 제공
  • 동적 객체 생성
  • 직렬화 지원
  1. 사용 예
UClass* MyClass = AMyActor::StaticClass();
for (TFieldIterator<FProperty> PropIt(MyClass); PropIt; ++PropIt)
{
    FProperty* Property = *PropIt;
    UE_LOG(LogTemp, Log, TEXT("Property Name: %s"), *Property->GetName());
}

가비지 컬렉션

 언리얼 엔진의 가비지 컬렉션 시스템은 더 이상 참조되지 않는 UObject 인스턴스를 자동으로 정리합니다.

  1. 작동 방식
  • 주기적으로 참조되지 않는 객체 탐지
  • 탐지된 객체 정리
  1. 메모리 관리
UPROPERTY()
UMyObject* MyObjectPtr;  // 가비지 컬렉션에 의해 관리됨
 
UMyObject* NonManagedPtr;  // 가비지 컬렉션에 의해 관리되지 않음

C++ 코드 컴파일 및 로딩 프로세스

  1. 컴파일 과정
  • UHT가 헤더 파일 처리
  • UBT가 빌드 스크립트 실행
  • 플랫폼별 컴파일러로 소스 코드 컴파일
  • 링커가 최종 바이너리 생성
  1. 로딩 과정:
  • 엔진 시작 시 코어 모듈 로드
  • 프로젝트 관련 모듈 로드
  • 필요에 따라 추가 모듈 동적 로드

일반적인 문제와 해결 방법

  1. 문제 : 리플렉션 데이터 누락
  • 해결 : UCLASS(), UPROPERTY(), UFUNCTION() 매크로 올바르게 사용했는지 확인
  1. 문제 : 빌드 오류
  • 해결 : .Build.cs 파일에서 필요한 모듈 의존성 추가 확인
  1. 문제 : 핫 리로드 실패
  • 해결 : 클래스 구조를 크게 변경하지 않고, 함수 구현만 수정

C++ 통합의 이점과 제약사항

 이점

  1. 고성능 : 네이티브 코드 실행으로 높은 성능 제공
  2. 완전한 엔진 접근 : 엔진의 모든 기능에 접근 가능
  3. 서드파티 라이브러리 통합 : C / C++ 라이브러리 쉽게 통합 가능

 제약사항

  1. 컴파일 시간 : 변경 사항 적용에 시간 소요
  2. 복잡성 : 블루프린트에 비해 진입 장벽이 높음
  3. 플랫폼 의존성 : 플랫폼별 빌드 설정 필요

 언리얼 엔진과 C++의 통합은 강력한 게임 개발 환경을 제공합니다. UHT와 UBT를 통한 자동화된 처리 과정, 리플렉션 시스템을 통한 동적 타입 정보 접근, 그리고 가비지 컬렉션을 통한 자동 메모리 관리 등은 개발자가 게임 로직에 집중할 수 있게 해줍니다. 그러나 이러한 기능들을 효과적으로 활용하기 위해서는 언리얼 엔진의 특수한 매크로와 시스템에 대한 이해가 필요합니다. C++ 통합의 이점을 최대한 활용하면서도 그 제약사항을 잘 인지하고 대응하는 것이 성공적인 언리얼 엔진 C++ 개발의 핵심입니다.