Menu
CoddyTech

Camera Shake

Part of the Physics and Gameplay section of Coddy's Unity journey. Lesson 50 of 71.

A shake is a short run of random offsets: for a few tenths of a second the camera sits at a random spot near its rest position, a new one on every frame, and then it goes back. A coroutine fits, because it runs over several frames and ends by itself. This camera shakes when a boulder lands (another script calls BoulderLanded(); the file starts with using System.Collections; for IEnumerator):

public float strength = 0.2f;
public float duration = 0.4f;
Vector3 rest;

void Start()
{
    rest = transform.localPosition;
}

public void BoulderLanded()
{
    StartCoroutine(Shake());
}

IEnumerator Shake()
{
    float elapsed = 0f;
    while (elapsed < duration)
    {
        transform.localPosition = rest + Random.insideUnitSphere * strength;
        elapsed += Time.deltaTime;
        yield return null;
    }
    transform.localPosition = rest;
}

Random.insideUnitSphere * strength is a random offset up to strength long in any direction, and yield return null picks a new one on the next frame. Adding Time.deltaTime each pass counts real seconds, so the shake lasts duration at any frame rate. The last line puts the camera back; without it, the camera stays wherever the last offset left it.

On each frame Unity runs every Update(), then the coroutines waiting on yield return null, then every LateUpdate(). So a follow camera that sets its position in LateUpdate() overwrites whatever the shake did. Shaking localPosition avoids that when the camera is the child of an empty object that does the following: the parent moves, and the camera shakes around its spot under it.

challenge icon

Challenge

Medium

Give the following camera a shake on Space.

  1. Add a field Vector3 shake;, and in LateUpdate() set transform.position = player.position + offset + shake;.
  2. In Shake(), while elapsed < duration: shake = Random.insideUnitSphere * strength;, add Time.deltaTime to elapsed, yield return null;.
  3. After the loop, set shake = Vector3.zero;.

Press Play, run and press Space: the view shakes as it follows. Then Check.

Try it yourself

using System.Collections;
using UnityEngine;

public class ShakeFollow : MonoBehaviour
{
    public Transform player;
    public Vector3 offset = new Vector3(0, 4, -8);
    public float strength = 0.3f;
    public float duration = 0.4f;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartCoroutine(Shake());
        }
    }

    void LateUpdate()
    {
        transform.position = player.position + offset;
    }

    IEnumerator Shake()
    {
        // Shake the camera for duration seconds, up to strength from its follow position.
        yield return null;
    }
}

All lessons in Physics and Gameplay

Practice on your own: Unity playground