Unreal 게임 개발 과정 TIL

Today's I Learning

본캠프 TIL

06.10 Unreal 본캠프) Character 클래스 활용하여 캐릭터 구현

Sunlight__ 2026. 6. 10. 20:53

 

오늘 배운 것 

 

1. GameMode 이해하기

 - GameMode란?

- GameMode는 게임의 전반적인 규칙과 흐름을 총괄 관리하는, 일종의 컨트롤러 타워 역할을 하는 클래스이다.
- 싱글 플레이에서는 '서버' 와 '클라이언트' 개념이 나뉘지 않으므로, GameMode가 온전히 로컬에서 동작하여 게임 전체를 제어한다.
- 어떤 Pawn (또는 Character)을 플레이어에게 스폰해줄지, 어떤 PlayerController를 사용할지, 승패 조건이나 점수 계산 방법은 어떻게 설정할지 등 게임 플레이의 핵심 로직을 담당한다.
   : 프로젝트 전역(기본) 혹은 레벨별로 필요한 GameMode를 구분해 설정할 수 있다.
     예) 튜토리얼 맵 전용 GameMode, 일반 맵 전용 GameMode 등

 

 - GameMode의 주요 기능과 책임

 - 플레이어 Pawn/Character 스폰
 : 게임이 시작될 때 (또는 플레이어가 리스폰 될 때), DefaultPawnClass 또는 지정한 Pawn 클래스자동으로 스폰한다.
   스폰된 Pawn을 플레이어가 조작할 수 있도록, PlayerController와 연동해주는 역할을 한다.
 - PlayerController 지정
 : 플레이어의 입력 (키보드, 마우스, 게임패드 등)을 전달하고 처리하는 PlayerController가 어떤 클래스로 동작할지 설정한다.
 - 게임 규칙 관리
 : 점수 계산, 타이머, 라운드 제어, 난이도 등 게임 전반의 규칙을 정의하고 유지한다.
   특정 점수 달성, 보스 몬스터 처치, 제한 시간 종료 등 승리/패배를 결정하는 조건을 관리한다.
   승리 혹은 패배가 확정되면, 게임 오버 화면을 띄우거나 다음 레벨로 전환하는 식의 후속 처리를 담당한다.
- GameState / PlayerState 사용
 : GameState는 전체 게임 흐름 (타이머, 전역 변수 등), PlayerState는 플레이어별 정보 (체력, 점수 등)를 관리하는 용도로 쓰일 수 있다.
   멀티플레이만큼 복잡하게 쓰진 않더라도, 상태 저장과 관리를 좀 더 체계적으로 하고 싶을 때 유용하다.

 

2. GameMode 클래스 생성하기

 - GameMode vs GameModeBase

: 언리얼 엔진 5에는 GameMode와 GameModeBase 두 종류가 있다.

- GameMode
 : 언리얼에서 제공하는 멀티플레이 기능 (세션, 플레이어 연결 로직)을 일부 포함하고 있으며, 싱글 플레이에서도 문제없이 사용할 수 있다.
   필요에 따라 GameState, PlayerState 등 연동이 활성화 되어 있다.
 - GameModeBase
 : 좀 더 단순화 된 형태로, 멀티플레이 관련 로직이 거의 포함되지 않는다.
   간단한 싱글 플레이 게임 또는 직접 멀티플레이 로직을 구현하고 싶을 때 사용하기도 한다.

 

- C++ 클래스 GameMode 생성

- 언리얼 에디터 상단 메뉴에서 Tools -> New C++ Class를 클릭한다.
- Common Classes 목록 또는 검색창에서 GameMode를 선택한다.
- 클래스 접근 수준을 Public으로 설정한 후, 클래스 이름을 SpartaGameMode로 지정하고 CreateClass 버튼을 클릭한다.
- 잠시 후 엔진이 프로젝트를 빌드하고, Visual Studio에서 SpartaGameMode.h SpartaGameMode.cpp 파일을 자동으로 열어준다.
- 코드를 열어 보면 SpartaGameMode 클래스GameMode를 상속받고 있으며, 아직 아무런 로직이 구현되지 않은 기본 골격만 갖추고 있다.

 

 - GameMode 클래스 적용

 : 직접 만든 C++ GameMode 클래스를 게임에서 활용하려면, 일반적으로 블루프린트 클래스로 한 번 더 감싸는 방식을 권장한다.

   이렇게 하면, 에디터에서 세부 파라미터를 수정하기 훨씬 편리하기 때문이다.

 - Content Browser에서 SpartaGameMode를 우클릭하고, Create Blueprint Class based on SpartaGameMode를 선택한다.
 - 이름은 BP_SpartaGameMode로 지정하고, Blueprints 폴더에 생성한다.

 

 - 언리얼 엔진에서 GameMode를 적용하는 방법은 크게 2가지이다.

 

