컨텐츠 검색
[UE5 C++] 언리얼 엔진 C++ 개발 기초 정리

2026. 1. 12. 20:13Unreal Engine/개념

0. 개발 환경 구성

항목 내용
Visual Studio VS 2022 v17.8 이상 필요 (UE 5.5 호환).
워크로드 'C++를 사용한 데스크톱 개발', 'C++를 사용한 게임 개발' 두 가지 필수 설치.

1. 프로젝트 폴더 및 파일 구조

1-1. 최상위 파일 및 폴더

이름 유형 설명
.sln 파일 Visual Studio 솔루션 파일로, 프로젝트와 엔진 코드를 연결하는 진입점이다.
.uproject 파일 JSON 형식으로 된 프로젝트 디스크립터로, 플러그인 및 모듈 설정을 담고 있다.
.vsconfig 파일 프로젝트 실행에 필요한 VS 워크로드 및 구성 요소를 자동 감지하여 설치를 유도한다.
Binaries 폴더 컴파일된 실행 파일(.exe)과 동적 링크 라이브러리(.dll)가 저장된다.
Config 폴더 게임 및 엔진 설정을 위한 .ini 파일들이 저장된다.
Content 폴더 에셋(모델, 텍스처, 블루프린트 등)이 저장되며 에디터 콘텐츠 브라우저와 동기화된다.
DerivedDataCache 폴더 로딩 속도 향상을 위해 셰이더 컴파일 정보 등 가공된 에셋 데이터를 캐싱한다.
Intermediate 폴더 컴파일 시 생성되는 임시 객체 파일과 빌드 부산물이 저장되며 삭제 시 재생성된다.
Saved 폴더 자동 저장, 로그, 스크린샷, 크래시 덤프 등 런타임에 생성된 데이터가 모인다.
Source 폴더 C++ 소스 코드가 위치하며 실제 게임 로직과 클래스를 작성하는 곳이다.
.vs 폴더 (숨김 폴더) 사용자별 창 배치, 중단점 등 VS의 로컬 설정이 저장된다.

1-2. Config 내부 주요 파일

파일명 설명
DefaultEditor.ini 에디터 시작 시 로드할 맵이나 에디터 전용 환경 설정을 정의한다.
DefaultEditorSettings.ini 사용자 개인의 에디터 선호 설정이 저장되는 경우가 많으며 협업 시 제외하기도 한다.
DefaultEngine.ini 렌더링, 물리, 네트워킹 등 엔진 코어 시스템의 전반적인 설정을 담당한다.
DefaultGame.ini 기본 게임 모드, HUD 클래스 등 게임플레이 프레임워크 관련 설정을 정의한다.
DefaultInput.ini 키보드, 마우스, 패드 등의 액션 매핑 및 축 매핑(키 바인딩)을 설정한다.

1-3. Source 폴더 내부 빌드 파일

파일명 설명
프로젝트.Build.cs 해당 모듈(게임)이 의존하는 다른 모듈(Core, Engine 등)이나 라이브러리를 정의한다.
프로젝트.Target.cs 게임 실행 파일(Shipping, Development 등)을 빌드하기 위한 전체적인 설정을 정의한다.
프로젝트Editor.Target.cs 언리얼 에디터용 DLL을 빌드하기 위한 설정을 정의하며 에디터 실행 시 사용된다.

2. 언리얼 명명 규칙 (Coding Standard)

접두사 대상 설명
A Actor 월드에 스폰될 수 있는 모든 액터 클래스에 붙인다 (예: AActor).
U UObject 액터는 아니지만 엔진의 관리를 받는 모든 객체 클래스에 붙인다 (예: UObject).
F General UObject를 상속받지 않는 일반 C++ 클래스나 구조체에 붙인다 (예: FVector).
T Template 데이터 타입이 정해지지 않은 템플릿 클래스에 붙인다 (예: TArray).
E Enum 여러 상태나 타입을 정의하는 열거형(Enum)에 붙인다 (예: ECollisionChannel).
I Interface 클래스 간 통신을 위해 구현해야 하는 인터페이스 클래스에 붙인다 (예: IInteractable).
S Slate 언리얼의 커스텀 UI 프레임워크인 Slate 위젯 클래스에 붙인다 (예: SButton).
b Bool 참/거짓을 나타내는 불리언 변수명 앞에 소문자 b를 붙인다 (예: bIsDead).

3. 리플렉션 시스템과 매크로

3-1. 기본 개념

