Camera rotating around GameObject's pivot

Guys, sorry to post this thread yet again. This is the third thread regarding the same problem which I have for the past 1 week.

Please, somebody, anybody, please help me out. Im really really desperate at this point.

Sorry for asking this but could someone help me out? This is for my school’s Final Year Project.

Im currently having trouble in getting 3rd Person camera to work the way I want it to.

The problems which Im facing:

  1. Smooth transition of camera moving from point A to point B upon user interaction with the mouse click

  2. Camera rotating around the player. In other words, the pivot point is based on the player, and not the camera’s pivot. Actually, what I wanted to do is just an Over-The-Shoulder camera effect (when the player hold onto the right-click mouse button, it will switch from the default ThirdPersonCam to Over-The-Shoulder cam)

Before going further, I would like to highlight that:

  1. For the smooth transition, it seems that the function for moving the camera smoothly with the Lerp seems to be ran. However, that Lerping has been overwrite by the LateUpdate function in the ThirdPersonView’s script(Which I’ll be showing in a moment).

  2. Camera actually does rotates around the player. However, this can only work when the camera is DIRECTLY behind the player. It does not rotate around the player if the camera has been altered to move a certain distance to the right of the position.x. After trying with the changing of the position.x value, the whole camera just does not rotate around the player.
    Updated script:
    Ive combined both the scripts into one whole script, for easier reading and optimizing codes
    ```
    **// the target for the camera to orbit around
    var target : Transform;

//target for OverTheShoulderView
var targetOTSV : Transform;

//target for ThirdPersonView
var targetTPV : Transform;

public var lerpNowToTPV = false;

public var lockMouseInPos = false;

// initial distance between the camera and the target
var distance = 5.0;
// min and max distance for zooming
var minDistance = 3.0;
var maxDistance = 10.0;

// an offset to stop the camera clipping walls
var offsetFromWall : float = 0.28;

// the speed at which the scrollwheel zooms in/out
var zoomRate = 20;

// some internal variables to calculate distances
private var currentDistance : float;
private var desiredDistance : float;
private var correctedDistance : float;

// speed of camera rotation around the object in both axes and smoothing for rotation
var xSpeed : float = 200.0;
var ySpeed : float = 200.0;
var rotationDampening : float = 3.0;

// the min and max rotation limits of the camera in the y-axis (up and over the object) and smoothing for zooming
var yMinLimit : int = 0;
var yMaxLimit : int = 80;
var zoomDampening : float = 5.0;

// variables to store the rotation of the camera
private var x : float = 0.0;
private var y : float = 0.0;

// variables for zooming axis limit
public var yMinLimitZoomed: float = 0.00;
public var yMaxLimitZoomed: float = 0.00;

///////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////
//for Smooth Transition Cam//
/////////////////////////////
public var lockAtThisDist = 0;
public var speedAdjuster: int = 0;

//////////////////////
///Position Updater///
/////////////////////
private var oldPosX: float = 0.00;
private var oldPosY: float = 0.00;
private var oldPosZ: float = 0.00;

private var newPosX: float = 0.00;
private var newPosY: float = 0.00;
private var newPosZ: float = 0.00;

private var currentPosX: float = 0.00;
private var currentPosY: float = 0.00;
private var currentPosZ: float = 0.00;
///////////////////////////////////////////////////////////////////////////////////////

// adds a menu option to attach this script via the Component Menu
@script AddComponentMenu(“Camera-Control/Mouse Orbit”)

function Awake()
{
positionOld = transform.position;
}

function Start () {
// store the initial rotation of the camera on the x and y axes
var angles = transform.eulerAngles;
x = angles.y;
y = angles.x;

// set zoom distances to the value of the initial distance
currentDistance = distance; //Original distance uses the variable called “distance”
desiredDistance = distance;
correctedDistance = distance;

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

// LateUpdate is called every frame after all other updates have happened
//(preferable for camera follows since all objects should have already moved)
function LateUpdate () {

// if a target has been assigned (drag and drop one in the editor)
if (target) {
	// if there is input on the vertical or horizontal axes (default is arrow keys and wasd)
	if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal")) 
	{
		// store the current y-axis rotation of the target and the camera
		var targetRotationAngle = target.eulerAngles.y;
		var currentRotationAngle = transform.eulerAngles.y;
		// interpolate between the current y-axis rotation and the target y-axis rotation over time
		// setting the changing value to the x-axis rotation so the camera rotates around behind the PC
		x = Mathf.LerpAngle(currentRotationAngle, targetRotationAngle, rotationDampening * Time.deltaTime);
     
		 ////////////////////////
		 //EDITED VERSION//
		 ////////////////////////
		 x += Input.GetAxis("Mouse X") * xSpeed * 0.001;//EDITED VERSION,. DO REMOVE IF NOT WORKING
		 y -= Input.GetAxis("Mouse Y") * ySpeed * 0.01;//EDITED VERSION,. DO REMOVE IF NOT WORKING
	} 
	
	// if there is no input from the vertical/horizontal axes (we are not moving)
	else 
	{
		// allow the player to rotate the camera using the mouse by updating the camera's
		// x/y rotation values based on the mouse position
		x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
		y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
	}
  
     
	// set the y-axis rotation value based on the result of the ClampAngle function
	y = ClampAngle(y, yMinLimit, yMaxLimit);
	  
	// store the camera's rotation
	var rotation = Quaternion.Euler(y, x, 0);
	  
	// convert input from the scrollwheel into zooming between the min/max distance ranges
	//desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs (desiredDistance); //Disabled zooming feature, so that the mouse scroll is used for striking matches
	desiredDistance = Mathf.Clamp (desiredDistance, minDistance, maxDistance);
	correctedDistance = desiredDistance;
	  
	// store the camer's position
	var position = target.position - (rotation * Vector3.forward * desiredDistance);
	
	// a variable to hold a reference to raycast collision objects
	var hit : RaycastHit;
	// a variable to hold a flag so we know if we have already corrected the camera's position
	var isCorrected : boolean = false;
	// if a ray between the target and the desired position hits something then their must be something blocking the line of sight
	if (Physics.Linecast (target.position, position, hit)) 
	{
		// shorten the distance between the camera and the target using the distance to the wall
		// minus an offset to prevent clipping
		correctedDistance = Vector3.Distance (target.position, hit.point) - offsetFromWall;
		// we have corrected the camera's position
		isCorrected = true;
	}

	// if we haven't corrected the camera's position or the new distance is greater than the current distance
	if(!isCorrected || correctedDistance > currentDistance)
	{
		// interpolate the distance of the camera from the target between the current distance and the corrected distances
		// (ie. in front of the wall that is blocking our view)
			
		currentDistance = Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening);
	}
	  
	// set our current distance to this new distance
	currentDistance = correctedDistance;
		 
	// clamp this value between the minimum and maximum distance settings
	currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);
	  
	// store the new position
	position = target.position - (rotation * Vector3.forward * currentDistance);
	
	///////////////////////////////////////////////////
	//For initiating positions for TPVCam and OTSVCam//
	///////////////////////////////////////////////////
	var locateOTSVCam = GameObject.Find("OTSVCam");
	var locateTPVCam = GameObject.Find("TPVCam");
	
	locateTPVCam.transform.position = position;
	
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//FOR UPDATING THE CAMERA MOVEMENT. THE MAIN CODING THAT AFFECTS THE LOCKING OF THE POSITION AND THE ROTATION OF THE GAMEOBJECT//
	/////////////////////////////////////////////////This is just purely for switching between views, OTSV and TPV modes//////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//Over-the-shoulder-view
	if (Input.GetKey(KeyCode.Mouse1))
	{		
		storedMousePosition = Input.mousePosition;
		
		//if camera is no where near the target destination point, it will lerps to it
		if (Vector3.Distance(targetOTSV.position, transform.position) > lockAtThisDist)
		{
			//forcing the mouse to stay in position
			lockMouseInPos = true;	
			
			// Lock the cursor
			Screen.lockCursor = true;
			
			/*It is entirely possible to implement a custom cursor instead of the system one. 
			To do this you would hide the system one, track mouse position or movement and display your own image in the needed place.*/
			// Hide the cursor
			Screen.showCursor = false; //Disable the system mouse, so we can use our custom crosshair for the Over-The-Shoulder view
			
			oldPosX = transform.position.x;
			oldPosY = transform.position.y;
			oldPosZ = transform.position.z;
		
			newPosX = targetOTSV.position.x;
			newPosY = targetOTSV.position.y;
			newPosZ = targetOTSV.position.z;
			
			transform.position.x = Mathf.Lerp(oldPosX, newPosX, Time.deltaTime * speedAdjuster); 
			transform.position.y = Mathf.Lerp(oldPosY, newPosY, Time.deltaTime * speedAdjuster); 
			transform.position.z = Mathf.Lerp(oldPosZ, newPosZ, Time.deltaTime * speedAdjuster); 
		}
		
		else 
		{
			//locking to OTSV's mode
			lerpNowToTPV = true;
			lockMouseInPos = false;
			//y = ClampAngle(y, yMinLimitZoomed, yMaxLimitZoomed);
			//rotation = Quaternion.Euler(y, x, 0);
			//transform.rotation = rotation;
			//transform.rotation = rotation;
			//transform.position = position;
		}
	}
	
	//third-person-view
	else if (!Input.GetKey(KeyCode.Mouse1))
	{	
		storedMousePosition = Input.mousePosition;
		
		//if camera is no where near the target destination point, it will leap to it
		if (Vector3.Distance(targetTPV.position, transform.position) > lockAtThisDist  lerpNowToTPV)
		{
			//forcing the mouse to stay in position
			lockMouseInPos = true;		
			
			// Lock the cursor
			Screen.lockCursor = false;
			
			oldPosX = transform.position.x;
			oldPosY = transform.position.y;
			oldPosZ = transform.position.z;
		
			newPosX = targetTPV.position.x;
			newPosY = targetTPV.position.y;
			newPosZ = targetTPV.position.z;
			
			transform.position.x = Mathf.Lerp(oldPosX, newPosX, Time.deltaTime * speedAdjuster); 
			transform.position.y = Mathf.Lerp(oldPosY, newPosY, Time.deltaTime * speedAdjuster); 
			transform.position.z = Mathf.Lerp(oldPosZ, newPosZ, Time.deltaTime * speedAdjuster); 
		}
		
		else 
		{
			//locking to TPV's mode
			lerpNowToTPV = false;
			transform.rotation = rotation;
			transform.position = position;
			
			lockMouseInPos = false;
		}
	}
	
	/*
	//If right click is down, the camera is in OTSV mode
	if (Input.GetKey(KeyCode.Mouse1))
	{	
		//transform.rotation = rotation;
		//transform.position = position;
		y = ClampAngle(y, yMinLimitZoomed, yMaxLimitZoomed);
		rotation = Quaternion.Euler(y, x, 0);
		transform.rotation = rotation;
	}*/
}

}

// keeps the value of the y-axis rotation within 360 degrees (it would cause an error otherwise)
// and within the minimum and maximum limits previously defined
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);
}

function Update()
{
if(lockMouseInPos)
{
//Input.GetAxis (“Mouse Y”).sensitivity : float = 0.00;
}
}**
```
Thanks in advance for those who took the time and help me out. I really really do appreciate it…

my suggestion is to have the camera’s target destination relative to the players - dont bother giving the over the shoulder position a target, just fix it onto something:

create an empty game object, name it OverTheShoulder or something and put it in the position where you want the camera to be, but make the player model or controller the parent (i think its called parenting, drag it onto the character controller model on the menu) so it stays fixed in that relative position.

once youve got it in place, create some variables to store the x y and z positions and rotations of the gameobject you stuck behind your player’s shoulder - once you’ve got them write an if statement in the update function to check if the appropriate button is being pushed down, and command it to change it’s transform positions to the variables you made :slight_smile:

dont know if i was helpful or not, but good luck to you :slight_smile: if you dont get a response, try PMing some of the more experienced members like the forum moderators, they’re pure genius. hope you finish this in time!

Regards, ><>FreakFish<><

Erm…thanks for the reply FreakFish…but that’s not what I wanted…if I were to do that, the camera’s pivot point will be by its own…What I want is that the camera will rotate around the pivot point of the character…

Well, Im not a person who can express myself clearly…so I guess examples from a video will do a much better job than me explaining…

Metal Gear Peace Walker: http://www.youtube.com/watch?v=KE1LllEgElc

Please look at the timeline 2.15 onwards. You’ll see a brief moment of Solid Snake zooming from Third Person view to Over-the-shoulder-view. When he’s shooting, the camera is having its pivot point on character…or maybe I might be wrong…

Anyways, what Im trying to achieve is exactly whats in that video…the over-the-shoulder-view…

Could anyone please help me out here? Thanks in advance!