Trying to get a third person camera to be movable and lock in place when not being moved

I’m new and don’t really know what I’m doing working with rotations and the camera. I found a script in a free asset that almost does what I want and I started modifying it. The code below is what I have right now.

I’m trying to get the camera to zoom in and out from the player with the scroll wheel, rotate around the player and up and down by holding down the right mouse button and moving the mouse, and then trying to get the camera to stay locked in place relative to the player when you are not moving the camera IE you have the camera on your right side and turn while running and its still on your right side.

This script works exactly like I want it to now except for one major glitch. If I turn the player at all and then go to move the camera again it will jump to a new position at the first click of the mouse. After that it works just how I want it too until I turn the player again. I’m hoping someone knows an easy way to fix this.

Edit: the camera is a child of the player object and the script is attached to it.

   public class ThirdPersonCamera : MonoBehaviour
   {
    private const float Y_ANGLE_MIN = 0.0f;
    private const float Y_ANGLE_MAX = 80.0f;

    public Transform lookAt;            //this is set in inspecter to the characters head.
    public Transform camTransform;     
    public float distance = 5.0f;      //how far away the camara is

    private float currentX = 0.0f;             
    private float currentY = 45.0f;            

    private float speed = 3f;     //speed multiplier for moving camera.
    Quaternion rotation;

    private void Start()
    {
        camTransform = transform;
        rotation = Quaternion.Euler(currentY, currentX, 0);   //get camera in the starting position.
        camTransform.position = lookAt.position + rotation * new Vector3(0, 0, -distance);
    }

    private void Update()
    {
        distance -= Input.mouseScrollDelta.y * 40 * Time.deltaTime;  // mouse scroll to change cameras distance from player.
        distance = Mathf.Clamp(distance, 0.7f, 10f);    //stop camera from going into player or way far away.

        if (Input.GetMouseButton(1))   //try to get the camera to only move while holding down right mouse button.
        {
            currentX += Input.GetAxis("Mouse X") * speed;   
            currentY -= Input.GetAxis("Mouse Y") *speed;    //- so camera goes the other way

            currentY = Mathf.Clamp(currentY, Y_ANGLE_MIN, Y_ANGLE_MAX);
        }
    }

    private void LateUpdate()
    {
        Vector3 dir = new Vector3(0, 0, -distance);

        if (Input.GetMouseButton(1) || Input.mouseScrollDelta.y != 0)   //trying to keep the camera locked in place relative to the player when not moving the camera.
        {
            rotation = Quaternion.Euler(currentY, currentX, 0);
            camTransform.position = lookAt.position + rotation * dir;
        }
           camTransform.LookAt(lookAt.position);
    }
}

Thanks for the reply.

This example doesn’t seem to work for me. The camera will no longer rotate when I hold down the mouse button and it will still jump to a new position when I hit mouse button after turning the character.

I’m assuming the camTransform.position = lookAt.posistion + rotation * dir; is what is changing the camera’s position. Unfortunately I don’t understand the math here as it was part of the script before I started modifying it.

What value is multiplying those 2 vectors together intended to give? Why does it only drastically change the position after the character has rotated and then seem to move smoothly? Why doesn’t it do the same thing if I hold down the mouse button the entire time (it seems to not jump when moving around then)?

Somehow it seems to be deciding a rotation for the camera vastly different then what it was on the first frame of the click and then it moves the camera to match that rotation and still be the same distance away and looking at the player.

Oh well I guess I’ll work on something else for now and figure it out later after I learn some of the math involved. I already bought a Udemy course on math for games and just haven’t done it yet.

Hi, the solution below isn’t tested, and doesn’t contain rotation restrictions, but give it a try and tell me if it works for you.

[SerializedField]
Transform player;
Transform cam;

Vector3 offsetDir;
float distance;

float camDelay;
float camRotSpeed;
float camScrollSpeed;

void Start () {
	cam = Camera.Main.transform;
	offsetDir = cam.position - player.position;
}

public FixedUpdate () {

	// Function to handle the adjusted camera
	HandleAdjustment();
	
	// Function to handle the camera following the player
	HandleCameraMovement ();
	
}

void HandleAdjustment () {
	// Change Distance	
	distance -= Input.mouseScrollDelta.y * camScrollSpeed * Time.deltaTime; 
	distance = Mathf.Clamp(distance, 0.7f, 10f);  
	
	// Dont do anything if the right mouse is not held down
	if (!Input.GetKey(KeyCode.MouseButton(1)))
		return;
		
	offsetDir += new Vector3(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"), 0) * camRotSpeed * Time.DeltaTime;
}

void HandleCameraMovement () {
	var targetLocation = (offsetDir).normalized * distance;	
	cam.position = Vector3.Lerp (cam.position, targetLocation, camDelay);
	cam.LookAt(player.position + new Vector3 (0,player.localScal.y / 2,0));
}

Put this in your Update() method;

camTransform.position = Vector3.MoveTowards(camTransform.position, camTransform.position + camTransform.forward * Input.mouseScrollDelta.y, 1);

		if (Input.GetMouseButton(1))
		{
			camTransform.RotateAround(lookAt.position, Vector3.up, Input.GetAxis("Mouse X") * speed);
			camTransform.RotateAround(lookAt.position, camTransform.right, -Input.GetAxis("Mouse Y") * speed);
		}

and you can get rid of the entire LateUpdate() .

Now, there is no clamping / limits to movement implemented in there yet, but it should otherwise behave the way you want it to.