# camera orbit on mouse drag

Hi, I have this script from the wiki, when i drag my mouse it rotates the camera around my player character but when i release my mouse the camera stays where i left it. I wan't it to snap back to it's start position.

``````var target : Transform;
var distance = 5.0;
var xSpeed = 125.0;
var ySpeed = 50.0;

private var x = 0.0;
private var y = 0.0;

function Start () {
var angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
}

function LateUpdate () {
if (target) {
x += Input.GetAxis("Mouse X") * xSpeed * distance* 0.02;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
var rotation = Quaternion.Euler(y, x, 0);
var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
transform.rotation = rotation;
transform.position = position;
}
}

``````

I think the last position is stored cause when i click the screen again, my camera jumps back to it's last position when i was draggin my mouse over the screen. Any help would be appreciated.

Hi used that script MouseOrbitImproved (Thanks to Veli V) and modified it to get a smooth rotation on drag.

Here is the code:

``````using UnityEngine;
using UnityEngine;
using System.Collections;

public class DragMouseOrbit : MonoBehaviour
{
public Transform target;
public float distance = 5.0f;
public float xSpeed = 120.0f;
public float ySpeed = 120.0f;

public float yMinLimit = -20f;
public float yMaxLimit = 80f;

public float distanceMin = .5f;
public float distanceMax = 15f;

public float smoothTime = 2f;

float rotationYAxis = 0.0f;
float rotationXAxis = 0.0f;

float velocityX = 0.0f;
float velocityY = 0.0f;

// Use this for initialization
void Start()
{
Vector3 angles = transform.eulerAngles;
rotationYAxis = angles.y;
rotationXAxis = angles.x;

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

void LateUpdate()
{
if (target)
{
if (Input.GetMouseButton(0))
{
velocityX += xSpeed * Input.GetAxis("Mouse X") * distance * 0.02f;
velocityY += ySpeed * Input.GetAxis("Mouse Y") * 0.02f;
}

rotationYAxis += velocityX;
rotationXAxis -= velocityY;

rotationXAxis = ClampAngle(rotationXAxis, yMinLimit, yMaxLimit);

Quaternion fromRotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, 0);
Quaternion toRotation = Quaternion.Euler(rotationXAxis, rotationYAxis, 0);
Quaternion rotation = toRotation;

distance = Mathf.Clamp(distance - Input.GetAxis("Mouse ScrollWheel") * 5, distanceMin, distanceMax);

RaycastHit hit;
if (Physics.Linecast(target.position, transform.position, out hit))
{
distance -= hit.distance;
}
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + target.position;

transform.rotation = rotation;
transform.position = position;

velocityX = Mathf.Lerp(velocityX, 0, Time.deltaTime * smoothTime);
velocityY = Mathf.Lerp(velocityY, 0, Time.deltaTime * smoothTime);
}

}

public 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);
}
}
``````

This script should have nothing to do with your mouse button being held down if I read it correctly. Is there maybe another script that you have at work here that is based on the mouse button? Here's what your script does:

``````var target : Transform; //What to rotate around
var distance = 5.0; //How far away to orbit
var xSpeed = 125.0; //X sensitivity
var ySpeed = 50.0; //Y sensitivity

private var x = 0.0; //Angle of the y rotation?
private var y = 0.0; //Angle of the x rotation?

function Start() {Run this once at the start
//Initialize the angles
var angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
}

function LateUpdate() { //Every frame, do this as late as you can
if (target) {//There's a target
//Change the angles by the mouse movement
x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;

//Rotate the camera to those angles
var rotation = Quaternion.Euler(y, x, 0);
transform.rotation = rotation;

//Move the camera to look at the target
var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
transform.position = position;
}
}

``````

If you want it happen while the mouse is held down, you could add Input.GetMouseButton(0) or GetButton("Fire") (or whatever you have setup in your Input manager for the mouse button) to the if statement. As it was posted, the script doesn't care about the mouse button.

If you want it to return to the start position on mouse release, you will need to store the start angles and move to them. You will also likely want to smooth it nicely.

Doing all that, you can get a pretty good result like this, but it could possibly use some optimization and tuning:

``````var target : Transform; //What to rotate around
var distance : float = 5.0; //How far away to orbit
var xSpeed : float = 125.0; //X sensitivity
var ySpeed : float = 50.0; //Y sensitivity

var resetTime : float = 1.0; //How long to take to reset

private var startX : float = 0.0; //Start y rotation
private var startY : float = 0.0; //Start x rotation

private var x : float = 0.0; //Y rotation
private var y : float = 0.0; //X rotation

private var endX : float = 0.0; //Where to reset x from
private var endY : float = 0.0; //Where to reset y from

private var rotation : Quaternion; //Current orientation

