중요 포인트
- Pawn, Controller의 Rotation값 이해
- SpringArm과 Camera의 UsePawnControlRotation 이해
- Pawn.UseControllerRotationPitch, Yaw, Roll
Pawn, Controller의 Rotation값 이해
Pawn(Character)과 Controller는 각각 고유한 Rotate값을 가진다
이 두 객체의 회전은 만들고자 하는 게임(조작 방식)에 따라 적절하게 설정되어야 한다.
3인칭 기준으로 단순하게 나눠보자면
- TPS
- 캐릭터는 기본적으로 항상 카메라가 보는 방향을 바라봄
- 캐릭터가 이동하더라도 바라보는 방향은 항상카메라 정면
- 액션게임
- 카메라의 회전과 캐릭터의 움직임, 바라보는 방향은 독립적
- 캐릭터는 이동하려는 방향을 바라보고 회전및 이동한다
- 카메라는 마우스 움직임을 따라간다
핵심 차이점은 캐릭터가 행동 방향을 바라보느냐, 카메라방향(플레이어의 화면방향)을 바라보느냐가 되겟다.
이를 코드내에서 구현하려면 캐릭터의 Pawn의 회전 구현을 캐릭터의 움직임 부분에서 구현할지,
카메라 움직임에서 구현할지로 구분해볼 수 있겟다
SpringArm과 Camera의 UsePawnControlRotation 이해

SpringArm과 Camera는 bUsePawnControlRotation값을 가지는데,
해당값이 true이면 각 컴포넌트는 Controller의 회전값을 따라서 사용하게 된다.
즉 Controller의 회전값을 변경하는것으로 카메라가 회전하는 효과를 낼 수 있는것.
-> 앞으로 카메라를 움직이고싶다면 컨트롤러를 움직이는것으로 대충 이해해도 무방할듯하다,
실제로 공식 문서에서는 Pawn이 바라보는/조준중인 방향으로 설명된다!
SpringArm은 bInheritPitch, Yaw, Roll값이 추가로 존재해 어떤 값을 사용할지 결정할 수 있다.
일반적으로는 SpringArm의 bUseControllRotation을 True로, InheritPitch와 InheritYaw를 사용한다
*참고, Yaw는 Z축 : 좌우회전, Pitch는 Y축 : 상하 회전. Roll은 X축 : 중심기준 회전!! 챠량 등의 일부에만 사용
Pawn.UseControllerRotationPitch, Yaw, Roll

Pawn은 UseControllerRotationPitch, Yaw, Roll 세개의 bool값을 가지고 있다.
해당값은 위의 UsePawnControlRotation처럼 컨트롤러의 회전값을 Pawn에 적용을 할 것인지 여부를 의미한다.
코드 구현
MyPawn의 컴포넌트 구조는 다음과 같음

