Galaxy Shooter 2D — Camera Shake

Adding impact and intensity to damage reactions!

Pablo Gómez Platón
Nerd For Tech

--

Camera Shake has been constantly used in videogames to add feel to games, intensifying certain actions and increasing immersion. It’s a chaotic detail, but a subtle one that improves the player’s experience (when it is not overused or mishandled).

I have used Camera Shake when the player gets hit, along with the damage VFX to increase intensity.

Setup

To shake the camera, I’ll need to modify the camera’s transform position, but doing so will prevent me from moving it (it would constantly override the position of the camera back to the values of the shake).

To fix this, the Camera will be a child GameObject of an Empty GameObject which I named CameraContainer where the shake will occur. That way, the camera will be able to move freely, and also keep the shake from the parent GameObject.

Shaking

To properly shake the camera, I will need at least two variables or values: the random direction to shake the camera, and the intensity of that shake.

To displace the camera randomly in any direction, I first used Random.Range to return a random value between -1 and 1.

The problem with this approach is that the movement is not smooth. At higher values, this can easily be noticed and it’s chaotic and a bit unpleasant.

Smoothly Shaking

Unity API: Mathf.PerlinNoise

With the use of Perlin Noise, it can generate a random value that maintains continuity, and it’s perfect for what I am trying to achieve: smooth shaking.

PerlinNoise takes in two parameters: a X and Y values. What it does is that it generates a 2D Perlin Noise texture, looks for the greyscale value at the given coordinates, and returns that value, ranging between 0 and 1 (pure black, all shades of grey, and pure white).

I’ll use the X parameter to set a “random” fixed seed, and the Y parameter to move through that texture continually using Time.time. It’s very important to set a different X value between the axis, or the entire movement will be synchronized in the same direction.

Also, that value range is not ideal because that means it won’t move towards the negative side of an axis. To fix that, we multiply the value of the PerlinNoise by 2, and then subtract by 1 to transform it into -1…1.
This is what happens if we set the same X value in the X, Y, Z Perlin Noise

This is much better, but the movement is rather slow, and it’s due to the Y parameter (Time.time) scrolling too slow. Adding a new variable “shakeFrequency” and multiplying it to the Y parameter will solve that.

Frequency is set to 8. Doesn’t this feel much better?

More Improvements

This article has been a bit lenghty, so, I’ll leave it here with a list of other improvements I made (and you can also make):

  • The script can also shake the rotation of the camera.
  • Switched from Update to a Coroutine, to avoid executing the code every frame.
  • Set a max amount of translation / rotation to avoid excessive camera shake.
  • Added trauma, and trauma falloff (this is the quantity of camera shake in a range between 0 and 1).
  • Smoothed even more the shake by modifying the trauma value through an AnimationCurve.

--

--