// A 3ds max styled orbit/zoom/pan type camera. cobbled together from various sources by dbuchhofer. // Content is available under Creative Commons Attribution Share Alike. // Filename: maxCamera.cs // // original: http://www.unifycommunity.com/wiki/index.php?title=MouseOrbitZoom // // --01-18-2010 - create temporary target, if none supplied at start //////// Unluck Software Edit - http://www.chemicalbliss.com // --02-28-2013 - changes // - Added smooth camera stop // - Added smooth idle rotation // - Removed middle click behaviour // - Renamed file to "SmoothCameraOrbit.cs" using UnityEngine; using System.Collections; [AddComponentMenu("Camera-Control/Smooth Mouse Orbit - Unluck Software")] public class SmoothCameraOrbit : MonoBehaviour { public Transform target; public Vector3 targetOffset; public float distance = 5.0f; public float maxDistance = 20; public float minDistance = .6f; public float xSpeed = 200.0f; public float ySpeed = 200.0f; public int yMinLimit = -80; public int yMaxLimit = 80; public int zoomRate = 40; public float panSpeed = 0.3f; public float zoomDampening = 5.0f; public float autoRotate = 1f; public float autoRotateSpeed = 0.1f; private float xDeg = 0.0f; private float yDeg = 0.0f; private float currentDistance; private float desiredDistance; private Quaternion currentRotation; private Quaternion desiredRotation; private Quaternion rotation; private Vector3 position; private float idleTimer = 0.0f; private float idleSmooth = 0.0f; void Start() { Init(); } void OnEnable() { Init(); } public void Init() { //If there is no target, create a temporary target at 'distance' from the cameras current viewpoint if (!target) { GameObject go = new GameObject("Cam Target"); go.transform.position = transform.position + (transform.forward * distance); target = go.transform; } //distance = Vector3.Distance(transform.position, target.position); currentDistance = distance; desiredDistance = distance; //be sure to grab the current rotations as starting points. position = transform.position; rotation = transform.rotation; currentRotation = transform.rotation; desiredRotation = transform.rotation; xDeg = Vector3.Angle(Vector3.right, transform.right ); yDeg = Vector3.Angle(Vector3.up, transform.up ); position = target.position - (rotation * Vector3.forward * currentDistance + targetOffset); } /* * Camera logic on LateUpdate to only update after all character movement logic has been handled. */ void LateUpdate() { // If Control and Alt and Middle button? ZOOM! if (Input.GetMouseButton(2) && Input.GetKey(KeyCode.LeftAlt) && Input.GetKey(KeyCode.LeftControl)) { desiredDistance -= Input.GetAxis("Mouse Y") * 0.02f * zoomRate*0.125f * Mathf.Abs(desiredDistance); } // If middle mouse and left alt are selected? ORBIT else if (Input.GetMouseButton(0) ) { xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f; yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f; //Clamp the vertical axis for the orbit yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit); // set camera rotation desiredRotation = Quaternion.Euler(yDeg, xDeg, 0); currentRotation = transform.rotation; rotation = Quaternion.Lerp(currentRotation, desiredRotation, 0.02f * zoomDampening); transform.rotation = rotation; ///////// Reset idle timers idleTimer=0; idleSmooth=0; }else{ //////// Smooth idle rotation idleTimer+=0.02f ; if(idleTimer > autoRotate && autoRotate > 0){ idleSmooth+=(0.02f +idleSmooth)*0.005f; idleSmooth = Mathf.Clamp(idleSmooth, 0, 1); xDeg += xSpeed * Time.deltaTime * idleSmooth * autoRotateSpeed; } ///////// Smooth idle rotation ends ///////// Smooth exit //Clamp the vertical axis for the orbit yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit); // set camera rotation desiredRotation = Quaternion.Euler(yDeg, xDeg, 0); currentRotation = transform.rotation; rotation = Quaternion.Lerp(currentRotation, desiredRotation, 0.02f * zoomDampening*2); transform.rotation = rotation; ///////// Smooth exit ends } ///////// Middle click disabled // otherwise if middle mouse is selected, we pan by way of transforming the target in screenspace // else if (Input.GetMouseButton(2)) // { // grab the rotation of the camera so we can move in a psuedo local XY space // target.rotation = transform.rotation; // target.Translate(Vector3.right * -Input.GetAxis("Mouse X") * panSpeed); // target.Translate(transform.up * -Input.GetAxis("Mouse Y") * panSpeed, Space.World); // } //Orbit Position // affect the desired Zoom distance if we roll the scrollwheel desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * 0.02f * zoomRate * Mathf.Abs(desiredDistance); //clamp the zoom min/max desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance); // For smoothing of the zoom, lerp distance currentDistance = Mathf.Lerp(currentDistance, desiredDistance, 0.02f * zoomDampening); // calculate position based on the new currentDistance position = target.position - (rotation * Vector3.forward * currentDistance + targetOffset); transform.position = position; } private static float ClampAngle(float angle, float min, float max) { if (angle < -360) angle += 360; if (angle > 360) angle -= 360; return Mathf.Clamp(angle, min, max); } }