1) 프로젝트 전역 설정

- 상단 메뉴 Edit -> Project Settings로 이동 -> 왼쪽 목록에서 Maps & Modes 항목 선택
- Default GameMode 를 BP_SpartaGameMode로 지정
- 이 프로젝트의 모든 레벨에 대해 기본 GameMode가 BP_SpartaGameMode가 된다.

 

2) 레벨 별 설정

- 상단 메뉴 Window -> World Settings를 클릭해 World Settings 창을 연다.

- 현재 열려 있는 레벨의 GameMode OverrideBP_SpartaGameMode로 지정

 

- 이렇게 하면, 이 특정 레벨은 프로젝트 전역 설정 대신 BP_SprataGameMode를 사용하게 된다.

 

 * 만약 프로젝트 전역 설정과 레벨 별 설정이 충돌한다면, 레벨 별 설정 (World Settings)이 우선 적용된다.

   즉, 레벨에서 오버라이드 된 GameMode가 존재한다면 그 레벨에서는 해당 GameMode를 사용하고, 그렇지 않은 레벨은 전역에 설정된 GameMode를 사용한다.

 

 - 게임 모드 기본 설정 확인

 : 현재 BP_SpartaGameMode에는 별도의 코드나 설정이 없으므로, 언리얼 엔진의 기본값이 적용된다.

   World Settings 창의 'Selected GameMode' 영역을 펼쳐보면 다음과 같은 기본 클래스를 확인 할 수 있다.

- Default Pawn Class : 레벨 시작 시 플레이어가 조종하게 될 Pawn(또는 Character) 클래스를 지정한다.
- HUD Class : 게임 화면에 표시되는 HUD(UI) 요소를 관리하는 클래스를 지정한다.
- Player Controller Class : 플레이어 입력 처리와 카메라 제어, UI와의 상호작용을 담당하는 클래스를 지정한다.
- Game State Class / Player State Class : 게임의 전역 상태나 플레이어별 상태를 추적할 때 사용한다.
- Spectator Class : 관전자 모드에서 사용할 Pawn 클래스를 지정한다. 일반 플레이어와 다른 이동 방식이나 카메라 제어가 필요할 때 활용한다.

 

3. Pawn과 Character 클래스 이해하기

 - Pawn 클래스란?

 - Pawn은 플레이어 혹은 AI가 "소유 (Possess)" 할 수 있는 가장 상위 클래스이다.
   즉 엔진에서 "무언가를 조종한다" 라고 할 때 기본이 되는 형태가 Pawn이 된다.
- Pawn에는 이동 로직이나 충돌 처리, 중력, 네트워크 이동을 위한 기능들이 기본적으로 포함되어 있지 않다.
      - 보행(걷기, 달리기, 점프 등)에 필요한 시스템(캡슐 콜리전, 중력, 지형 따라가기)을 모든 단계에서 직접 구현해야 하므로, 사람 캐릭터를 처음부터 Pawn으로 만들기에는 다소 부담이 크다.
- 이러한 특성 덕분에, 비행기, 드론, 카메라처럼 기존 Character의 이동 방식을 벗어난 특수한 로직을 완전히 자유롭게 구현할 때 유용하다.

 

 - Character 클래스란?

- Character는 Pawn을 상속 받아 만들어진 자식 클래스 중 하나로, 기본적으로 UChracterMovementComponent를 포함하고 있다.
      - 이동, 회전, 점프, 중력, 지형 따라가기, 네트워크 동기화 등 보행형 캐릭터에게 필요한 기능이 이미 구현되어 있어, 사람이 달리고 점프하는 형태의 캐릭터를 쉽게 만들 수 있다.
      - 여기에 미리 정의된 대표적인 함수들(에: MoveForward, MoveRight, Jump)이 존재하므로, 몇 줄의 모드만 추가해도 금방 캐릭터 움직임을 테스트 할 수 있다.
- 캐릭터를 구성하는 전형적인 요소들이 표준화되어 있어, 일반적인 인간형 캐릭터를 만드는 데 최적화되어 있다.
      - 단, 자동차비행기처럼 완전히 다른 이동 방식을 구현할 때는 Character 내부에 탑재된 기능들이 오히려 방해가 될 수 있다. 이런 경우에는 Pawn을 직접 확장해서 사용하는 것을 고려해야 한다.

 

 - Character 클래스 생성

