Rotate the Camera around the Player

Hi everyone, I’m trying to make the Camera Rotate around the player by using the angle between the Spring Arm and the Target which in this case is the player, for that I’m using this code:

FRotator lookAtRot = FRotator(mainCameraSpring->RelativeRotation.Pitch ,UKismetMathLibrary::FindLookAtRotation(mainCameraSpring->RelativeLocation, mainPlayer->GetActorLocation()).Yaw, mainCameraSpring->RelativeRotation.Roll);
			mainCameraSpring->SetRelativeRotation(lookAtRot);

Basically I only Want to move the camera around the player just like the blue arrow that I painted, for that I’m using the code in top to calculate the rotation factor.

I’m not sure what I’m missing to do this right because what happens is that the Camera moves around the X axis (the red axis).

Any idea how to solve this?

thanks.

Camera Movement Code:

void ACameraManager::CameraMovement(TEnumAsByte<TouchGestures> gesture)
{
	if ((gesture & TouchGestures::Pinch) == TouchGestures::Pinch)
	{
		zoomLevel = FMath::Clamp(zoomLevel - 5 * CameraSpeed, minZoomLevel, maxZoomLevel);
	}

	if ((gesture & TouchGestures::SwipeLeftRight) == TouchGestures::SwipeLeftRight)
	{
		zoomLevel = FMath::Clamp(zoomLevel + 5 * CameraSpeed, minZoomLevel, maxZoomLevel);
	}

	if ((gesture & TouchGestures::SwipeUpDown) == TouchGestures::SwipeUpDown)
	{
		if (mainCameraSpring)
		{
			cameraSpringPosition.Y -= mainCameraSpring->RelativeLocation.RightVector.Y + (5 * CameraSpeed);
		}
		else if (mainCamera)
		{
			cameraSpringPosition.Y -= mainCameraSpring->RelativeLocation.RightVector.Y + (5 * CameraSpeed);
		}
	}

	if ((gesture & TouchGestures::SwipeDownUp) == TouchGestures::SwipeDownUp)
	{
		if (mainCameraSpring)
		{
			cameraSpringPosition.Y += mainCameraSpring->RelativeLocation.RightVector.Y + (5 * CameraSpeed);
		}
		else if (mainCamera)
		{
			cameraSpringPosition.Y += mainCameraSpring->RelativeLocation.RightVector.Y + (5 * CameraSpeed);
		}
	}
}

And Camera Tick:

void ACameraManager::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	FString message = "Spring Arm Rotation: ";
	message.Append("Yaw: ");
	message.AppendInt(mainCameraSpring->RelativeRotation.Yaw);
	message.Append(", Pitch: ");
	message.AppendInt(mainCameraSpring->RelativeRotation.Pitch);
	message.Append(", Roll: ");
	message.AppendInt(mainCameraSpring->RelativeRotation.Roll);
	message.Append(", Spring Arm Length: ");
	message.AppendInt(mainCameraSpring->TargetArmLength);

	GEngine->AddOnScreenDebugMessage(-1, DeltaSeconds, FColor::Red, message);

	if (mainCameraSpring && mainCameraSpring->TargetArmLength != zoomLevel)
	{
		mainCameraSpring->TargetArmLength = FMath::FInterpTo(mainCameraSpring->TargetArmLength, zoomLevel, DeltaSeconds, CameraSpeed);
	}

	if (mainPlayer)
	{
		if (mainCameraSpring && mainCameraSpring->RelativeLocation != cameraSpringPosition)
		{
			mainCameraSpring->SetRelativeLocation(FMath::VInterpTo(mainCameraSpring->RelativeLocation, cameraSpringPosition, DeltaSeconds, CameraSpeed));
			
			FTransform playerTransfrom;

			mainPlayer->GetTransform().GetRelativeTransform(playerTransfrom);

			FRotator lookAtRot = FRotator(mainCameraSpring->RelativeRotation.Pitch, UKismetMathLibrary::FindLookAtRotation(mainCameraSpring->RelativeLocation, playerTransfrom.GetLocation()).Yaw, 0);
			mainCameraSpring->SetRelativeRotation(lookAtRot);
		}
		else if (mainCamera && mainCamera->RelativeLocation != cameraPosition)
		{
			mainCamera->SetRelativeLocation(FMath::VInterpTo(mainCamera->RelativeLocation, cameraPosition, DeltaSeconds, CameraSpeed));
		}
	}    	
}

If you rotate Yaw and you see a rotation in a different axis, then its parent or its parent’s parent must be rotated 90 degrees in X or Y. Or if the spring is attached to a socket, then that socket is oriented with Z (blue arrow) not pointing up.

I check the Z axis of the spring arm an it’s pointing up so I think that is correct at leas, do you have any other Idea of what might be causing this behavior, Here is the code on how I create the spring arm and attach it to the player:

//El brazon en el cual se va a adjuntar la camara
	playerCameraArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("player Camera Arm"));
playerCameraArm ->bUsePawnControlRotation = true;
			playerCameraArm ->SetRelativeLocationAndRotation(FVector(0.0f, 150.0f, 150.0f), FRotator(-45.0f, -90.0f, 0.0f));
			playerCameraArm ->TargetArmLength = zoomLevel;
			playerCameraArm ->bEnableCameraLag = true;
			playerCameraArm ->CameraLagSpeed = 0.5f;
	playerCameraArm ->AttachTo(RootComponent);	

	playerCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Player Camera"));
playerCamera ->AttachTo(playerCameraArm , USpringArmComponent::SocketName);
			playerCamera ->bUsePawnControlRotation = false;

Maybe this part of the code can help understand what the problem is, thank you.

If I understood you correctly, this is what i use for things like this.

void AActor::AddControllerYawInput(float Val)
{
	if (Val != 0.f && Controller && Controller->IsLocalPlayerController())
	{
		APlayerController* const PC = CastChecked<APlayerController>(Controller);

		//CAMERA ROTATION
		FTransform _t = playerCameraArm->GetRelativeTransform();
		FRotator _r = _t.GetRotation().Rotator();
		_r.Yaw += Val * PC->InputYawScale;
		playerCameraArm ->SetRelativeRotation(FRotator(_r.Pitch, _r.Yaw, 0));
	}
}

So I Managed to get the Yaw3 correctly to rotate but it only goes from -90 Yaw to 90 Yaw, so it looks like it flips behind the character instead of going around it, do you have any ideas to what could be causing this?

So I Managed to get the Yaw3 correctly to rotate but it only goes from -90 Yaw to 90 Yaw, so it looks like it flips behind the character instead of going around it, do you have any ideas to what could be causing this?

nope, show some code maybe can be everything.

Hi, I edited the answer to show How I’m managing the camera movement. Thank you.

You can try something like that, the camera spring will rotate around whatever it is attached to (comment out the CameraTick()).

 if ((gesture & TouchGestures::SwipeDownUp) == TouchGestures::SwipeDownUp)
     {
         if (mainCameraSpring)
         {

        	FTransform transform = mainCameraSpring->GetRelativeTransform();
        	FRotator rotation = transform.GetRotation().Rotator();
         	rotation.Yaw += 5 * CameraSpeed;
        	mainCameraSpring->SetRelativeRotation(FRotator(rotator.Pitch, rotator.Yaw, 0));
      
         }
         ...
         ...

Hi, this worked perfectly but I don’t understand it fully, can you explain it a little bit to me?

And another thing I have the Spring in a location that is not exactly the center of the player has shown in this line:

playerCameraArm ->SetRelativeLocationAndRotation(FVector(0.0f, 150.0f, 150.0f), FRotator(-45.0f, -90.0f, 0.0f));

I had to do this because when I center it by putting it in the Relative Location (0, 0, 0) the camera end’s up inside the player mesh, do you have any idea of what could be the cause for this?

Sounds like the camera arm collides with something inside you player blueprint, you can try to set

playerCameraArm ->ProbeChannel = ECC_Visibility;

or check collision Channels of you player Blueprint.

here i leave the roll value to 0 to avoid the camera flip.

    mainCameraSpring->SetRelativeRotation(FRotator(rotator.Pitch, rotator.Yaw, 0));

Hi, So I added the line you said for the probe channel, but I don’t see anything strange on the blueprint, let me post you a Screenshot to see if you can see something.

If you need anything else please tell me to see if we can solve this. thank you.

could reproduce the problem you have. The camera is not Attached to the Camera arm.
solved it this way comment out in the constructor following code:

playerCamera = CreateDefaultSubobject(TEXT("Player Camera"));
playerCamera ->AttachTo(playerCameraArm , USpringArmComponent::SocketName);
playerCamera ->bUsePawnControlRotation = false;

compile the code then uncomment and recompile again it should update the blueprint correctly.

Hi, I managed to get the camera to attach correctly in the Blueprint but when I press play in the PIE it goes completely wrong, I mean the camera seems to be looking at the right angle but it wont go to the right distance so it can see the map and the character.

What I did was that I changed the line of code from:

playerCamera ->AttachTo(playerCameraArm , USpringArmComponent::SocketName);

To:

playerCamera->AttachTo(playerCameraArm, playerCameraArm->SocketName);

I had to do it this way, because when I commented the lines you told me too, It wouldn’t make a camera so there was nothing that would be shown.

Here are some screenshots of whats happening know.

insert the original lines back they are fine. Comment out → build → uncomment → build I do this to update the blueprint and to avoid doing a rebuild.

Hi, I finally got it to work, the issue was caused by the “map” mesh, the camera for some reason is colliding with the mountain and gets contracted into the player. Thank you for all your help.

Glad to hear that. No problem.