private var resetting : boolean = false; //resetting?
private var resetTimer : float = 0.0; //How long we've been resetting

function LateUpdate() { //Every frame, do this as late as you can
if (target) {//There's a target
if(!resetting && Input.GetMouseButtonUp(0)) { //Released mouse button
resetting = true;
endX = x;
endY = y;
resetTimer = 0.0; //Reset the reset timer
}

if(!resetting) {
if (Input.GetMouseButtonDown(0)) { //Pushed mouse button
//Initialize the angles
var angles = transform.eulerAngles;
x = angles.y;
startX = x;
y = angles.x;
startY = y;
} //first time the button down

if(Input.GetMouseButton(0)) { //Mouse button is down
//Change the angles by the mouse movement
x += Input.GetAxis("Mouse X") * xSpeed * distance* 0.02;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
Reorient();
} //button held down
} //Camera moving
else { //Reset
resetTimer += Time.deltaTime; //add to the timer;
var amountReset = resetTimer / resetTime; //How far we are
x = Mathf.LerpAngle(endX, startX, amountReset); //Smooth angles
y = Mathf.LerpAngle(endY, startY, amountReset); //Smooth angles
Reorient();
if(resetTimer >= resetTime) resetting = false;
} //Reset
} //There's a target
} //LateUpdate

function Reorient() { //orient yourself
//Rotate the camera to those angles
rotation = Quaternion.Euler(y, x, 0);
transform.rotation = rotation;

//Move the camera to look at the target
transform.position = rotation * Vector3(0.0, 0.0, -distance)
+ target.position;
}

``````

## EDIT 09/27:

As Joaquin brings up, you may want to maintain the original position and orientation relative to the target as when you start the orbit. The following will do this because it does not derive orientation from the initial euler angles, but from the current relative orientation, but it will not force the camera to look at the target:

``````var target : Transform; //What to rotate around
var xSpeed : float = 125.0; //X sensitivity
var ySpeed : float = 50.0; //Y sensitivity

var resetTime : float = 1.0; //How long to take to reset

private var startDirection : Vector3 = Vector3.zero; //How far away to orbit

private var x : float = 0.0; //Y rotation
private var y : float = 0.0; //X rotation

private var endX : float = 0.0; //Where to reset x from
private var endY : float = 0.0; //Where to reset y from

private var startRotation : Quaternion; //Start orientation
private var rotation : Quaternion; //Current orientation

private var resetting : boolean = false; //resetting?
private var resetTimer : float = 0.0; //How long we've been resetting

function LateUpdate() { //Every frame, do this as late as you can
if (target) {//There's a target
if(!resetting && Input.GetMouseButtonUp(0)) { //Released mouse button
resetting = true;
endX = x;
endY = y;
resetTimer = 0.0; //Reset the reset timer
}

if(!resetting) {
if (Input.GetMouseButtonDown(0)) { //Pushed mouse button
//Initialize
startDirection = (transform.position - target.position);
startRotation = transform.rotation;
x = 0.0;
y = 0.0;
} //first time the button down

if(Input.GetMouseButton(0)) { //Mouse button is down
//Change the angles by the mouse movement
x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
Reorient();
} //button held down
} //Camera moving
else { //Reset
resetTimer += Time.deltaTime; //add to the timer;
var amountReset = resetTimer / resetTime; //How far we are
x = Mathf.LerpAngle(endX, 0.0, amountReset); //Smooth angles
y = Mathf.LerpAngle(endY, 0.0, amountReset); //Smooth angles
Reorient();
if(resetTimer >= resetTime) resetting = false;
} //Reset
} //There's a target
} //LateUpdate

function Reorient() { //orient yourself
//Get the orientation and reorient
rotation = Quaternion.Euler(y, x, 0);
transform.rotation = rotation * startRotation;

//Move the camera to that orientation
transform.position = rotation * startDirection + target.position;
}

``````

To make the camera immediately and explicitly look at the target in the above code, you could make a change something like:

``````//in the getMouseButtonDown, replace the startRotation assignment with
//Rotate to look at the target
startRotation = Quaternion.FromToRotation(transform.forward,
target.position - transform.position) * transform.rotation;

``````

or to do it more gradually, you could add a timer as was done for resetting the view with the following changed:

``````//script global, add
var lookAdjustTime : float = 1.0; //How long to take to look at the target
private var lookAdjust : Quaternion; //A start rotation that looks at the target
private var lookAdjustTimer : float = 0.0; //How long we've been rotating the look
private var adjustedStartRotation : Quaternion; //The new start rotation to orient to

//Get a start rotation that looks at the target
target.position - transform.position) * startRotation;

//Replace Reorient with this
function Reorient() { //orient yourself
//Get the orientation and reorient
rotation = Quaternion.Euler(y, x, 0);