
GameMode클래스로 생성하면 cpp,h파일이 각각 생성된다
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameMode.h"
#include "SpartaGameMode.generated.h"
UCLASS()
class SPARTAPROJECT_API ASpartaGameMode : public AGameMode
{
GENERATED_BODY()
};
GameMode.h
#include "SpartaGameMode.h"
GameMode.cpp



BP_SpartaGameMode (내부적으로 SpartaGameMode)가 GameMode로 동작하는 모습을 볼 수 있다.
UCharacterMovementComponent를 포함하고 있다.MoveForward, MoveRight, Jump)이 존재하므로, 몇 줄의 코드만 추가해도 금방 캐릭터 움직임을 테스트할 수 있다.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SpartaCharacter.generated.h"
UCLASS()
class SPARTAPROJECT_API ASpartaCharacter : public ACharacter
{
GENERATED_BODY()
public:
ACharacter();
protected:
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
Character.h
#include "Character.h"
ASpartaCharacter::ACharacter()
{
PrimaryActorTick.bCanEverTick = true;
}
void ACharacter::BeginPlay()
{
Super::BeginPlay();
}
void ACharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ACharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
Character.cpp



MoveForward, MoveRight, Jump)가 이미 연결되어 있어, 최소한의 코드만으로 캐릭터 조작을 구현할 수 있다.
#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; // 이 함수는 이후에 다루게 되니, 우선 삭제하기 않고 둡니다.
};
Character.h
VisibleAnywhere, BlueprintReadOnly: 블루프린트에서 보기만 가능하고, C++ 코드 쪽에서만 수정 가능하게 하는 속성이다.#include를 추가)SpringArmCompCameraComp#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;
}
void ASpartaCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
Character.h
SpringArmComp->bUsePawnControlRotation = true
CameraComp->bUsePawnControlRotation = false
- 이미 스프링 암이 회전을 처리하므로, 카메라 자체는 PawnControlRotation을 사용하지 않도록 한다.
그 후 빌드후 언리얼 에디터로 돌아오면

SpringArmComp와 CameraComp가 추가된 것을 확인할 수 있다.
그 후 카메라를 잘 보기좋게 조절하자.



#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameMode.h"
#include "SpartaGameMode.generated.h"
UCLASS()
class SPARTAPROJECT_API ASpartaGameMode : public AGameMode
{
GENERATED_BODY()
public:
ASpartaGameMode();
}
GameMode.h
#include "SpartaGameMode.h"
#include "SpartaCharacter.h"
ASpartaGameMode::ASpartaGameMode()
{
DefaultPawnClass = ASpartaCharacter::StaticClass();
}
GameMode.cpp

SetupInputComponent() 함수를 오버라이드하여, 블루프린트에서는 이벤트 그래프를 통해 입력 로직을 구현한다.UnPossess() 함수를 호출하여 Pawn과의 연결을 해제한 뒤, 다른 Pawn으로 바꿔 탈 수도 있다.PlayerController 클래스를 선택하여 만들면 PlayerController.cpp와 PlayerController.h 파일이 생성된다. 코드는 아래와 같다.#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "SpartaPlayerController.generated.h"
UCLASS()
class SPARTAPROJECT_API ASpartaPlayerController : public APlayerController
{
GENERATED_BODY()
};
PlayerController.h
#include "SpartaPlayerController.h"
PlayerController.cpp
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameMode.h"
#include "SpartaGameMode.generated.h"
UCLASS()
class SPARTAPROJECT_API ASpartaGameMode : public AGameMode
{
GENERATED_BODY()
public:
ASpartaGameMode();
};
GameMode.h
#include "SpartaGameMode.h"
#include "SpartaCharacter.h"
#include "SpartaPlayerController.h" // PlayerController 클래스를 사용
ASpartaGameMode::ASpartaGameMode()
{
DefaultPawnClass = ASpartaCharacter::StaticClass();
PlayerControllerClass = ASpartaPlayerController::StaticClass();
}
GameMode.cpp
PlayerControllerClass는 GameMode가 제공하는 속성으로, 게임 시작 시 사용할 PlayerController 타입을 지정한다.ASpartaPlayerController::StaticClass()는 언리얼 엔진이 ASpartaPlayerController 클래스의 정보를 런타임에 참조할 수 있도록 제공하는 정적 함수이다.SpartaPlayerController를 기본 PlayerController로 인식하게 된다.
Project Settings → Input 시스템을 대체하거나 확장하기 위해 Enhanced Input 시스템이 제공된다.IA_Move, 스페이스바 점프를 담당하는 IA_Jump, 마우스 회전을 담당하는 IA_Look 등을 만들 수 있다.
Bool (참/거짓)Axis1D (1차원 축 값)Axis2D (2차원 축 값)Axis3D (3차원 축 값)IA_Move 는 아래와 같이 키를 매핑해준다.