개념 설명
리플렉션 (Reflection) 프로그램이 런타임에 자신의 구조(클래스, 변수 등)를 파악하고 수정할 수 있는 기능이다.
UHT (Unreal Header Tool) 헤더를 파싱하여 리플렉션 데이터와 글루(Glue) 코드를 generated.h에 생성한다.
Garbage Collection UPROPERTY로 지정된 객체들의 참조를 추적하여 사용되지 않는 메모리를 자동 해제한다.

3-2. 주요 매크로

매크로 설명
UCLASS() 클래스를 엔진에 등록하고 블루프린트와의 상속/참조 관계를 정의한다.
UPROPERTY() 변수를 에디터에 노출하거나 블루프린트에서 접근하는 권한을 제어한다.
UFUNCTION() C++ 함수를 블루프린트에서 호출하거나 구현 방식을 정의한다.

4. 클래스 생성과 코드 구조

4-1. 파일 생성 위치에 따른 접근 제어

생성 위치 설명
Public 헤더는 Public 폴더, 소스는 Private 폴더에 생성되며 타 모듈에서 해당 클래스를 포함(Include)할 수 있다.
Private 헤더와 소스 모두 Private 폴더에 생성되며, 해당 모듈 내부에서만 사용하고 외부는 차단한다.

4-2. Actor 클래스 기본 코드 분석

코드 라인 설명
#pragma once 헤더 파일이 컴파일 시 단 한 번만 포함되도록 하여 중복 정의 오류를 방지한다.
#include "CoreMinimal.h" 언리얼의 가장 기본적인 자료형(FString 등)과 로그 기능을 포함하는 경량 헤더이다.
#include "GameFramework/Actor.h" AActor 클래스의 정의가 들어있어 상속받기 위해 필수적이다.
#include "클래스명.generated.h" UHT가 생성한 파일로, 반드시 include 목록의 가장 마지막에 위치해야 한다.

5. Actor 라이프 사이클 (생명주기)

단계 함수명 설명
초기화 생성자 (Constructor) CDO(Class Default Object)를 생성하고 컴포넌트 초기화 및 기본값을 설정한다.
PostInitializeComponents() 모든 컴포넌트의 초기화가 완료된 직후 호출되며 컴포넌트 간 의존성 설정에 쓴다.
게임 시작 BeginPlay() 게임이 실제로 시작되거나 액터가 월드에 스폰된 직후 게임 로직을 시작할 때 호출된다.
업데이트 Tick(float DeltaTime) 매 프레임마다 호출된다. DeltaTime은 이전 프레임과의 시간차로 프레임 독립적인 이동 구현에 쓰인다.
종료 EndPlay() 액터가 수명을 다하거나 레벨이 전환되어 제거되기 직전에 호출된다.
Destroyed() 액터가 메모리에서 완전히 제거되는 과정에서 호출된다.
주의사항 Super::함수명() 부모 클래스의 중요 로직(엔진 내부 처리)을 실행하기 위해 반드시 오버라이드 함수 내에서 호출해야 한다.
    // PostInitializeComponents: 컴포넌트가 완성된 직후 호출되는 함수
    // 컴포넌트끼리 데이터 주고받기, 상호작용 등에 사용
    virtual void PostInitializeComponents() override;

    // BeginPlay: Actor가 배치(Spawn)된 직후 호출되는 함수
    // 게임 시작 시 한 번 호출
    virtual void BeginPlay() override;

    // Tick: 매 프레임마다 호출되는 함수
    // DeltaTime: 이전 프레임과 현재 프레임 사이의 시간 간격
    virtual void Tick(float DeltaTime) override;

    // Destroyed: Actor가 삭제되기 직전에 호출되는 함수
    // 리소스 해제, 참조 정리 등에 사용
    virtual void Destroyed() override;

    // EndPlay: Actor가 게임에서 제거되기 직전에 호출되는 함수
    // EEndPlayReason::Type 열거형 매개변수를 통해 제거되는 이유를 알 수 있다.
    // 게임 종료, 파괴, 레벨 전환 등 다양한 이유가 있다.
    virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

6. 컴포넌트와 트랜스폼

6-1. 주요 컴포넌트 목록

