Cinemachine First or Third person camera for spherical movement

I’m working on a 3d game where the character can be aligned with various gravity directions. One situation is a large sphere. As the character moves around the sphere it is rotated such that down is always towards the center. Additionally, rotating the camera left to right will cause the player to face that direction. While first person is preferred, I can work with third person as well.

My issue is with the up direction of the camera not being synced, even if override world up in the brain is set to the player’s transform. The FreeLook vcam is the closest I can get to working, as it seems to rotate with the character’s up direction, but it doesn’t play well with the left and right aiming.

Have a look at our sample scene called “SphericalSurfaceFollow”. This has a player moving on a sphere with two different camera setups. One is a transposer and composer (CM vcam1) and the other is a freelook (CM FreeLook1) in Cinemachine version 2.8.6.

You can also create a new vcam, assign your player to the Follow field and add ThirdPersonFollow to the body component. This will create a ThirdPerson camera for you. You can modify this camera to be a first person by changing Shoulder Offset, Vertical Arm Length and Camera Distance (to 0 for example).

To get our sample scenes, go to the package manager, click on Cinemachine, and on the right side you’ll see Samples and a download button.

Thanks for the help, I think my issue was using target lock on the freelook camera and coupling the rotation with both the movement and the camera direction.

Alright, so I modified the SphericalSurfaceFollow’s player script to always look towards the camera position and move relative to the camera direction. I then made a new virtual camera with a third person follow body with the player as the follow and lookat target. I chose FOV for the aim type, as I want the player to control the look direction. Everything works well until the player moves to the opposite side of the sphere. At that point the camera does not rotate properly to reflect the new up direction.

var delta = inputManager.Player.Move.ReadValue<Vector2>();
    Vector3 input = new Vector3(delta.x, 0, delta.y);
    if (input.magnitude > 0) {
      if(moveCameraDir)
        input = Camera.main.transform.rotation * input;

      if (input.magnitude > 0.001f) {
        transform.position += input * (speed * Time.deltaTime);
      }
    }
    if (rotatePlayer) {
      float t = Cinemachine.Utility.Damper.Damp(1, rotationDamping, Time.deltaTime);
      //Quaternion newRotation = Quaternion.LookRotation(input.normalized, transform.up);
      Quaternion newRotation = Quaternion.LookRotation(Camera.main.transform.forward, transform.up);
      transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, t);
    }

To make the POV work properly, try making the vcam a child of the player.

1 Like

Thanks for the help. Parenting the vcam to the child led to other issues, namely rotating the player about its y axis would also rotate the camera. To get around this I made an empty with a script to sync itself to the player depending on how I want the camera to function. Leaving it below for anyone with similar problems.

using UnityEngine;
namespace Mathalous {
  public class PositionSync : MonoBehaviour {
    public GameObject other;
    public Vector3 rotationOffset;
    public Vector3 positionOffset;
    [System.Flags]
#if ODIN_INSPECTOR 
    [Sirenix.OdinInspector.EnumToggleButtons]
#endif
    public enum UpdateOptions{
      Position = 1,
      Up = 1 << 2,
      Forward = 1 << 3,
    }
    public UpdateOptions updateOptions;
    private void Update() {
      if(updateOptions.HasFlag(UpdateOptions.Position))
        this.transform.position = other.transform.position + positionOffset;
      if (updateOptions.HasFlag(UpdateOptions.Up))
        this.transform.up = other.transform.up;
      if (updateOptions.HasFlag(UpdateOptions.Forward)) {
        transform.rotation = other.transform.rotation * Quaternion.Euler(rotationOffset);
      }
    }
  }
}
2 Likes