- 언리얼 에디터 상단 메뉴에서 Tools -> New C++ Class클릭한다.
- 부모 클래스로 Character를 선택한다.
- 클래스 이름은 SpartaCharacter로, Public 접근 지정자로 설정한 뒤 Create Class를 클릭한다.
- C++ 클래스가 생성되면 Contetnt Browser에서 C++ Classes 폴더 내의 SpartaCharacter 클래스를 우클릭하여, Create Blueprint class based on SpartaCharacter를 선택한다.
- 이름을 BP_SpartaCharacter로 지정하고, Blueprints 폴더에 저장한다.

 

- Chracter 클래스 구조 살펴보기

 : BP_SpartaCharacter를 열면, 왼쪽 컴포넌트 트리에 이미 여러 기본 컴포넌트가 포함되어 있다.

 

1. CapsuleComponent (Root Component)
 - 캐릭터가 벽이나 지형에 충돌하는 범위를 정의하는 콜리전 컴포넌트이다.
 - 캡슐 형태이며, Radius (반지름)와 Half Height (높이 절반)를 조정해 캐릭터의 물리적 크기를 설정할 수 있다.
2. ArrowComponent
 - 캐릭터가 어느 방향을 바라보고 있는지를 표시하기 위해 씬에 화살표를 띄워주는 컴포넌트이다.
 - 게임플레이 로직에는 직접적인 영향을 주지 않고, 주로 편집기에서 시각적 디버깅용으로 사용된다.
3. SkeletalMeshComponent
 - 캐릭터의 3D 모델애니메이션을 적용하는 컴포넌트이다.
 - Skeletal Mesh, Anim Blueprint 등을 여기로 할당해 캐릭터의 외형과 동작을 제어한다.
4. CharacterMovementComponent
 - 캐릭터의 이동, 점프, 중력, 네트워크 동기화 등 물리적 이동 로직을 담당하는 핵심 컴포넌트이다.
 - 언리얼에서 제공하는 주요 이동 함수 (MoveForward, MoveRight, Jump)가 이미 연결되어 있어, 최소한의 코드만으로 캐릭터 조작을 구현할 수 있다.

 

5. 스켈레탈 메시 설정하기하기

 - Skeleta Mesh란?

- Skeletal Mesh는 내부에 뼈대(Skeleton)를 갖춘 3D 모델을 의미한다.
   : 이 뼈대(본, Bone)가 부모-자식 관계로 연결되어 있으며, 본이 움직이면 외형 (Mesh)도 함께 움직이게 된다.
     예 : 팔, 다리, 머리 등 신체 부위별 본이 존재한다.
- 본과 메시가 연동되기 때문에, 애니메이션 (Bone 움직임)에 맞춰 캐릭터가 뛰거나 걷는 동작을 구현할 수 있다.
- 언리얼 엔진은 물리 엔진과도 연결할 수 있어, Ragdoll(피격 후 쓰러지는) 효과 등 물리 기반 애니메이션도 쉽게 가능하다.

 

 - 메시 위치 및 방향 조절

- 메시 방향 조정
   - 언리얼에서 일반적으로 캐릭터의 전방 방향은 X축이다.
   - 그러나 SKM_Manny나 SKM_Quinn의 모델은 Y축을 전방으로 사용하기 때문에, 적용 후 캐릭터가 옆을 보는 것 처럼 보일 수 있다.
   - 이를 해결하려면 Mesh 컴포넌트 선택Details 패널에서 Rotation -> Yaw(Z축) 값을 -90도로 조정한다. 

 

 - 캡슐 크기와 메시 위치 조정

- 언리얼의 Character 클래스최상위 루트CapsuleComponent(캡슐 형태 충돌체)를 사용한다.
- 그 내부 중앙 부분Skeletal Mesh가 위치하게 된다.
- BP_SpartaCharacter 뷰표트에서 Mesh 컴포넌트를 선택한 뒤, Location 값을 조정해 캐릭터의 발이 캡슐 바닥에 정확히 닿도록 위치를 맞춘다.
- 캡슐 충돌 범위가 너무 작거나 크면 게임 플레이 시 충돌 문제가 발생할 수 있으므로, CapsuleComponent를 선택하고 Half Height, Radius 값을 적절히 조절한다.

 