컴포넌트 설명
Scene Component 트랜스폼(위치, 회전, 크기) 정보만 가지고 있으며, 자식 컴포넌트들을 그룹화하는 부모 역할을 한다.
Static Mesh Component 애니메이션이 없는 고정된 3D 모델을 렌더링하고 물리 충돌을 처리한다.
Skeletal Mesh Component 뼈대(Bone)가 있어 애니메이션을 재생할 수 있는 캐릭터나 몬스터의 모델을 처리한다.
Camera Component 플레이어가 세상을 보는 시점(눈) 역할을 하며, 화면 렌더링 영역을 결정한다.
Spring Arm Component 카메라와 캐릭터 사이의 거리를 유지하고, 벽에 가려질 때 카메라를 당겨주는 3인칭 시점용 도구다.
Box/Sphere/Capsule Component 렌더링되지 않는 단순한 도형 모양으로, 충돌 감지(Trigger)나 물리 경계 설정에 사용한다.
Audio Component 게임 내에서 사운드 큐나 웨이브 파일을 재생하여 소리를 나게 한다.
Particle System / Niagara Component 불꽃, 연기, 마법 효과 등 시각적인 파티클 이펙트를 생성하고 제어한다.
Character Movement Component 걷기, 점프, 수영, 비행 등 캐릭터의 물리적인 움직임 로직을 자동으로 처리해준다.
Widget Component 체력바나 닉네임처럼 3D 월드 공간 안에 UI 위젯을 띄울 때 사용한다.
AItem::AItem()
{
    // 씬 컴포넌트를 생성해 포인터에 연결한다.
    SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));

    // 씬 컴포넌트를 루트 컴포넌트로 한다.
    SetRootComponent(SceneRoot);

    // 스태틱 메시 컴포넌트를 생성해 포인터에 연결한다.
    StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));

    // 씬 컴포넌트에 스태틱 메시 컴포넌트를 붙인다.
    StaticMeshComp->SetupAttachment(SceneRoot);

    // 오디오 컴포넌트를 생성해 포인터에 연결한다.
    AudioComp = CreateDefaultSubobject<UAudioComponent>(TEXT("AudioComp"));

    // 스태틱 메시 컴포넌트에 오디오 컴포넌트를 붙인다.
    AudioComp->SetupAttachment(StaticMeshComp);
}

6-2. 좌표계와 Transform

개념 설명
절대좌표계 (World) 게임 월드의 원점(0,0,0)을 기준으로 하는 불변의 전역 좌표이다.
로컬좌표계 (Local) 부모 컴포넌트나 액터 자신을 기준으로 하는 상대적인 좌표이다.
위치 (Location) X, Y, Z 축의 벡터(FVector)로 표현되는 공간상의 지점이다.
회전 (Rotation) Roll, Pitch, Yaw의 오일러 각(FRotator) 혹은 쿼터니언(FQuat)으로 표현된다.
스케일 (Scale) X, Y, Z 축 방향으로의 크기 배율을 나타낸다.
쿼터니언 (Quaternion) 짐벌 락(Gimbal Lock) 현상을 방지하고 부드러운 회전 보간을 위해 사용하는 4차원 복소수 체계이다.

7. 게임 수학의 활용

함수/개념 활용 방법
Sin (사인) -1 ~ 1 사이를 왕복하므로 아이템의 부유 효과(둥둥 뜨는 모션)나 색상 점멸 등에 사용한다.
Cos (코사인) Sin과 함께 사용하여 원운동을 구현하거나, 주기적인 패턴을 만들 때 사용한다.
Tan (탄젠트) 시야각(FOV) 계산이나 빗변이 아닌 두 변의 비율로 각도를 구할 때 활용한다.
void ABigSmallActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    // 1. 위치 변경 (Z축으로 일정 속도 이동)
    FVector MoveOffset = FVector(0.0f, 0.0f, SpeedZ * DeltaTime);
    AddActorWorldOffset(MoveOffset);

    // 2. 회전 변경 (Yaw축 회전)
    FRotator RotOffset = FRotator(0.0f, RotationSpeed * DeltaTime, 0.0f);
    AddActorLocalRotation(RotOffset);

    // 3. 스케일 변경 (2초 주기로 커졌다 작아졌다 반복)
    // 설명: DeltaTime을 직접 누적하기보다 엔진의 절대 시간(GetTimeSeconds)을 쓰는 것이 오차 없이 정확하다.
    float Time = GetWorld()->GetTimeSeconds();

    // 2초 주기 공식: Sin(Time * PI)
    // 설명: 주파수(B) = 2π / 주기(T). 주기가 2초이므로 B = π 이다.
    float SinValue = FMath::Sin(Time * PI); // 결과: -1.0 ~ 1.0

    // 범위를 0.0 ~ 1.0으로 변환 (Lerp에 쓰기 위함)
    float Alpha = (SinValue + 1.0f) / 2.0f;

    // 0.5배 ~ 2.0배 사이를 부드럽게 보간
    float NewScale = FMath::Lerp(0.5f, 2.0f, Alpha);

    SetActorScale3D(FVector(NewScale));

}