icon안동민 개발노트

언리얼의 구조와 C++의 역할


 언리얼 엔진은 복잡하고 강력한 게임 개발 플랫폼으로, 다양한 모듈과 시스템으로 구성되어 있습니다.

 이 구조 안에서 C++는 핵심적인 역할을 담당하며, 엔진의 성능과 확장성을 뒷받침합니다.

언리얼 엔진의 아키텍처 개요

 언리얼 엔진은 모듈식 아키텍처를 채택하고 있으며 주요 모듈들은 다음과 같습니다.

  1. 렌더링 엔진
  2. 물리 엔진
  3. 오디오 시스템
  4. 네트워킹 시스템
  5. 게임플레이 프레임워크
  6. 에디터 서브시스템
  7. 에셋 관리 시스템

 이러한 모듈들은 서로 긴밀하게 상호작용하며 전체적으로 통합된 개발 환경을 제공합니다.

주요 모듈과 C++의 역할

 1. 렌더링 엔진

 렌더링 엔진은 언리얼 엔진의 가장 핵심적인 부분 중 하나로, 고품질의 그래픽을 실시간으로 처리합니다.

 C++의 역할

  • 저수준 그래픽 API(DirectX, Vulkan, Metal 등) 인터페이싱
  • 셰이더 컴파일 및 관리
  • 렌더링 파이프라인 구현

 예시 코드

class FMyCustomShader : public FGlobalShader
{
    DECLARE_SHADER_TYPE(FMyCustomShader, Global);
 
public:
    static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
    {
        return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
    }
 
    // 셰이더 파라미터 선언 및 초기화
};

 2. 물리 엔진

 물리 엔진은 게임 내 객체들의 물리적 상호작용을 시뮬레이션합니다.

 C++의 역할

  • 충돌 감지 알고리즘 구현
  • 리지드 바디 동역학 계산
  • 물리 기반 애니메이션 처리

 예시 코드

void AMyActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
 
    FVector Force = GetActorForwardVector() * 1000.0f;
    MyPrimitiveComponent->AddForce(Force);
}

 3. 오디오 시스템

 오디오 시스템은 게임 내 사운드 효과와 음악을 관리하고 재생합니다.

 C++의 역할

  • 오디오 디바이스 제어
  • 3D 사운드 처리
  • 오디오 효과 구현

 예시 코드

void AMyActor::PlayCustomSound()
{
    if (CustomSound)
    {
        UGameplayStatics::PlaySoundAtLocation(this, CustomSound, GetActorLocation());
    }
}

 4. 네트워킹 시스템 네트워킹 시스템은 멀티플레이어 게임을 위한 데이터 동기화와 통신을 담당합니다.

 C++의 역할

  • 네트워크 프로토콜 구현
  • 상태 복제 및 동기화
  • 레이턴시 보상 기법 적용

 예시 코드

UFUNCTION(Server, Reliable, WithValidation)
void AMyCharacter::ServerMove(FVector NewLocation)
{
    if (!ensure(GetLocalRole() == ROLE_Authority)) return;
 
    SetActorLocation(NewLocation);
}

C++ 코드를 위한 언리얼 엔진의 특수 도구

 언리얼 엔진은 C++ 코드를 효율적으로 처리하기 위한 여러 특수 도구를 제공합니다.

 1. 언리얼 헤더 도구 (UHT)

 UHT는 C++ 헤더 파일을 분석하여 언리얼 엔진의 리플렉션 시스템에 필요한 메타데이터를 생성합니다.

  • UCLASS(), UPROPERTY(), UFUNCTION() 등의 매크로 처리
  • 자동으로 생성된 코드를 통한 직렬화, 네트워크 복제 지원

 2. 언리얼 빌드 도구 (UBT)

 UBT는 프로젝트의 빌드 프로세스를 관리합니다.

  • 모듈 의존성 분석 및 빌드 순서 결정
  • 플랫폼별 컴파일 설정 관리
  • 핫 리로드 기능 지원

C++와 블루프린트의 상호작용

 C++와 블루프린트는 언리얼 엔진에서 긴밀하게 상호작용합니다.

 1. C++ 클래스 노출

  • UCLASS(), UPROPERTY(), UFUNCTION() 매크로를 사용하여 C++ 클래스와 멤버를 블루프린트에 노출

 2. 블루프린트 상속

  • C++ 클래스를 부모로 하는 블루프린트 클래스 생성 가능

 3. 네이티브 이벤트

  • C++에서 정의한 이벤트를 블루프린트에서 구현 가능

 예시 코드

UCLASS(Blueprintable)
class AMyActor : public AActor
{
    GENERATED_BODY()
 
public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    float MyFloat;
 
    UFUNCTION(BlueprintCallable)
    void MyFunction();
 
    UFUNCTION(BlueprintImplementableEvent)
    void MyBlueprintEvent();
};

C++ 코드의 엔진 통합

 C++로 작성된 코드는 다음과 같은 방식으로 언리얼 엔진과 통합됩니다.

 1. 모듈 시스템

  • C++ 코드를 모듈로 구성하여 엔진과 결합
  • 모듈은 독립적으로 컴파일되고 로드됨

 2. 리플렉션 시스템

  • UHT가 생성한 메타데이터를 통해 런타임에 객체 속성과 함수에 접근

 3. 가비지 컬렉션

  • UPROPERTY() 매크로로 선언된 객체들은 언리얼 엔진의 가비지 컬렉터에 의해 관리됨

 4. 에셋 시스템

  • C++로 정의된 에셋 타입을 언리얼 에디터에서 생성 및 편집 가능

 5. 네이티브 클래스 등록

  • 엔진 시작 시 C++ 클래스들이 자동으로 등록되어 인스턴스화 가능

 예시 코드 (모듈 정의)

// MyModule.cpp
##include "Modules/ModuleManager.h"
 
class FMyModule : public IModuleInterface
{
public:
    virtual void StartupModule() override
    {
        // 모듈 초기화 코드
    }
 
    virtual void ShutdownModule() override
    {
        // 모듈 종료 코드
    }
};
 
IMPLEMENT_MODULE(FMyModule, MyModule)

 이러한 구조와 도구들을 통해 C++는 언리얼 엔진의 코어 기능을 구현하고 확장하는 데 중추적인 역할을 합니다.

 개발자들은 엔진의 강력한 기능을 활용하면서도 필요에 따라 저수준의 최적화와 커스터마이징을 수행할 수 있습니다.

 C++와 블루프린트의 조화는 언리얼 엔진의 유연성과 접근성을 크게 향상시키며 다양한 규모와 유형의 게임 개발을 가능하게 합니다.