How can I gradually rotate my camera vertically on mouse press/hold?

I’m learning cinemachine and I made a simple script for first-person. I have my virtual camera separate from the player object, with Body set to 3rd Person Follow, Aim to Do Nothing, Look At is None (Transform) and in the Follow I have my “Camera” empty game object. That empty camera game object is a child of my player object and so it’s used for the camera movement and rotation.

What I’m trying to do is rotate my player camera vertically only slightly, but smoothly and gradually whenever I either hold or press left mouse button. So holding the key or pressing it repeatedly would continue to build up the rotation. Currently it mostly works, the rotation is in small increments but the rotation is instant rather than gradual.

# Script A
public float rotationSpeed = 1f;
public float topClamp = 70.0f;
public float botClamp = -30.0f;
private Vector2 input;
private float cinemachineTargetPitch = 0.0f;
private float rotationVelocity = 0.0f;
public Transform CinemachineCameraTarget;
private float rotationAmount = 2f; # how much should the ball rotate per key press/hold 

void Update()
{
    float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity;
    float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity;
    input = new Vector2(mouseX, mouseY);
    CameraRot();
}

private void CameraRot()
{
    if (input.sqrMagnitude >= 0.01f)
    {
        float deltaTimeMultiplier = 1f;
        cinemachineTargetPitch -= input.y * rotationSpeed * deltaTimeMultiplier;
        rotationVelocity = input.x * rotationSpeed * deltaTimeMultiplier;
        cinemachineTargetPitch = ClampAngle(cinemachineTargetPitch, botClamp, topClamp);
        CinemachineCameraTarget.localRotation = Quaternion.Euler(cinemachineTargetPitch, 0.0f, 0.0f);
        transform.Rotate(Vector3.up * rotationVelocity);
    }
}

private static float ClampAngle(float angle, float min, float max)
{
    if (angle < -360f) angle += 360f;
    if (angle > 360f) angle -= 360f;
    return Mathf.Clamp(angle, min, max);
}

public void ApplyRotToBall()
{
    cinemachineTargetPitch -= rotationAmount;
    cinemachineTargetPitch = ClampAngle(cinemachineTargetPitch, botClamp, topClamp);
    CinemachineCameraTarget.localRotation = Quaternion.Euler(cinemachineTargetPitch, 0.0f, 0.0f);
}

# Script B
# Update method
if (Input.GetMouseButton(0))
{
    cameraRotation.ApplyRotToBall();
}

I used some of my old non-cinemachine camera code to get this far, plus the static ClampAngle which I found. Currently I can’t move my player which is a ball object but I can still test the rotation.

transform.rotate

I use it already transform.Rotate(Vector3.up * rotationVelocity);

then it should work

OK so, I don’t have the answer to your question yet but I’m going through your code piece by piece and catching up problems.

  • First of all, deltaTimeMultiplier is not a good idea, it is not frame rate dependent but the camera rendering and movement are so you should use Time.deltaTime instead, especially when it comes to velocities which is what you do.

  • Then, always remember that floating point arithmetic is never accurate so never do something like:

if (input.sqrMagnitude >= 0.01f)

… without an epsilon.

To give you an example, this is what the line should look like:

public static bool IsGreaterThanOrEqual(this float a, float b, float epsilon)
{
    return a - b > -epsilon;
}

// In your code...
if (input.sqrMagnitude.IsGreaterThanOrEqual(.01f, epsilon: .001f))
{
	// ...
}
  • Additionally, I don’t think that for an input you would like to get the square magnitude of it. The input direction and input magnitude are sufficient.

  • Finally, If nothing shows up with your code, maybe you should check the way your hierarchy of objects is designed.

    • The look at game object should be the origin that you use to rotate around (in a 3rd person view usually set to the head of the player’s mesh).
    • The follow object should be the player itself.

I managed to solve the issues on my own and added even more functionality to it. I do have other problems but they’re not related to this topic question.

I’m going to take a look at your recommendations as well and make some small changes there