← Cheatsheets
Tags: unity, camera, cinemachine, follow, damping, orthographic, perspective, shake, game-dev
Last updated: 2026-06-27
Camera Systems Cheatsheet
Quick Reference
| Approach | Best For | Complexity |
| Scripted Follow | Simple 2D/3D follow camera | Low |
| Cinemachine | Production-quality cinematic cameras | Low–Medium |
| Multi-camera | Cutscenes, camera switching | Medium |
| Custom Physics | Smooth damping, collision avoidance | Medium |
Scripted Follow Camera
Smooth Follow (3D)
public Transform target;
public Vector3 offset = new(0, 5, -10);
public float smoothSpeed = 5f;
void LateUpdate() {
Vector3 targetPos = target.position + offset;
transform.position = Vector3.Lerp(
transform.position, targetPos, smoothSpeed * Time.deltaTime);
transform.LookAt(target);
}
2D Follow with Dead Zone
public Vector2 deadZone = new(1f, 0.5f);
public float smoothTime = 0.3f;
Vector3 velocity;
void LateUpdate() {
Vector3 delta = target.position - transform.position;
delta.z = 0;
if (Mathf.Abs(delta.x) > deadZone.x)
delta.x -= Mathf.Sign(delta.x) * deadZone.x;
else delta.x = 0;
if (Mathf.Abs(delta.y) > deadZone.y)
delta.y -= Mathf.Sign(delta.y) * deadZone.y;
else delta.y = 0;
transform.position = Vector3.SmoothDamp(
transform.position, transform.position + delta,
ref velocity, smoothTime);
}
Camera Bounds (Clamp to Level)
public Vector2 minBounds, maxBounds;
public float camHalfHeight, camHalfWidth;
void LateUpdate() {
Vector3 pos = target.position + offset;
pos.x = Mathf.Clamp(pos.x, minBounds.x + camHalfWidth,
maxBounds.x - camHalfWidth);
pos.y = Mathf.Clamp(pos.y, minBounds.y + camHalfHeight,
maxBounds.y - camHalfHeight);
transform.position = pos;
}
Cinemachine
Virtual Camera Types
| Camera | Use Case |
| Virtual Camera | Base camera with composer/lookat/follow |
| FreeLook | Orbital camera around target |
| Blend List | Sequenced camera cuts |
| State-Driven | Switches per Animator state |
| ClearShot | Auto-picks best view avoiding obstacles |
| Dolly | Track-based movement |
| 2D Camera | Orthographic 2D follow |
Follow & LookAt
CinemachineVirtualCamera vcam;
vcam.Follow = playerTransform;
vcam.LookAt = playerTransform;
var transposer = vcam.GetCinemachineComponent<CinemachineTransposer>();
transposer.m_FollowOffset = new Vector3(0, 5, -10);
var composer = vcam.GetCinemachineComponent<CinemachineComposer>();
composer.m_TrackedObjectOffset = Vector3.up * 1.5f;
Damping & Dead Zone
| Property | Description |
| X/Y/Z Damping | Smoothing per axis (0 = instant) |
| Dead Zone Width/Height | No movement within zone |
| Soft Zone Width/Height | Gradual movement beyond dead zone |
| Bias | How much to favour centre (0–1) |
| Lookahead Time | Anticipate movement direction |
| Lookahead Smoothing | How quickly lookahead adjusts |
Camera Shake (Cinemachine Impulse)
# Generate impulse
CinemachineImpulseManager.Instance.GenerateImpulse(
transform.position, direction, 0.5f, 0.2f);
CinemachineImpulseSource source = GetComponent<CinemachineImpulseSource>();
source.GenerateImpulse(direction * force);
# Listener on VCam
CinemachineImpulseListener listener;
listener.m_Gain = 1f;
listener.m_ChannelMask = ~0;
Camera Shake (Scripted)
public IEnumerator Shake(float duration, float magnitude) {
Vector3 originalPos = transform.localPosition;
float elapsed = 0f;
while (elapsed < duration) {
float x = Random.Range(-1f, 1f) * magnitude;
float y = Random.Range(-1f, 1f) * magnitude;
transform.localPosition = originalPos + new Vector3(x, y, 0);
elapsed += Time.deltaTime;
yield return null;
}
transform.localPosition = originalPos;
}
Shake Presets
| Type | Duration | Magnitude |
| Gunshot | 0.05s | 0.3 |
| Explosion | 0.3s | 2.0 |
| Footstep | 0.1s | 0.1 |
| Earthquake | 2.0s | 1.5 |
| Hit reaction | 0.15s | 0.5 |
Orthographic vs Perspective
| Aspect | Orthographic | Perspective |
| Depth perception | None | Realistic |
| Size consistency | Objects same size regardless of distance | Farther = smaller |
| Use case | 2D, isometric, strategy | 3D, FPS, TPS |
| Zoom | Adjust orthographic size | Adjust FOV or move camera |
Camera cam = GetComponent<Camera>();
cam.orthographic = true;
cam.orthographicSize = 5f;
cam.orthographic = false;
cam.fieldOfView = 60f;
Multi-Camera Setup
public Camera[] cameras;
int currentIndex = 0;
void SwitchCamera(int index) {
foreach (Camera cam in cameras) cam.enabled = false;
cameras[index].enabled = true;
currentIndex = index;
}
IEnumerator Cutscene() {
SwitchCamera(1); yield return new WaitForSeconds(3f);
SwitchCamera(2); yield return new WaitForSeconds(5f);
SwitchCamera(0);
}
Cinemachine Blend
CinemachineBrain brain = Camera.main.GetComponent<CinemachineBrain>();
brain.m_DefaultBlend.m_Style = CinemachineBlendDefinition.Style.EaseInOut;
brain.m_DefaultBlend.m_Time = 1.5f;