Over the Shoulder Camera Not Working

Hello. I’ve been struggling on getting this over-the-shoulder camera to work. I’m trying to modify the MouseOrbit script so that the camera will zoom into an over-the-shoulder view when the right mouse button is clicked. Right now I have it set up so that the camera should zoom into a null Transform “starget” that is located near the shoulder of my character. The problem is that when the right mouse button is clicked this only happens for about a frame before everything snaps back into normal third person view. Also, when the right mouse button is down the camera should not be able to orbit anymore, but it is with what I have written.

Here is my code.

var target : Transform;
var distance = 10.0;

var xSpeed = 250.0;
var ySpeed = 120.0;

var yMinLimit = -20;
var yMaxLimit = 80;

private var x = 0.0;
private var y = 0.0;
private var baseFOV : float;

/*Point that the camera should zoom in to when right 
mouse button is clicked.*/
public var starget : Transform;
 
@script AddComponentMenu("Camera-Control/Mouse Orbit")

function Start () {
    var angles = transform.eulerAngles;
    x = angles.y;
    y = angles.x;
    baseFOV = Camera.main.fieldOfView;

	// Make the rigid body not change rotation
   	if (rigidbody)
		rigidbody.freezeRotation = true;
}

function L() {
	/*Zoom camera to fixed position over shoulder when
	right mouse button is clicked*/
	if(Input.GetMouseButtonDown(1)){ 
		Camera.main.transform.LookAt(starget);
		Camera.main.fieldOfView = 20;
	}
	else{
		if(Input.GetMouseButtonUp(1)){
			Camera.main.transform.LookAt(target);
			Camera.main.fieldOfView = baseFOV;
		}
		/*Orbit camera around player character*/
		if (target){
		    x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
		    y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
		 		
		 	y = ClampAngle(y, yMinLimit, yMaxLimit);
		 		       
		    var rotation = Quaternion.Euler(y, x, 0);
		    var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
		        
		    transform.rotation = rotation;
		    transform.position = position;
		}
	}
}

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

Also, if there is a better way of accomplishing this, please let me know. I’m still getting used to coding and Unity and appreciate any help I can get.

I suggest you use a boolean variable to keep track of your zoom state.

public var isZoomed : boolean;

This lets you easily stop that pesky mouseOrbit code from running when you’re zoomed in.

//Put this in your update
if (isZoomed == false) {

     //MouseOrbit code

     }

Then you simply use a method to control when it zooms.

function Zoom(action:boolean) {

     if (action == true) {
          Camera.main.transform.LookAt(starget);
          Camera.main.fieldOfView = 20;
          isZoomed = true;
          }
     else {
          Camera.main.transform.LookAt(target);
          Camera.main.fieldOfView = baseFOV;
          isZoomed = false;
          }

     }

And call it using Input.GetMouseButton.

//Put these in your update
if (Input.GetMouseButtonDown(1)) {
    Zoom(true);
    }

if (Input.GetMouseButtonUp(1)) {
    Zoom(false);
    }

Other than that, I also suggest using MouseLook rather than MouseOrbit. You can use nested empty gameObjects with multiple MouseLooks to get that Over-The-Shoulder feel. But what you’re doing will probably work too.