Why don't we just call GetActorForwardVector()?

In this tutorial, the author calculated the Direction as follows:

void APlayerCharacter::MoveForward(float AxisValue)


    if ((Controller != nullptr) && (AxisValue != 0.0f))


        // Find out which way is forward

        const FRotator Rotation = Controller->GetControlRotation();

        const FRotator YawRotation(0, Rotation.Yaw, 0);

        // Get forward vector

        const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

        AddMovementInput(Direction, AxisValue);



Why don’t we just call GetActorForwardVector()?

void APlayerCharacter::MoveForward(float AxisValue)


    if ((Controller != nullptr) && (AxisValue != 0.0f))


       const FVector Direction = GetActorForwardVector();

        AddMovementInput(Direction, AxisValue);



By the way, I have checked their numerical values are not exactly identical.

I don’t know.
It could be for people that are new to Unreal but not new to game development. Not every engine has an equivalent of GetActorForwardVector()
By showing them the lower-level approach, those developers may have a better understanding of what’s going on.

May have been better if they listed the GetActorForwardVector solution just below it.

In the tutorial they are getting the forward direction from the controllers rotation ( XY plane specifically ), that is not the same as the actors forward vector ( XYZ normalized ). The actor can be looking one way and the controller another independently with player input.

Thank you. I am still confused in deciding which one I should choose to get Direction.

By the way, another tutorial here uses GetActorForwardVector() as follows:

void ACollidingPawn::MoveForward(float AxisValue)
    if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
        OurMovementComponent->AddInputVector(GetActorForwardVector() * AxisValue);

Because in this case they are constantly updating the RootComponent of the pawn so they should be the same. RootComponent transforms = Actor transforms.

// Create an instance of our movement component, and tell it to update the root.
OurMovementComponent = CreateDefaultSubobject<UCollidingPawnMovementComponent>(TEXT("CustomMovementComponent"));
OurMovementComponent->UpdatedComponent = RootComponent;

Sorry. I am still confused.

In the first tutorial, the author calculates the direction from the transform of APlayerController via GetControlRotation() and matrix rotation while in the second tutorial, the author calculates the direction from the transform of ACharacter via GetActorForwardVector().

When APlayerController possesses ACharacter, are their transforms identical? If not, how are their transforms related?

They are not. Characters are a “physical” representation of the player in the world whilst the controller is the wil of the player over that character. A quick example is the third person template: camera is set to rotate same as controller, but the character is independent allowing you to move the camera freely without rotating the character.

PlayerController can posses pawns. ACharacter are Pawns that have a mesh, collision, and built-in movement logic.

ACharacteris a subclass of the Pawn class, thus can be possessed.
Screen Shot 2022-01-26 at 4.23.30 PM

Now on how do they relate:

Pawn A Pawn is an Actor that can be an “agent” within the world. Pawns can be possessed by a Controller, they are set up to easily accept input, and they can do various and sundry other player-like things. Note that a Pawn is not assumed to be humanoid.
Controller Controller is an Actor that is responsible for directing a Pawn. They typically come in 2 flavors, AIController and PlayerController. A controller can “possess” a Pawn to take control of it.
PlayerController A PlayerController is the interface between the Pawn and the human player controlling it. The PlayerController essentially represents the human player’s will.

The controllers can move the pawn through the Movement Component: The character movement component is an Actor Component that provides an encapsulated movement system with common modes of movement for humanoid characters , including walking, falling, swimming, and flying..

Hope it makes sense and I didn’t mess it up further. :sweat_smile:

1 Like

I don’t still quite understand. Lets me rewind to the main part. Here is the code in question.

void AMyPlayerController::SetupInputComponent()

    // Move Forward
    FName Name = TEXT("MoveForward");
    UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping(Name, EKeys::W));
    UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping(Name, EKeys::S, -1.f));
    FInputAxisBinding MoveForward(Name);
        [this](float Value)
            if (Value)
                const FVector DirA = FRotationMatrix(FRotator(0, GetControlRotation().Yaw, 0)).GetUnitAxis(EAxis::X);
                const FVector DirB = GetCharacter()->GetActorForwardVector();
                GetCharacter()->AddMovementInput(DirA, Value);
                // GetCharacter()->AddMovementInput(DirB, Value);

In the first tutorial I found the author chose DirA but in another tutorial I found another author (maybe different person) chose DirB. For me it is confusing because DirA is not exactly identical to DirB (I have compared their numerical values which are not identical). Are both approaches correct? So in the future, which approach should I use?


Depends on your project.

You can test both yourself. I suggest you do so with a character that does not have its rotation fixed with the camera.

1 Like

I just found that both DirA and DirB are numerically identical only if ACharacterMovementComponent::bOrientRotationToMovement = false.

1 Like

It seems to me the following two functions produce the same output.

FRotationMatrix(FRotator(0, GetControlRotation().Yaw, 0)).GetUnitAxis(EAxis::X);

UKismetMathLibrary::GetForwardVector(FRotator(0, GetControlRotation().Yaw, 0));

This is one of those questions where you need in the tutorial to show the different camera settings and rotations vs what the player allows, and see the difference between the RotationMatrix and the GetForwardVector() piece.

I know the tutorial you are using, it made me have the same question.