IA_Move)은 W, A, S, D 키를 각각 축 값으로 매핑한다.IA_Jump 는 아래와 같이 키 설정을 지정해줍니다

IA_Look 은 아래와 같이 마우스 설정을 지정해줍니다.

Axis2D로 지정한 X축, Y축 값을 게임 내 좌표계에 맞춰 회전에 반영한다.
기본적으로 마우스 Y축의 움직임은 "위로 움직임 = 양수, 아래로 움직임 = 음수"로 전달된다.
하지만, 카메라의 상하 회전 (Pitch)은 엔진의 좌표계에서 "위로 = 음수, 아래로 = 양수"로 작동하는 경우가 많습니다. 따라서, Y축 값을 Negate Modifier를 통해 반전하여야 한다.
X축 (좌우 회전, Yaw)의 경우, 기본적인 엔진 좌표계와 마우스 움직임의 방향이 일치한다.
IA_Sprint 는 아래와 같이 키 설정을 지정해준다.

#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "SpartaPlayerController.generated.h"
class UInputMappingContext; // IMC 관련 전방 선언
class UInputAction; // IA 관련 전방 선언
UCLASS()
class SPARTAPROJECT_API ASpartaPlayerController : public APlayerController
{
GENERATED_BODY()
public:
ASpartaPlayerController();
// 에디터에서 세팅할 IMC
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Input")
UInputMappingContext* InputMappingContext;
// IA_Move를 지정할 변수
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Input")
UInputAction* MoveAction;
// IA_Jump를 지정할 변수
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Input")
UInputAction* JumpAction;
// IA_Look를 지정할 변수
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Input")
UInputAction* LookAction;
// IA_Sprint를 지정할 변수
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
UInputAction* SprintAction;
};
PlayerController.h
#include "SpartaPlayerController.h"
ASpartaPlayerController::ASpartaPlayerController()
: InputMappingContext(nullptr),
MoveAction(nullptr),
JumpAction(nullptr),
LookAction(nullptr),
SprintAction(nullptr)
{
}
PlayerController.cpp
UPROPERTY() 이렇게 선언해두면, 언리얼 에디터나 Blueprint에서 해당 멤버 변수에 .uasset 파일 (우리가 만든 IMC, IA 등)을 할당해줄 수 있다.

Local Player Subsystem을 통해 Input Mapping Context를 활성화하거나 비활성화한다.#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "SpartaPlayerController.generated.h"
class UInputMappingContext;
class UInputAction;
UCLASS()
class SPARTAPROJECT_API ASpartaPlayerController : public APlayerController
{
GENERATED_BODY()
public:
ASpartaPlayerController();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
UInputMappingContext* InputMappingContext;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
UInputAction* MoveAction;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
UInputAction* JumpAction;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
UInputAction* LookAction;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input")
UInputAction* SprintAction;
virtual void BeginPlay() override;
};
PlayerController.h
#include "SpartaPlayerController.h"
#include "EnhancedInputSubsystems.h"
ASpartaPlayerController::ASpartaPlayerController()
: InputMappingContext(nullptr),
MoveAction(nullptr),
JumpAction(nullptr),
LookAction(nullptr),
SprintAction(nullptr)
{
}
void ASpartaPlayerController::BeginPlay()
{
Super::BeginPlay();
//LocalPlayer는 그 플레이어의 입력이나 화면뷰를 관리하는 객체이다. -> 입력을 관리하는 객체이다.(플레이어마다 붙어있음)
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
{
// Local Player에서 EnhancedInputLocalPlayerSubsystem을 획득
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
{
if (InputMappingContext)
{
// Subsystem을 통해 우리가 할당한 IMC를 활성화
// 우선순위(Priority)는 0이 가장 높은 우선순위
Subsystem->AddMappingContext(InputMappingContext, 0);
}
}
}
}
PlayerController.cpp
GetLocalPlayer()GetSubsystem<UEnhancedInputLocalPlayerSubsystem>()AddMappingContext나 RemoveMappingContext 등을 호출하여 입력 매핑을 동적으로 제어할 수 있다.AddMappingContext()SpartaInputMappingContext: 활성화할 IMC.0: 우선순위. 낮을수록 높은 우선순위를 가진다.BP_PlayerController Blueprint를 열어 이벤트 그래프창에서
w, a, s, d 키를 누르거나 space를 누르거나 shift키를 누르면 각각에 맞는 이벤트가 발생함을 알 수 있다.