Third-person camera and movement

Course day 8 (camera setup) · AWarriorHeroCharacter constructor, Input_Move, Input_Look · 8 min

In one breath

Three rotations are in play: the controller's (where you're looking), the camera boom's (follows the controller) and the character's (turns toward where you're walking). Your settings keep the character out of the controller's rotation, so the camera orbits freely while he turns to face his movement direction.

The components

CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(GetRootComponent());
CameraBoom->TargetArmLength = 200.0f;
CameraBoom->SocketOffset = FVector(0.0f, 55.0f, 65.0f);
CameraBoom->bUsePawnControlRotation = true;

FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
FollowCamera->bUsePawnControlRotation = false;

Who turns the character?

bUseControllerRotationYaw = false;                       // don't snap to the camera
GetCharacterMovement()->bOrientRotationToMovement = true; // turn toward movement
GetCharacterMovement()->RotationRate = FRotator(0.f, 500.f, 0.f); // 500°/s yaw
SettingFeels like
Yaw from controller off, orient to movement onFree camera; he runs toward what you press. Exploring. (What you have.)
Yaw from controller onHe always faces where the camera looks and strafes. Aiming / locked on.

Kratos switches between these: free while exploring, facing the target when you lock on or aim the axe. Expect a lesson that flips these flags (or uses bUseControllerDesiredRotation) at runtime.

Input_Move, line by line

const FVector2D MovementVector = InputActionValue.Get<FVector2D>();
const FRotator MovementRotation(0.f, Controller->GetControlRotation().Yaw, 0.f);

if (MovementVector.Y != 0.f) {
    const FVector ForwardDirection = MovementRotation.RotateVector(FVector::ForwardVector);
    AddMovementInput(ForwardDirection, MovementVector.Y);
}
if (MovementVector.X != 0.f) {
    const FVector RightDirection = MovementRotation.RotateVector(FVector::RightVector);
    AddMovementInput(RightDirection, MovementVector.X);
}
  1. Get<FVector2D>(): the stick/WASD value. Y is forward/back, X is right/left. That only works because the action's value type is Vector2D.
  2. Keep only the yaw. If you used the full control rotation, looking down would push "forward" into the floor and he'd move slower. Zeroing pitch and roll gives a flat direction.
  3. RotateVector(ForwardVector): world forward (X) turned to match the camera's heading. That's "forward relative to the camera", the standard third-person feel.
  4. AddMovementInput(dir, scale): this doesn't move anything itself. It adds to a request the Character Movement Component uses on its tick, together with speed, acceleration, friction and BrakingDecelerationWalking.

Input_Look is simpler: AddControllerYawInput / AddControllerPitchInput rotate the controller. The boom follows because of bUsePawnControlRotation. If looking up and down feels inverted, the fix is a Negate modifier on the mapping, not code.

Quiz yourself

Why build MovementRotation from only the yaw?

With pitch included, looking down tilts "forward" into the ground, so movement slows down or goes wrong. Yaw-only gives a flat heading.

What does bOrientRotationToMovement = true plus bUseControllerRotationYaw = false feel like in game?

The camera orbits freely, and the character turns (at RotationRate) to face the direction he's moving.

What does SocketOffset = (0, 55, 65) achieve?

It moves the camera right and up from the end of the arm: an over-the-shoulder framing.

SetupAttachment vs AttachToComponent?

SetupAttachment is for the constructor, before the component is registered. AttachToComponent is for runtime (e.g. attaching a spawned weapon to a hand socket).

Does AddMovementInput move the character straight away?

No. It accumulates an input vector that the Character Movement Component consumes on its tick, applying acceleration, max speed and friction.

A wall comes between the character and the camera. What stops the camera from clipping through it?

The spring arm's collision test (bDoCollisionTest, on by default). It sweeps from the character to the camera and shortens the arm to the hit point.

Which component actually swings around when you move the mouse: the boom, the camera, or the character?

Mouse input rotates the controller. The boom follows it (bUsePawnControlRotation = true), and the camera rides on the end of the boom. The character doesn't turn, because controller yaw is off.