생성자 내용 참고(기본값 설정 및 컴포넌트 부착)
AMyPawn::AMyPawn()
{
PrimaryActorTick.bCanEverTick = true;
MoveSpeed = 600.f;
YawSpeed = 1.f;
PitchSpeed = 1.f;
RootComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("RootCapsuleComponent"));
SetRootComponent(RootComp);
RootComp->SetCapsuleHalfHeight(90);
RootComp->SetCapsuleRadius(25);
SkeletalMeshComp = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("SkeletalMeshComp"));
SkeletalMeshComp->SetupAttachment(RootComp);
//에셋 가져오는방법 암기할것.
//ConstructorHelpers::FObjectFinder<UType>
static ConstructorHelpers::FObjectFinder<USkeletalMesh> MeshAsset(TEXT("/Game/Resources/Characters/Meshes/SKM_Quinn.SKM_Quinn"));
if (MeshAsset.Succeeded()) {
SkeletalMeshComp->SetSkeletalMesh(MeshAsset.Object);
SkeletalMeshComp->SetWorldRotation(FRotator(0, -90, 0));
SkeletalMeshComp->SetRelativeLocation(FVector(0, 0, -90));
SkeletalMeshComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp"));
SpringArmComp->SetupAttachment(RootComp);
SpringArmComp->TargetArmLength = 400.f;
SpringArmComp->bUsePawnControlRotation = true;
SpringArmComp->bInheritYaw = true;
SpringArmComp->bInheritPitch = true;
SpringArmComp->bDoCollisionTest = true;
SpringArmComp->SetRelativeLocation(FVector(0, 0, 60));
CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComp"));
CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
CameraComp->bUsePawnControlRotation = false;
bUseControllerRotationYaw = false;
bUseControllerRotationPitch = false;
bUseControllerRotationRoll = false;
}
SpringArm에 이전에 언급했던 bool값들을 설정해둔것이 눈에띄는정도.
의외에는 컴포넌트 초기값 설정 등.
마우스 인풋 -> 카메라 움직임 구현
InputAction은 Vector2d값, InputMappingContext에서는 Mouse XY 2D-Axis를 사용함,
void AMyPawn::Look(const FInputActionValue& value)
{
const FVector2D LookValue = value.Get<FVector2D>();
if (!Controller || LookValue.IsNearlyZero())
return;
//컨트롤러의 Rotation은 플레이어가 바라보고 있는 방향
FRotator ControlRot = Controller->GetControlRotation();
//마우스 이동값을 더함
ControlRot.Yaw += LookValue.X * YawSpeed;
ControlRot.Pitch += LookValue.Y * PitchSpeed;
// 상하 회전각도의 제한을 두려면 ClampAngle을 이용하여 제한한다.(값, 최소, 최대)
ControlRot.Pitch = FMath::ClampAngle(
ControlRot.Pitch + LookValue.Y * PitchSpeed,
-80.f,
80.f
);
//컨트롤러의 회전 = 스프링암 회전
Controller->SetControlRotation(ControlRot);
//컨트롤러와 동일한 회전값을 Pawn에게 Set
//카메라 보는방향과 캐릭터 보는 방향이 같아짐.
//슈터게임에 어울리는 방식
//SetActorRotation(FRotator(0.f, ControlRot.Yaw, 0.f));
}
코드의 과정 설명
Enhanced Input을 통해 2dvector값을 받아온다(X,Y값 존재)
값이 정상인지 먼저 체크하고 0또는 준하는 값이면 취소.
Controller의 현재 회전값을 받아 저장하고,
Vector2D값을 현재 회전값의 Yaw, Pitch값에 각각 더한다.
Pitch가 부자연스럽지 않게 ClampAngle을 통해 최소 최대값을 -80,80으로 제한하고
변경된 값으로 컨트롤러의 회전값을 변경한다.
(혹시라도 -90미만 90이상이 넘어가면 카메라가 뒤집히는 등 불편을 초래할 수 있다.)
필요하다면, 현재 회전값의Yaw값을 Pawn에 적용시킨다(SetActorRotation)
여담) 앞서 언급한 Pawn의 bUseControllerRotationYaw 속성을 true로 설정하면 pawn의 회전도 Controller에게 맡길수 있다.
다만 굳이 C++을 사용하는것이 확장성과 성능인만큼 엔진에게 맡기는것보다 직접 제어하는것이 더 유리
키보드 인풋->캐릭터 이동과 회전 제어
void AMyPawn::Move(const FInputActionValue& value) {
//Move는 값만 받아오고 저장함. 이동은 Tick에서.
MoveInput = value.Get<FVector2D>();
}
void AMyPawn::Tick(float DeltaTime)
{
//값은 move에서 받고 실행은 Tick에서.
Super::Tick(DeltaTime);
//미입력 또는 0입력 시 return;
if (!Controller || MoveInput.IsNearlyZero())
return;
//현재 컨트롤러(카메라)가 보는 방향중 Yaw값을 가져옴
const FRotator ControlRot = Controller->GetControlRotation();
const FRotator YawOnlyRot(0.f, ControlRot.Yaw, 0.f);
//바라보는 방향을 기준으로 방향 단위벡터를 가져오는함수라고함, 각각 정면, 우측기준,
const FVector Forward = FRotationMatrix(YawOnlyRot).GetUnitAxis(EAxis::X);
const FVector Right = FRotationMatrix(YawOnlyRot).GetUnitAxis(EAxis::Y);
//단위 벡터에 입력값을 곱함(-1,0,1)
FVector MoveDirection =
Forward * MoveInput.X +
Right * MoveInput.Y;
//안전장치, 0을 방지함.
if (MoveDirection.IsNearlyZero())
return;
//이미 위의 GetUnitAxis 로 단위벡터를 얻었지만, 안전장치 한번더
MoveDirection = MoveDirection.GetSafeNormal();
////방향 벡터의 Yaw값으로 Pawn이 회전하도록 함, 액션게임에 어울리는방식?
//const FRotator TargetRotation = MoveDirection.Rotation();
//SetActorRotation(FRotator(0.f, TargetRotation.Yaw, 0.f));
//방향*시간*속도를 곱해 실제 이번 프레임에 움직일 량을 계산하고, 현재 위치에 더함
const FVector DeltaMove = MoveDirection * MoveSpeed * DeltaTime;
const FVector NewLocation = GetActorLocation() + DeltaMove;
//Pawn이 실제로 움직이는 부분.
FHitResult Hit;
SetActorLocation(NewLocation, false, &Hit);
}
코드 과정 설명
Move함수는 WASD 키입력으로부터 향상된 입력시스템을 통해 이벤트가 발생하고,
트리거 이벤트 Triggered와 Completed에 바인딩해두었다.
Completed 트리거에 발생을 추가해야 마지막에 (0,0)값이 저장되어 이동을 멈출 수 있다.
발생한 값은 MoveInput변수에 저장된다.
이동속도의 프레임 독립성(일정한 이동속도)구현을 위해 실제 이동은 Tick에서 구현한다
이동방향은 카메라=플레이어의 시선을 기준으로 하기 때문에 Controller로부터 방향을 가져온다.
그리고 Rotator의 Yaw값만을 남긴다 (*참고, FRotator 생성자는 Pitch, Yaw, Roll순서임)
FRotationMatrix(FRotator).GetUnitAxis(EAxis::Type) 함수를 이용하여
주어진 FRotator로부터 방향 단위벡터를 쉽게 구할 수 있다.
이를 통해 Character때는 GetForward~~ GetRight~~를 사용했던걸 대체할 수 있다.
방향벡터에 입력값(-1, 0, 1 중의 하나의 값)을 방향에 곱해주고
마지막으로 방향벡터에 속도와 시간을 곱한 값을 적용시켜 실제로 이동하도록 한다.
중간에 주석을 친 문항 두줄
const FRotator TargetRotation = MoveDirection.Rotation();
SetActorRotation(FRotator(0.f, TargetRotation.Yaw, 0.f));
이 부분은 캐릭터를 화면 방향에 고정시키지 않고, 이동방향을 바라보도록 할때 사용하는 부분이다.
이동방향의 Yaw값만을 가져와 Pawn의 회전에 사용하는것으로 이동방향을 바라보게 하였다.
더 발전시킨다면 회전값에 RInterp 보간처리를 적용해 부드럽게 적용해 볼 수 있겟다.
아래 Gif는 SetActorRotation()함수를 이동시에, 카메라 회전시에 각각 따로 적용해본 예시.
티스토리 GIF가 날아가서 안올라간다 방법을 찾는중...
외워두면 좋을것같은 방향, 회전 관련 함수
FRotationMatrix(FRotator).GetUnitAxis(EAxis::Type)
주어진 FRotator에 대해 방향 단위벡터를 가벼올 수 있는 함수.
Controller->SetControlRotation( FRotator);
캐릭터 컨트롤러의 회전 제어, 일반적으로 카메라의 회전을 할 때 사용
SetActorLocation(), SetActorRotation()
Pawn(캐릭터)의 회전, 이동을 제어할 때 사용
참고 문서
https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/Engine/AController
AController | Unreal Engine 5.7 Documentation | Epic Developer Community
Controllers are non-physical actors that can possess a Pawn to control its actions.
dev.epicgames.com
'개발 > 언리얼' 카테고리의 다른 글
| SpawnActor로 생성된 캐릭터가 움직이지 않는경우 (0) | 2026.04.29 |
|---|---|
| Collision Response, Linetrace (0) | 2026.04.24 |
| SpawnActor, SetTimer활용해보기 (0) | 2026.04.13 |
| 언리얼 C++ 펜듈럼 움직임 구현하기 (0) | 2026.04.10 |
| 언리얼 빌드 이해하기(UBT, UHT, CDO, GC) (0) | 2026.04.10 |