6. 카메라 및 GameMode 설정하기

 : 3인칭 게임에서는 플레이어가 캐릭터의 뒤쪽이나 어깨 너머 시점을 보며 이동하는 경우가 많다.

   이를 위해 SpringArmCameraComponent를 추가한다.

   이후 GameMode 설정을 통해, 만든 캐릭터가 스폰되도록 구성한다.

 

 - SpringArm 및 CameraComponent 추가

 : SpartaCharacter.h를 열고, 아래처럼 스프링 암(SpringArm)과 카메라(Camera) 관련 클래스를 전방 선언하고 프로퍼티를 추가한다.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SpartaCharacter.generated.h"

class USpringArmComponent;   // 스프링 암 관련 클래스 전방 선언
class UCameraComponent;   // 카메라 관련 클래스 전방 선언

UCLASS()
class SPARTAPROJECT_API ASpartaCharacter : public ACharacter
{
      GENERATED_BODY()

public:
      ASpartaCharacter();

protected:
      // 스프링 암 컴포넌트
      UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
      USpringArmComponent* SpringArmComp;

      // 카메라 컴포넌트
      UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
      UCameraComponent* CameraComp;

      virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};

SpartaCharacter.h

 

 - Forward Declaration (전방 선언) : 전방 선언은 헤더 파일의 의존성을 줄이는 좋은 습관이다. (필요할 때만 #include를 추가)

 

 - SpringArmComp

: 스프링 암 컴포넌트(카메라 붐). 캐릭터와 카메라 간의 거리를 유지하고, 충돌 시 카메라가 벽 등에 박히지 않도록 자동 조정해준다.

 - CameraComp

 : 실제로 화면에 표시되는 카메라 컴포넌트이다. 위치와 회전을 제어하면 게임 뷰가 변경된다.

 

#include "SpartaCharacter.h"
// 카메라, 스프링 암 실제 구현이 필요한 경우라서 include
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"

ASpartaCharacter::ASpartaCharacter()
{
      // Tick 함수는 우선 꺼둔다.
      PrimaryActorTick.bCanEverTick = false;

      // (1) 스프링 암 생성
      SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
      // 스프링 암을 루트 컴포넌트 (CapsuleComponent)에 부착
      SpringArmComp->SetupAttachment(RootComponent);
      // 캐릭터와 카메라 사이의 거리 기본값 300으로 설정
      SpringArmComp->TargetArmLength = 300.0f;
      // 컨트롤러 회전에 따라 스프링 암도 회전하도록 설정
      SpringArmComp->bUsePawnControlRotation = true;
      // (2) 카메라 컴포넌트 생성
      CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
      // 스프링 암의 소켓 위치에 카메라를 부착
      CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
      // 카메라는 스프링 암의 회전을 따르므로 PawnControlRotation은 꺼둠
      CameraComp->bUsePawnControlRotation = false;
}

SpartaCharacter.cpp

 

 - SpringArmComp->bUsePawnControlRotation = true

 : 플레이어가 마우스를 움직이면 Controller의 회전 값이 변경되고, 이 때 스프링 암도 같이 회전하도록 설정한다.

   결과적으로 카메라도 따라 회전하여 3인칭 시점을 자연스럽게 구현할 수 있다.

- CameraComp->bUsePawnControRotation = false

 : 이미 스프링 암이 회전을 처리하므로, 카메라 자체는 PawnControlRotation을 사용하지 않도록 한다.

 

- GameMode에서 DefaultPawnClass 설정

 : DefaultPawnClass"게임 시작 시 어떤 캐릭터 Pawn)를 플레이어에게 제공할 것인지" 를 결정한다.

   만든 SpartaCharacter가 기본 캐릭터로 스폰되도록 설정하려면, SpartaGameMode에 다음과 같은 코드를 추가한다.

public:
      ASpartaGameMode();

SpartaGameMode.h

#include "SpartaCharacter.h"

ASpartaGameMode::ASpartaGameMode()
{
      DefaultPawnClass = ASpartaCharacter::StaticClass();
}

SpartaGameMode.cpp

 

  - 이 코드가 있으면, 게임 시작 시 SpartaCharacter가 자동으로 스폰되고, PlayerController와 연결되어 플레이어가 조작할 수 있게 된다.

 

 

오늘 배운 것에서 개인적으로 중요하다고 생각하는 것

- Forward Declaration (전방 선언)
 : 전방 선언은 구체적인 내용(.h파일)을 통째로 들고 오는 대신, 이름표만 먼저 보여주는 것이다. (빌드 시간 획기적으로 단축)
- bUsePawnControlRotation = true or false

 : "카메라(또는 스프링 암)의 회전을 플레이어의 입력(컨트롤러 회전)에 동기화 할 것인가?" 를 결정하는 것이다.