Skip to content

Instantly share code, notes, and snippets.

@ashblue
Created July 4, 2015 23:17
Show Gist options
  • Save ashblue/bc7bdbad245d58b45aa0 to your computer and use it in GitHub Desktop.
Save ashblue/bc7bdbad245d58b45aa0 to your computer and use it in GitHub Desktop.
Camera 2D follow
using UnityEngine;
using System.Collections;
namespace Adnc.Cam {
public class Camera2DFollow : MonoBehaviour {
Vector3 currentVelocity; // Velocity used for damping camera movement
[Tooltip("Draws debug lines representing the camera's move logic (easing only)")]
[SerializeField] bool debug;
[Tooltip("Creates drag when moving to a new camera point. Increasing the value results in more drag.")]
[SerializeField] float damping = 0.25f;
[Tooltip("Maximum look ahead distance (how far the camera will push in front of the player when moving forward). Allows the player to look forward when moving forward.")]
[SerializeField] float lookAheadMax = 4.5f;
[Tooltip("How much force to apply when the camera pushes ahead of the player")]
[SerializeField] float lookAheadForce = 0.05f;
[Tooltip("When the character moves past this box, the camera will begin panning forward")]
[SerializeField] float boundaryWidth = 1.8f;
public void Stop () {
StopAllCoroutines();
}
public void SetTargetLock (Transform target) {
StopAllCoroutines();
StartCoroutine(FollowTargetLock(target));
}
IEnumerator FollowTargetLock (Transform target) {
while (target != null) {
Sm.camera.newPos = CameraHelper.ForceZAxis(target.position);
yield return null;
}
}
public void SetTargetEase (Transform target) {
StopAllCoroutines();
transform.position = target.position;
StartCoroutine(FollowTargetEase(target));
}
// @TODO Consider this. The screen locations for the boxes need to be scaled based on the camera size.
// All box sizes should be -1 to 1. With 0 being dead center and 1 being the far left or right side
IEnumerator FollowTargetEase (Transform target) {
Vector3 lookAheadDist = Vector3.zero;
Vector3 targetPos = CameraHelper.ForceZAxis(target.position);
Sm.camera.newPos = transform.position;
Color innerColor = Color.yellow;
float boxPush;
bool touchLeftInner;
bool touchRightInner;
Vector3 targetPrevPos = transform.position;
Vector3 boxInnerPos = targetPos;
// Reset current velocity since it may have an inherited value from the last time the camera was used
currentVelocity = Vector3.zero;
while (target != null) {
touchLeftInner = target.position.x < boxInnerPos.x - (boundaryWidth / 2f);
touchRightInner = target.position.x > boxInnerPos.x + (boundaryWidth / 2f);
boxInnerPos.y = target.position.y;
if ((touchLeftInner || touchRightInner) && target.position != targetPrevPos) {
// Push the inner box
boxPush = Mathf.Abs(target.position.x - targetPrevPos.x);
boxInnerPos.x += touchRightInner ? boxPush : -boxPush;
// The inner box was pushed, so we should snap the camera to it
targetPos.x = boxInnerPos.x;
// Since the camera was pushed, accumulate offset in the appropriate direction
lookAheadDist.x += touchLeftInner ? -lookAheadForce : lookAheadForce;
lookAheadDist.x = Mathf.Clamp(lookAheadDist.x, (boundaryWidth + lookAheadMax) / -2f, (boundaryWidth + lookAheadMax) / 2f);
}
// Draw debug lines
if (debug) {
innerColor = touchLeftInner || touchRightInner ? Color.red : Color.yellow;
DebugExt.DrawSides(boxInnerPos, boundaryWidth, 3f, innerColor);
DebugExt.DrawSides(target.position, lookAheadMax, 3f, Color.magenta);
DebugExt.DrawCrosshair(targetPos, 0.2f, Color.yellow);
DebugExt.DrawCrosshair(targetPos + lookAheadDist, 0.2f, Color.magenta);
}
// Always attempt to match the player's y axis position
targetPos.y = target.position.y;
// Move to the new position with a slight drag
Sm.camera.newPos = Vector3.SmoothDamp(Sm.camera.newPos, CameraHelper.ForceZAxis(targetPos + lookAheadDist), ref currentVelocity, damping);
// Track the target's old position
targetPrevPos = target.position;
yield return null;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment