Skip to content

Instantly share code, notes, and snippets.

@nonathaj
Created August 18, 2015 18:26
Show Gist options
  • Save nonathaj/119a428130cf8c506dc9 to your computer and use it in GitHub Desktop.
Save nonathaj/119a428130cf8c506dc9 to your computer and use it in GitHub Desktop.
using UnityEngine;
using System.Collections;
/// <summary>
/// Camera Follower
///
/// Causes a camera to follow the position of a provided transform, and optionally it's x/y/z rotatations.
/// The camera can zoom out, in either orthographic or perspective mode and is limited on both ends.
///
/// Do NOT parent this component's gameobject to the follow transform. It must be at the same transform level, or higher.
/// </summary>
[RequireComponent(typeof(Camera))]
public class CameraFollower : MonoBehaviour
{
private Camera cam;
public Camera Cam {
get {
if (cam == null)
cam = GetComponent<Camera>();
return cam;
}
}
[SerializeField, Tooltip("What Transform are we following?")]
Transform followTransform;
public Transform FollowTransform { get { return followTransform; } }
public enum MoveType { Direct, Lerp, MoveTowards }
[SerializeField, Tooltip("What method of movement toward our desired position should we use?")]
MoveType movementType;
public MoveType MovementType { get { return movementType; } set { movementType = value; } }
[SerializeField, Tooltip("How quickly do we move toward our relative follow transform position? (Does nothing when Movement Type is set to Direct)")]
float MoveSpeed = 10;
[SerializeField, Tooltip("What method of movement toward our desired rotation should we use?")]
MoveType rotationType;
public MoveType RotationType { get { return rotationType; } set { rotationType = value; } }
[SerializeField, Tooltip("How quickly do we move toward our relative follow transform rotation? (Does nothhin when Rotation Type is set to Direct)")]
float rotationSpeed = 10f;
public float RotationSpeed { get { return rotationSpeed; } set { rotationSpeed = value; } }
[SerializeField, Tooltip("Should we follow the Follow Transform's X Rotation")]
bool followXRotation = false;
[SerializeField, Tooltip("Should we follow the Follow Transform's Y Rotation")]
bool followYRotation = false;
[SerializeField, Tooltip("Should we follow the Follow Transform's Z Rotation")]
bool followZRotation = false;
[SerializeField, Tooltip("How quickly can we zoom in and out?")]
float zoomSpeed = 10f;
public float ZoomSpeed { get { return zoomSpeed; } set { zoomSpeed = value; } }
[SerializeField, Tooltip("What is the min/max amount of our zoom?")]
Vector2 zoomRange = new Vector2(10f, 100f);
public Vector2 ZoomRange { get { return zoomRange; } set { zoomRange = value; } }
/// <summary>
/// Our desired position, relative to the follow transform
/// </summary>
public Vector3 RelativeToFollow { get; set; }
/// <summary>
/// Our World space desired position
/// </summary>
public Vector3 DesiredPosition {
get {
return FollowTransform.position + FollowedRotation * RelativeToFollow;
}
}
/// <summary>
/// What segment of the FollowTransform's rotation are we actually using?
/// </summary>
public Quaternion FollowedRotation {
get {
Vector3 relativeRotation = Vector3.zero;
if (followXRotation)
relativeRotation.x = FollowTransform.eulerAngles.x;
if (followYRotation)
relativeRotation.y = FollowTransform.eulerAngles.y;
if (followZRotation)
relativeRotation.z = FollowTransform.eulerAngles.z;
return Quaternion.Euler(relativeRotation);
}
}
public Quaternion DesiredRotation {
get {
Vector3 desiredRotation = transform.eulerAngles;
if (followXRotation)
desiredRotation.x = FollowTransform.eulerAngles.x;
if (followYRotation)
desiredRotation.y = FollowTransform.eulerAngles.y;
if (followZRotation)
desiredRotation.z = FollowTransform.eulerAngles.z;
return Quaternion.Euler(desiredRotation);
}
}
void Awake()
{
RelativeToFollow = transform.position - FollowTransform.position;
}
void Update()
{
Follow(Time.deltaTime);
if (Input.GetAxis("Mouse ScrollWheel") > 0)
ZoomIn();
if (Input.GetAxis("Mouse ScrollWheel") < 0)
ZoomOut();
}
public void ZoomIn() { ModifyZoom(-ZoomSpeed); }
public void ZoomOut() { ModifyZoom(ZoomSpeed); }
public void ModifyZoom(float amount)
{
if (Cam.orthographic)
Cam.orthographicSize = Mathf.Clamp(Cam.orthographicSize + amount * Time.deltaTime, ZoomRange.x, ZoomRange.y);
else
Cam.fieldOfView = Mathf.Clamp(Cam.fieldOfView + amount * Time.deltaTime, ZoomRange.x, ZoomRange.y);
}
void Follow(float deltaTime)
{
if (MovementType == MoveType.Direct)
transform.position = DesiredPosition;
else if (MovementType == MoveType.Lerp)
transform.position = Vector3.Lerp(transform.position, DesiredPosition, MoveSpeed * deltaTime);
else if (MovementType == MoveType.MoveTowards)
transform.position = Vector3.MoveTowards(transform.position, DesiredPosition, MoveSpeed * deltaTime);
if (RotationType == MoveType.Direct)
transform.rotation = DesiredRotation;
else if (RotationType == MoveType.Lerp)
transform.rotation = Quaternion.Lerp(transform.rotation, DesiredRotation, RotationSpeed * deltaTime);
else if (RotationType == MoveType.MoveTowards)
transform.rotation = Quaternion.RotateTowards(transform.rotation, DesiredRotation, RotationSpeed * deltaTime);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment