본문 바로가기

[C++과 Unreal Engine으로 3D 게임 개발] 클래스를 활용한 캐릭터 구현

@iamrain2025. 9. 18. 10:48

GameMode

GameMode는 게임의 전반적인 규칙과 흐름을 총괄하는, 컨트롤 타워 역할을 하는 클래스다.

 

싱글 플레이에서는 '서버'와 '클라이언트'가 나누어져 있지 않기 때문에, GameMode가 온전히 로컬에서 동작하여 전체를 제어한다.

어떤 Pawn(또는 Character)을 플레이어에게 스폰해줄지, 어떤 PlayerController를 사용할지, 승패 조건이나 점수 계산을 어떻게 설정할지 등 게임 플레이의 핵심 로직을 담당한다.

프로젝트 전역(기본) 혹은 레벨 별로 필요한 GameMode를 구분해 설정할 수 있다.

주요 기능과 책임

플레이어 Pawn / Character 스폰

  • 게임이 시작될 때(또는 플레이어가 리스폰 될 때), `DefaultPawnClass` 또는 지정한 Pawn 클래스가 자동으로 스폰된다.
  • 스폰된 Pawn을 플레이어가 조작할 수 있도록 PlayerController와 연동하는 역할

PlayerController 지정

  • 플레이어의 입력(키보드, 마우스, 게임패드 등)을 전달하고 처리하는 PlayerController가 어떤 클래스로 동작할지 설정한다.

게임 규칙 관련

  • 점수 계산, 타이머, 라운드 제어, 난이도 등 게임 전반의 규칙을 정의하고 유지한다.
  • 특정 점수 달성, 보스 처치, 시간 제한 등 승패를 결정하는 조건을 관리한다.
  • 승리 혹은 패배 확정 시, 후속처리 또한 담당한다.

GameState / PlayerState 사용

  • GameState는 전체 게임 흐름, PlayerState는 플레이어별 정보를 관리하는 용도로 쓰일 수 있다.

 

GameMode 클래스 생성

GameMode vs. GameModeBase

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

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

C++ 클래스 GameMode 생성

Tool -> New C++ Class...
GameMode 선택 후 Public으로 클래스 생성

GameMode 클래스 적용

직접 만든 클래스를 게임에 적용하려면, 블루프린트 클래스로 한 번 더 감싸는 방식을 권장한다. 이렇게 하면 세부 파라미터 수정에 더 유리하기 때문이다.

 

GameMode를 적용하는 방법은 크게 두 가지다.

  1. 프로젝트 전역 설정
    • Edit → Project Settings → Maps & Modes → Default GameMode를 생성한 블루프린트 클래스로 지정.
    • 프로젝트의 모든 레벨에 대해 기본 GameMode가 변경된다.
  2. 레벨 별 설정
    • Window → World Settings → GameMode Override를 생성한 블루프린트 클래스로 지정
    • 수정한 특정 레벨은 전역 설정 대신 지정한 GameMode를 사용한다.
프로젝트 전역 설정과 레벨 별 설정이 충동하면, 레벨 별 설정이 우선 적용된다.

GameMode 기본 설정 확인

별도의 코드나 설정을 안했기 때문에 언리얼 엔진의 기본값이 적용되어 있다.

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

 

Pawn과 Character 클래스

Pawn 클래스란?

Pawn은 플레이어 혹은 AI가 "소유(Possess)" 할 수 있는 가장 상위 클래스로 엔진에서 무언가를 조종할 때 기본이 되는 형태다.

 

기본적으로 이동 로직이나 충돌, 중력, 네트워크 이동을 위한 기능이 포함되어 있지 않다.

Character 클래스란?

Pawn을 상속받아 만들어진 자식 클래스 중 하나로, `UCharacterMovementComponent`를 기본으로 포함하고 있다.

 

이동, 회전, 점프, 중력, 지형 따라가기, 네트워크 동기화 등 보행형 캐릭터에게 필요한 기능이 이미 구현되어 있어, 사람 형태의 캐릭터를 쉽게 만들 수 있다.

미리 정의된 함수(`MoveForward`, `MoveRight`, `Jump` 등)가 존재하므로, 몇 줄의 코드만 추가해도 움직임을 테스트할 수 있다.

 

Character 클래스 생성

Tool -> New C++ Class...
Character 선택 후 Public으로 클래스 생성
Blueprint 생성

Character 클래스 구조

생성한 블루프린트를 열어보면 컴포넌트 트리에 몇 가지 기본 컴포넌트가 포함되어 있다.

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

 

스켈레탈 메시 설정

스켈레탈 메시(Skeletal Mesh)란?

내부에 뼈대(Skeleton)를 갖춘 3D 모델을 의미한다.

Bone이 부모-자식 관계로 연결되어 있으며, Bone이 움직이면 외형(Mesh)도 함께 움직인다. 본과 메시가 연동되기 때문에 애니메이션에 맞춰 동작을 구현할 수 있다.

Mesh 컴포넌트에서 에셋 적용

 

카메라 및 GameMode 설정

SpringArm 및 CameraComponent 추가

`.h`

#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;

};

`.cpp`

#include "SpartaCharacter.h"

#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"

ASpartaCharacter::ASpartaCharacter()
{
	PrimaryActorTick.bCanEverTick = false;

	SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
	SpringArmComp->SetupAttachment(RootComponent);
	SpringArmComp->TargetArmLength = 300.0f;
	SpringArmComp->bUsePawnControlRotation = true;

	CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
	CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
	CameraComp->bUsePawnControlRotation = false;
}

void ASpartaCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

}

GameMode에서 DefaultPawnClass 설정

`.h`

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameMode.h"
#include "SpartaGameMode.generated.h"

UCLASS()
class SPARTAPROJECT_API ASpartaGameMode : public AGameMode
{
	GENERATED_BODY()

public:
	ASpartaGameMode();
};

`.cpp`

#include "SpartaGameMode.h"
#include "SpartaCharacter.h"

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

 

빌드 후 언리얼 에디터에서 프로젝트 세팅 혹은 World Settings의 GameMode를 확인한다.

GameMode의 Default Pawn Class를 생성한 블루프린트로 변경한다.

iamrain
@iamrain :: Annals of Unreal

iamrain 님의 블로그 입니다.

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차