Skip to content

Instantly share code, notes, and snippets.

@Zal0
Last active August 7, 2017 16:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zal0/b84ca842c730d29b81f0343d547e4405 to your computer and use it in GitHub Desktop.
Save Zal0/b84ca842c730d29b81f0343d547e4405 to your computer and use it in GitHub Desktop.
CameraManager - 6
/*
* Camera interpolator by Zalo (http://zalods.blogspot.com)
*/
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Camera))]
public class CameraManager : MonoBehaviour {
class CameraParams {
public Quaternion rotation;
public Vector3 offset;
public float fov;
public float near;
public float far;
public void Set(Quaternion finalRot, Camera _cam, Transform _target) {
rotation = Quaternion.Inverse(finalRot) * _cam.transform.rotation; //rotation relative to final_rot
offset = -_cam.transform.worldToLocalMatrix.MultiplyPoint(_target.position); //translation from target to current camera position (in camera local)
fov = _cam.fieldOfView;
near = _cam.nearClipPlane;
far = _cam.farClipPlane;
if(_cam.orthographic) {
fov = 0.1f;
float zOffset = -(_cam.orthographicSize) / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad) - offset.z;
offset.z += zOffset;
near -= zOffset;
far -= zOffset;
}
}
}
public AnimationCurve interpolationCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
private CameraParams fromParams = new CameraParams();
private CameraParams toParams = new CameraParams();
private Camera toCamera;
private float interpolationTime;
private float interpolationTimeAccum;
private Transform target;
private Camera cachedCamera;
void Awake() {
cachedCamera = GetComponent< Camera >();
}
public static void EnableComponents(Camera _cam, bool _value) {
_cam.enabled = _value;
AudioListener toCameraAudioListener = _cam.GetComponent< AudioListener >();
if(toCameraAudioListener != null) {
toCameraAudioListener.enabled = _value;
}
}
public void InterpolateTo(Camera _toCamera, Transform _target, float _time) {
if(_target == null) {
_target = _toCamera.transform;
}
//Update From Camera values
if (toCamera != null) { //Check if the previous target camera is still there to interpolate from it
EnableComponents(toCamera, false);
if(interpolationTimeAccum >= interpolationTime) {
//we don't need to care about this is the interpolation is not finished since this camera if currently being updated
toParams.Set(toCamera.transform.rotation, toCamera, target);
transform.rotation = toCamera.transform.rotation;
transform.position = target.position;
transform.Translate(toParams.offset);
cachedCamera.fieldOfView = toParams.fov;
cachedCamera.nearClipPlane = toParams.near;
cachedCamera.farClipPlane = toParams.far;
}
} else {
//Set interpolation time to 0 if there isn't any Camera to interpolate from
_time = 0.0f;
}
target = _target;
fromParams.Set(_toCamera.transform.rotation, cachedCamera, target);
//Update To Camera values
toCamera = _toCamera;
EnableComponents(toCamera, false);
//Activate interpolator
gameObject.SetActive(true);
//Restet time
interpolationTime = _time;
interpolationTimeAccum = 0.0f;
}
void Refresh() {
float t = interpolationCurve.Evaluate(interpolationTimeAccum / interpolationTime);
toParams.Set(toCamera.transform.rotation, toCamera, target);
cachedCamera.fieldOfView = Mathf.Lerp(fromParams.fov, toParams.fov, t);
//Rotate
transform.rotation = toCamera.transform.rotation * Quaternion.Lerp(fromParams.rotation, toParams.rotation, t);
//Translate
transform.position = target.position;//Place in target position
Vector3 p0 = fromParams.offset;
Vector3 p1 = toParams.offset;
Vector3 p2 = Vector3.Lerp(p0, p1, t);
//Fix Z based on fov changes so height interpolates linearly (better interpolation on fov changes)
float h0 = Mathf.Tan(fromParams.fov * Mathf.Deg2Rad * 0.5f) * p0.z;
float h1 = Mathf.Tan(toParams.fov * Mathf.Deg2Rad * 0.5f) * p1.z;
float h2 = Mathf.Lerp(h0, h1, t);
p2.z = h2 / Mathf.Tan(cachedCamera.fieldOfView * Mathf.Deg2Rad * 0.5f);
transform.Translate(p2);
float tZ = (p1.z == p2.z) ? t : (p2.z - p0.z) / (p1.z - p0.z) ;
cachedCamera.nearClipPlane = Mathf.Lerp(fromParams.near, toParams.near, tZ);
cachedCamera.farClipPlane = Mathf.Lerp(fromParams.far, toParams.far, tZ);
}
void LateUpdate() {
interpolationTimeAccum = Mathf.Clamp(interpolationTimeAccum + Time.deltaTime, 0.0f, interpolationTime);
if(interpolationTimeAccum < interpolationTime) {
Refresh();
} else {
gameObject.SetActive(false);
EnableComponents(toCamera, true);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment