Search Unity

Cinemachine First or Third person camera for spherical movement

Discussion in 'Cinemachine' started by Mathalous, Jun 26, 2022.

  1. Mathalous

    Mathalous

    Joined:
    Jul 5, 2018
    Posts:
    4
    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.
     
  2. gaborkb

    gaborkb

    Unity Technologies

    Joined:
    Nov 7, 2019
    Posts:
    856
    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.
     
  3. Mathalous

    Mathalous

    Joined:
    Jul 5, 2018
    Posts:
    4
    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.
     
  4. Mathalous

    Mathalous

    Joined:
    Jul 5, 2018
    Posts:
    4
    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.
    Code (CSharp):
    1. var delta = inputManager.Player.Move.ReadValue<Vector2>();
    2.     Vector3 input = new Vector3(delta.x, 0, delta.y);
    3.     if (input.magnitude > 0) {
    4.       if(moveCameraDir)
    5.         input = Camera.main.transform.rotation * input;
    6.  
    7.       if (input.magnitude > 0.001f) {
    8.         transform.position += input * (speed * Time.deltaTime);
    9.       }
    10.     }
    11.     if (rotatePlayer) {
    12.       float t = Cinemachine.Utility.Damper.Damp(1, rotationDamping, Time.deltaTime);
    13.       //Quaternion newRotation = Quaternion.LookRotation(input.normalized, transform.up);
    14.       Quaternion newRotation = Quaternion.LookRotation(Camera.main.transform.forward, transform.up);
    15.       transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, t);
    16.     }
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    To make the POV work properly, try making the vcam a child of the player.
     
    Mathalous likes this.
  6. Mathalous

    Mathalous

    Joined:
    Jul 5, 2018
    Posts:
    4
    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.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. namespace Mathalous {
    4.   public class PositionSync : MonoBehaviour {
    5.     public GameObject other;
    6.     public Vector3 rotationOffset;
    7.     public Vector3 positionOffset;
    8.     [System.Flags]
    9. #if ODIN_INSPECTOR
    10.     [Sirenix.OdinInspector.EnumToggleButtons]
    11. #endif
    12.     public enum UpdateOptions{
    13.       Position = 1,
    14.       Up = 1 << 2,
    15.       Forward = 1 << 3,
    16.     }
    17.     public UpdateOptions updateOptions;
    18.     private void Update() {
    19.       if(updateOptions.HasFlag(UpdateOptions.Position))
    20.         this.transform.position = other.transform.position + positionOffset;
    21.       if (updateOptions.HasFlag(UpdateOptions.Up))
    22.         this.transform.up = other.transform.up;
    23.       if (updateOptions.HasFlag(UpdateOptions.Forward)) {
    24.         transform.rotation = other.transform.rotation * Quaternion.Euler(rotationOffset);
    25.       }
    26.     }
    27.   }
    28. }
    29.  
    30.  
     
    gaborkb and Gregoryl like this.