언리얼에서 캐릭터를 움직이려면 클래스 네댓 개가 함께 관여한다. GameMode가 무엇을 스폰할지 정하고, PlayerController가 그것을 붙잡고, Enhanced Input이 키를 액션으로 바꿔 넘기고, 그 결과가 State Machine을 통해 애니메이션으로 나온다. 이 글에서는 키를 누른 순간부터 애니메이션이 재생되기까지의 경로를 순서대로 따라가며 각 클래스가 어디를 맡는지 이야기하려 한다.
GameMode & 캐릭터 기초 — 무엇이 스폰되는가
GameMode란?
GameMode는 게임의 규칙과 흐름을 관리하는 컨트롤 타워다. 플레이어 수, 승패 조건 같은 것을 여기서 정한다. 클래스는 두 종류가 있는데, AGameMode는 로그인·재시작 같은 기능이 붙은 멀티플레이어 전용이고, 싱글 프로젝트에서는 기본형인 AGameModeBase를 주로 쓴다.
핵심 프로퍼티
1
2
3
| // DefaultPawnClass : 플레이어가 빙의할 Pawn 클래스 지정
// PlayerControllerClass : 입력 처리 담당 컨트롤러 클래스 지정
DefaultPawnClass = ASpartaCharacter::StaticClass();
|
Pawn vs Character
| 항목 | Pawn | Character |
|---|
| 이동 컴포넌트 | 없음 (직접 구현) | UCharacterMovementComponent 내장 |
| 중력 / 점프 | 없음 | 자동 처리 |
| 자유도 | 높음 (비행체·탈것 등) | 낮음 (인간형 캐릭터 최적화) |
컴포넌트 구성
1
2
3
4
| // Root: CapsuleComponent
// SkeletalMeshComponent — SKM_Manny, Yaw -90° 보정
// SpringArmComponent — bUsePawnControlRotation = true
// CameraComponent — bUsePawnControlRotation = false (SpringArm이 대신 회전)
|
PlayerController 역할
GameMode가 어떤 Pawn과 Controller를 쓸지 정했다면, 이제 입력이 Pawn까지 도달하는 경로를 만들 차례다. PlayerController는 입력 이벤트를 받아 Pawn에 전달하는 중간 레이어다. ASpartaPlayerController를 만들고 GameMode의 PlayerControllerClass에 등록했다.
| 에셋 | 역할 | 예시 |
|---|
| Input Action (IA) | 단일 입력 정의 | IA_Move (Axis2D), IA_Jump (Bool) |
| Input Mapping Context (IMC) | IA ↔ 키 바인딩 묶음 | IMC_Character |
WASD 매핑 — Modifier 조합
1
2
3
4
5
| W → X+ (기본값)
S → X+ + Negate (X 반전)
A → Y+ + Swizzle + Negate (Y축으로 이동 후 반전)
D → Y+ + Swizzle (Y축으로 이동)
마우스 Y → Negate (위 = 카메라 위)
|
IMC 활성화 (BeginPlay)
1
2
3
4
5
6
| if (auto* PC = Cast<ASpartaPlayerController>(GetController()))
{
if (auto* Sub = PC->GetLocalPlayer()
->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
Sub->AddMappingContext(InputMappingContext, 0);
}
|
입력 바인딩 & 이동 함수 — 액션을 이동으로
1
2
3
4
5
6
7
8
9
| if (auto* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent))
{
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ASpartaCharacter::Move);
EIC->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ASpartaCharacter::StartJump);
EIC->BindAction(JumpAction, ETriggerEvent::Completed, this, &ASpartaCharacter::StopJump);
EIC->BindAction(LookAction, ETriggerEvent::Triggered, this, &ASpartaCharacter::Look);
EIC->BindAction(SprintAction, ETriggerEvent::Triggered, this, &ASpartaCharacter::StartSprint);
EIC->BindAction(SprintAction, ETriggerEvent::Completed, this, &ASpartaCharacter::StopSprint);
}
|
함수 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // Move
void Move(const FInputActionValue& Value)
{
FVector2D V = Value.Get<FVector2D>();
AddMovementInput(GetActorForwardVector(), V.X);
AddMovementInput(GetActorRightVector(), V.Y);
}
// Look
void Look(const FInputActionValue& Value)
{
FVector2D V = Value.Get<FVector2D>();
AddControllerYawInput(V.X);
AddControllerPitchInput(V.Y);
}
// Sprint
void StartSprint() { GetCharacterMovement()->MaxWalkSpeed = SprintSpeed; } // 900
void StopSprint() { GetCharacterMovement()->MaxWalkSpeed = NormalSpeed; } // 600
|
애니메이션 State Machine — 이동을 동작으로
Animation Blueprint State Machine 개요
이동까지 붙였으니 마지막은 애니메이션이다. 캐릭터 동작(Idle / Walk / Run / Jump / Fall)을 상태(State) 와 전환 조건(Transition) 으로 설계한다.
주요 변수
1
2
3
| // AnimBP에서 매 프레임 업데이트
float Speed; // GetVelocity().Size2D()
bool bIsInAir; // GetMovementComponent()->IsFalling()
|
상태 전환 흐름
1
2
3
4
5
| Idle ──(Speed > 0)──► Walk ──(Speed > 600)──► Run
▲ │
└──────────────(Speed == 0)────────────────────┘
Idle/Walk/Run ──(bIsInAir)──► Jump ──(!bIsInAir)──► Idle
|
적용 포인트
- AnimBP의
NativeUpdateAnimation에서 Pawn 레퍼런스 캐스팅 → 변수 갱신 - Blend Space 사용 시 Speed 축으로 Idle~Walk~Run 부드럽게 보간
핵심 요약 — GameMode → PlayerController → Enhanced Input(IA/IMC) → 이동 함수 → AnimBP State Machine 으로 이어지는 캐릭터 입력 파이프라인 전체를 한 번에 훑었다. WASD 이동이 키 4개가 아니라 IA_Move(Axis2D) 하나에 Negate·Swizzle Modifier 를 조합해 처리된다는 점이 이 챕터의 핵심 구조였다.