C++ Help With Top Down Camera Pitch and Yaw Please.

Here is my source file for my character class. I am trying to have your typical MMo Style Camera where you can zoom in and zoom out which works fine but when I go to rotate the spring arm I have issues achieving the desired result.
For testing right now I do not require input to rotate or adjust camera such as hold X button to start input while held this will be later.

Here is an example if i remove the pitch code.

The rotation of the spring arm works but it just feels off idk why.
But when i try to do anything with the pitch to allow me to go up or down and orbit as i want around the player I get undesired results such as this.

I have tried many different ways to try to get this that is why thought to add a scene component to attach the spring arm to so I could adjust them differently. but still same result. I can not seem to achieve the typical MMO style camera such as in runescape or ff14 or wow.
Anyone please point me in the right direction and It will be greatly appreciated. Thank you.

// Initializer
APharosPlayableGameCharacter::APharosPlayableGameCharacter()
{
	CameraAnchor = CreateDefaultSubobject<USceneComponent>(TEXT("CameraAnchor"));
	CameraAnchor->SetupAttachment(RootComponent);
	
	SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
	SpringArm->SetupAttachment(CameraAnchor);
	SpringArm->TargetArmLength = 300.0f;
	SpringArm->bEnableCameraLag = true;
	SpringArm->CameraLagSpeed = 3.0f;
	SpringArm->SetRelativeRotation(FRotator(-90.0f, 0.0f, 0.0f));

	Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
	Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
	
	bIsOrbiting = false;
}


// Being Play
void APharosPlayableGameCharacter::BeginPlay()
{
	Super::BeginPlay();
}

// Input Component
void APharosPlayableGameCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAxis("Zoom", this, &APharosPlayableGameCharacter::ZoomInOut);
	PlayerInputComponent->BindAxis("Look", this, &APharosPlayableGameCharacter::AddCameraYawInput);
	PlayerInputComponent->BindAxis("Look up", this, &APharosPlayableGameCharacter::AddCameraPitchInput);
}

// Zoom In and Out
void APharosPlayableGameCharacter::ZoomInOut(float AxisValue)
{
	SpringArm->TargetArmLength = FMath::Clamp(SpringArm->TargetArmLength + AxisValue * 50.0f, 300.0f, 2500.0f);
}

void APharosPlayableGameCharacter::AddCameraYawInput(float Value)
{
	FRotator CurrentRotation = SpringArm->GetRelativeRotation();
	FRotator NewRotation(CurrentRotation.Pitch, CurrentRotation.Yaw + Value * 10.0f, CurrentRotation.Roll); 
	SpringArm->SetRelativeRotation(NewRotation);
	
	GEngine->AddOnScreenDebugMessage(-1, 0.f, FColor::Green, *NewRotation.ToString());
	
}

void APharosPlayableGameCharacter::AddCameraPitchInput(float Value)

{	FRotator CurrentRotation = CameraAnchor->GetRelativeRotation();
	FRotator DeltaRotation(0.0f, 0.0f, Value * 10.0f);
	CameraAnchor->AddRelativeRotation(DeltaRotation);

	GEngine->AddOnScreenDebugMessage(-1, 0.f, FColor::Green, *DeltaRotation.ToString());
}
AddCameraPitchInput > AddRelativeRotation

add is going to make it loop upside down and back into eternity, you should use SetRelativeRotation clamped to a range of a minimum and maximum angle.

  • Edit
    Also to make the value framerate independent you must multiply the rotation value by world tick seconds, which you can retrieve from the UGameplayStatics library
1 Like

I feel dumb because I tried this earlier but must have messed it up so it did not work.

void APharosPlayableGameCharacter::AddCameraPitchInput(float Value)
	{
		FRotator newRotation = SpringArm->GetRelativeRotation();
		newRotation.Pitch = FMath::Clamp(newRotation.Pitch + Value * 10.0f, -88.0f, 0.0f);
		SpringArm->SetRelativeRotation(newRotation);
	}```
Thank you for quick response.
1 Like