Created
August 19, 2014 20:42
-
-
Save bingomanatee/764858f6c1323770c77b to your computer and use it in GitHub Desktop.
The camera control - using state and Lerping betweeen camera data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
/** | |
* this is a structure that freezes a target camera position rotation and field of view | |
* as a lerp target for transitions. | |
* while these properties will be frozen in place for the target extremes, the main camera's properteis | |
* will be constantly fluxuating between values. Also, if a camera transitions to a new target while en route | |
* to an old one, the goal is to freeze that transition point into a CameraState as a basis for lerping. | |
*/ | |
public struct CameraState | |
{ | |
public Vector3 position; | |
public Quaternion rotation; | |
public float fieldOfView; | |
public string name; | |
// redundant as most of the time cameraState will be pulled off of the dictionary | |
// but useful occasionally. | |
public CameraState (Camera c) | |
{ | |
position = c.transform.position; | |
rotation = c.transform.rotation; | |
fieldOfView = c.fieldOfView; | |
name = c.name; | |
} | |
public CameraState (Camera c, string n) | |
{ | |
position = c.transform.position; | |
rotation = c.transform.rotation; | |
fieldOfView = c.fieldOfView; | |
name = n; | |
} | |
} | |
public class CameraShift : MonoBehaviour | |
{ | |
const float DEFAULT_TRANSITION_TIME = 4f; | |
public const string HOME_CAMERA_NAME = "HOME"; | |
public List <Camera> targets = new List<Camera> (); | |
Dictionary<string, CameraState> lookup = new Dictionary<string, CameraState> (); | |
public CameraState currentTarget; | |
public CameraState lastTarget; | |
float lastRetargetTime = 0; | |
float transitionTime = DEFAULT_TRANSITION_TIME; | |
public delegate void CameraArrival (string name); | |
public static event CameraArrival CameraArrived; | |
public AnimationCurve animationTransition; | |
enum MoveState | |
{ | |
Unknown, | |
Stable, | |
Moving | |
} | |
public float progressToTarget = 0f; | |
MoveState state = MoveState.Unknown; | |
public string _ntName; | |
public string targetName { | |
set { | |
if (state == MoveState.Moving) { | |
FreezeCurrentCameraState (); | |
} | |
Debug.Log ("Lerping to target: " + value); | |
if (lookup.ContainsKey (value)) { | |
_ntName = value; | |
currentTarget = lookup [value]; | |
} else { | |
Debug.Log ("Cannot find key " + value + " in CameraShift dictionary"); | |
currentTarget = lookup [HOME_CAMERA_NAME]; | |
_ntName = HOME_CAMERA_NAME; | |
} | |
state = MoveState.Moving; | |
lastRetargetTime = Time.time; | |
} | |
get { | |
return _ntName; | |
} | |
} | |
// Use this for initialization | |
void Start () | |
{ | |
currentTarget = new CameraState (this.GetComponent<Camera>(), HOME_CAMERA_NAME); | |
lastTarget = currentTarget; | |
state = MoveState.Stable; | |
progressToTarget = 1.0f; | |
lookup.Add(HOME_CAMERA_NAME, new CameraState(this.GetComponent<Camera>(), HOME_CAMERA_NAME)); | |
foreach (Camera c in targets) { | |
lookup.Add (c.name, new CameraState (c)); | |
} | |
// for testing purposes | |
//targetName = targets [0].name; | |
CameraArrived += OnCameraArrive; | |
} | |
// Update is called once per frame | |
void Update () | |
{ | |
if (state == MoveState.Moving) { | |
MoveCamera (); | |
} | |
} | |
void FreezeCurrentCameraState(){ | |
lastTarget = new CameraState(this.GetComponent<Camera>()); | |
} | |
void OnCameraArrive (string arrivedName) | |
{ | |
/* Debug.Log ("Camera change -- arrived at " + arrivedName); | |
string firstTarget = targets [0].name; | |
string secondTarget = targets [1].name; | |
switch (arrivedName) { | |
case HOME_CAMERA_NAME: | |
Debug.Log ("Switching to first target " + firstTarget); | |
targetName = firstTarget; | |
break; | |
case "TableCamera": | |
Debug.Log ("Switching to second target " + secondTarget); | |
targetName = secondTarget; | |
break; | |
default: | |
targetName = HOME_CAMERA_NAME; | |
break; | |
} */ | |
} | |
float CurveValue (float inputValue) | |
{ | |
return animationTransition.Evaluate (inputValue); | |
} | |
void MoveCamera () | |
{ | |
float l = (Time.time - lastRetargetTime) / transitionTime; | |
if (l >= 1) { | |
this.GetComponent<Camera>().transform.position = currentTarget.position; | |
this.GetComponent<Camera>().transform.rotation = currentTarget.rotation; | |
state = MoveState.Stable; | |
lastTarget = currentTarget; | |
this.GetComponent<Camera>().fieldOfView = currentTarget.fieldOfView; | |
if (CameraArrived != null) | |
CameraArrived (currentTarget.name); | |
} else { | |
l = CurveValue (l); | |
this.GetComponent<Camera>().transform.position = LerpPosition(l); | |
this.GetComponent<Camera>().transform.rotation = LerpRotation(l); | |
this.GetComponent<Camera>().fieldOfView = LerpFOV(l); | |
} | |
} | |
float LerpFOV (float l) | |
{ | |
return Mathf.Lerp (lastTarget.fieldOfView, currentTarget.fieldOfView, l); | |
} | |
Vector3 LerpPosition (float l) | |
{ | |
Vector3 previous = (1 - l) * lastTarget.position; | |
Vector3 current = l * currentTarget.position; | |
return previous + current; | |
} | |
Quaternion LerpRotation (float l) | |
{ | |
return Quaternion.Lerp (lastTarget.rotation, currentTarget.rotation, l); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment