Help needed with Movement and 3rd person camera

Hey Everyone,

I’ve been following a guide(Link to unreal docs) and have a few questions,
I’d also like to declare that I followed the tutorial while using a Character class, that said here are my questions:

  1. Not really a question but a problem, my character is going forward, and not in the direction my Camera is facing and I cannot figure out what I did wrong.
  2. While Rotating in the Tick() function, by default the camera was turning left while I dragged the mouse to the right and turning right while moving the mouse to the left
    this was easily resolved by changing the *+= *to -= in the NewYaw.Yaw -= MouseInputData.X; line, the cause of that is still unclear to me.
  3. In the line MoveInputData = MoveInputData.GetSafeNormal() 500.f; *what does GetSafeNormal() do and why doesn’t it work without that line?
  4. Is this basic movement system good enough for future bipedal animations?

Any answer is appreciated and thanks in advance!


// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Protagonist_Character.generated.h"

UCLASS()
class PROJECT_BULWARK_API AProtagonist_Character : public ACharacter
{
    GENERATED_BODY()

public:
    // Sets default values for this character's properties
    AProtagonist_Character();

    UPROPERTY(EditAnywhere)
    UStaticMeshComponent* CharMesh;

    UPROPERTY(EditAnywhere)
        USpringArmComponent* CameraSpringArm;
    UCameraComponent* ThirdPersonCamera;


protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public:    
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    // Called to bind functionality to input
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    //MovementFunctions
    void MovementForward(float amount);
    void MovementRight(float amount);
    //CameraFunctions
    void CameraYaw(float value);
    void CameraPitch(float value);

    FVector2D MouseInputData;
    FVector2D MoveInputData;
};



And the cpp


// Fill out your copyright notice in the Description page of Project Settings.

#include "Protagonist_Character.h"
#include "Components/StaticMeshComponent.h"
#include "Components/InputComponent.h"

// Sets default values
AProtagonist_Character::AProtagonist_Character()
{
     // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    CharMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CharacterMesh"));
    CharMesh->SetupAttachment(RootComponent);

    CameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
    ThirdPersonCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));

    CameraSpringArm->SetupAttachment(RootComponent);
    CameraSpringArm->TargetArmLength = 350.f;
    CameraSpringArm->SetWorldRotation(FRotator(-60.f, 0.f, 0.f));

    ThirdPersonCamera->SetupAttachment(CameraSpringArm, USpringArmComponent::SocketName);

    AutoPossessPlayer = EAutoReceiveInput::Player0;


}

// Called when the game starts or when spawned
void AProtagonist_Character::BeginPlay()
{
    Super::BeginPlay();

}

// Called every frame
void AProtagonist_Character::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    FRotator NewYaw = GetActorRotation();
    NewYaw.Yaw -= MouseInputData.X;


    FRotator NewPitch = CameraSpringArm->GetComponentRotation();
    NewPitch.Pitch = FMath::Clamp(NewPitch.Pitch + MouseInputData.Y, -80.f, 0.f);


    SetActorRotation(NewYaw);
    CameraSpringArm->SetWorldRotation(NewPitch);
    if (!MoveInputData.IsZero())
    {
        MoveInputData = MoveInputData.GetSafeNormal()* 500.f;
        FVector NewLocation = GetActorLocation();
        NewLocation += GetActorForwardVector()*MoveInputData.X*DeltaTime;
        NewLocation += GetActorRightVector()*MoveInputData.Y*DeltaTime;
        SetActorLocation(NewLocation);
    }
}

// Called to bind functionality to input
void AProtagonist_Character::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);
    PlayerInputComponent->BindAxis("MoveForward", this, &AProtagonist_Character::MovementForward);
    PlayerInputComponent->BindAxis("MoveRight", this, &AProtagonist_Character::MovementRight);
    PlayerInputComponent->BindAxis("YawCamera", this, &AProtagonist_Character::CameraYaw);
    PlayerInputComponent->BindAxis("PitchCamera", this, &AProtagonist_Character::CameraPitch);
}

void AProtagonist_Character::MovementForward(float amount)
{
    MoveInputData.X = amount;
}

void AProtagonist_Character::MovementRight(float amount)
{
    MoveInputData.Y = amount;
}

void AProtagonist_Character::CameraYaw(float value)
{
    MouseInputData.X = value;
}

void AProtagonist_Character::CameraPitch(float value)
{
    MouseInputData.Y = value;
}