Camera shake effect with Rigid Body physics in Unity Game Engine

A great way to add some juice or "oomph" to your game is to add a camera shake. It's a great way of emphasizing some kind of action or any explosion creating a small but satisfying form of feedback that can create a difference between an engaging or addictive game and a boring or static game.

When used correctly it can provide the player with some of the most engaging game feel with very little effort. But when used incorrectly it can make the player nauseous and irritated making them turn it off completely.

In this blog, we will be focussing on making the camera shake effect using rigid body physics in the Unity game engine.

So the idea revolves around adding a spring joint to the Main Camera in the scene and giving the Main Camera some force in a random direction so it can oscillate and its energy decays after some time.

Let's first set up our scene. Create a new 2d project in unity Hub. Let's name it "Example Scene".

Now create an empty game object. Name it "Camera Container". Put the "MainCamera" as a child of the "Camera Container". Now attach a springjoint2d component on the "MainCamera" by clicking on add component button in the Inspector panel. Doing this would automatically attach a rigidBody2d to the main camera as well. Now attach a rigidbody2d on the "Camera Container" as well. Make sure you turn off the gravity in both the rigidbody2d components otherwise both of them would just fall when we press the play button.

Now, all we need to do is to add some force in a random direction on the "Main Camera" so that it can oscillate. For that make a new C# script and name it "Camera_Shake". You can name it anything you like, it's up to you.

Now, use the following code in the script:

using System.Collections;
using UnityEngine;

public class Camera_Shake : MonoBehaviour
{
    public static Camera_Shake instance;
    private void Awake() {
        if(instance!=null){
            Destroy(gameObject);
        }
        else{
            instance = this;
            DontDestroyOnLoad(instance);
        }
    }
    SpringJoint2D shake_joint;
    private void Start()
    {
        shakeJoint = gameObject.GetComponent<SpringJoint2D>();//taking the spring joint on the camera object
    }
    public IEnumerator Shake(float magnitude)
    {
        float x = Random.Range(-0.1f, 0.1f) * magnitude;
        float y = Random.Range(-0.1f, 0.1f) * magnitude;

        gameObject.GetComponent<Rigidbody2D>().AddForce(new Vector2(x, y), ForceMode2D.Impulse); // adding force on the Main Camera

        shake_joint.distance = 0;//this is done so that the camera object can return to its original position
        yield return 0;

    }
}

Let's look at the code in a bit more depth.

We have used a very common design/programming pattern here known as the singleton design pattern.

What is a Singleton Design Pattern??

In simple words, it is a globally accessible class that exists in the scene but only once. The purpose of using singleton is to easily connect multiple objects in the scene. We can't discuss the singletons in too much detail over here. You can read this blog to learn about singletons in much more detail. If you are not much of a reader kind of person here is a youtube tutorial on singletons.

Moving forward, we have declared a SpringJoint2d type of variable named "shake_joint". In the start method, we have assigned the SpringJoint2d component (attached on Main Camera) to "shake_joint".

Now, In the coroutine, we have two random values (x,y) between the same ranges. Next, we have given a force to the Main Camera by accessing the rigidbody2d attached to it. Next "shake_joint.distance" is set to 0 to ensure the camera reaches back to its original position. If you don't know what coroutines are you can go through this blog to get a basic understanding of coroutines.

Alright, we are almost done. We just need a way to test whatever we have made till now.

For that let's make another empty gameObject and name it "Testing Object". Now make another C# script and name it "Testing". Now write the following in that script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Testing : MonoBehaviour
{
    public float magnitude; // set this in inspector
    void Update()
    {
        if(Input.GetMouseButtonDown(0)){
            StartCoroutine(Camera_Shake.instance.Shake(magnitude));
        }
    }
}

Here, at first, we have declared a variable "magnitude" which will be set in the inspector. In the update method, we take a mouse click as our input ( such that on clicking once camera shake will occur). Inside the if statement the coroutine(made in the Camera_Shake script) is called and magnitude is set as the argument. Add this script to the "Testing Object" gameObject and set the magnitude to 100 ( This value is experimental. You can change this according to your needs).

Now go back to the Unity scene and add a fixedJoint component on "Camera Container". This is to make sure that the parent object remains fixed in its position. (Although you should try out the effect without adding the fixedJoint component to see how the system behaves).

Now to observe the camera shake effect add some random sprites and 2D objects in the scene with different colors. Now press the play button and click on the left mouse button to see your effect. You can observe that camera does shake but doesn't stop even after a long time. This is because the energy of the spring joint is not decaying and it's going to oscillate forever. There is no resistive force to stop the oscillation.

So to stop the oscillation we will have to increase the linear drag and angular drag of the RigidBody component on "MainCamera". Set the linear drag to 15 and the angular drag to 10 (This value is obtained via hit and trial, You can adjust your values according to your game). Now on the SpringJoint component increase the frequency to 100. This would make the oscillations faster. Now press play and press the left mouse button to test the shake effect. You can see that the screen shake effect works !!! You can always tweak the values according to the game you are making.

So this was a quick guide on making the screen shake effect. I hope you learned something new and informative. Happy developing !!!