Add Camera Shake to Your Games with This Script

Keep in mind, the player has a total of 3 health. We do not want the camera to shake when the player loses their last health because it will look very strange when the Game Over screen appears.

First, let’s create a script called CameraShake. At the top, create 2 serialized fields: one called magnitude which is set to 0.05 and the other is time which is set to 0.5. Then create a Vector3 initialPos to keep track of the initial position of the camera. The last instance field will be a Camera called mainCamera.

Then at Start(), we set mainCamera to be the Camera component on the object this script is on which will be the Main Camera.

using UnityEngine;

public class CameraShake : MonoBehaviour {
    [SerializeField] private float magnitude = 0.05f;
    [SerializeField] private float time = 0.5f;

    private Vector3 initialPos;
    private Camera mainCamera;

void Start() {
    mainCamera = GetComponent<Camera>();
}

Go into Unity and drag the CameraShake script onto your Main Camera.

Next, write StartCameraShake() where we create 2 local floats called offsetX and offsetY. Each is set to a random value which is multiplied by the magnitude, then multiplied by 2 and finally subtracted by the magnitude.

Write a local Vector3 offsetPos and set it to the mainCamera’s position. Then we’ll take offsetX and add it to the offsetPos’s x value. We’ll do the same for offsetY and offsetPos’s y value. Finally, we set the mainCamera’s position to the offsetPos.

We will be utilizing the Invoke methods built into MonoBehaviour which work similar to Coroutines. The Invoke methods are simple to use but the downside is you have to refer to the method as a string parameter. This opens the floor to possible errors if you type the method wrong. Also, if you wanted to change the name of the method you invoked, it will not update when using F2 to rename all instances of that method because it’s a string.

Invoke methods can be useful and it’s important to know they exist. We will share how to do this with Coroutines as well.

Create StopCameraShake() where we simply call CancelInvoke which will stop the StartCameraShake(). Lastly, set the mainCamera’s position to the initialPos.

void StartCameraShake() {
        float offsetX = Random.value * magnitude * 2 - magnitude;
        float offsetY = Random.value * magnitude * 2 - magnitude;
        Vector3 offsetPos = mainCamera.transform.position;
        offsetPos.x += offsetX;
        offsetPos.y += offsetY;
        mainCamera.transform.position = offsetPos;
    }

    void StopCameraShake() {
        CancelInvoke("StartCameraShake");
        mainCamera.transform.position = initialPos;
    }

The final piece we’ll add to CameraShake is the Shake method. Set initalPos to the mainCamera’s position. Call InvokeRepeating which “invokes the method in time seconds, then repeatedly every repeatRate seconds.” So we will invoke “StartCameraShake” immediately and then every 0.005 seconds so it’s fast enough to give a very fast shaking motion effect.

We then call Invoke to “invoke the method in time seconds.” So we’ll invoke StopCameraShake after a half of a second.

public void Shake() {
    initialPos = mainCamera.transform.position;
    InvokeRepeating("StartCameraShake", 0f, 0.005f);
    Invoke("StopCameraShake", time);
}

 

If you would like to use a Coroutine instead of the Invoke methods, let’s go back to where we have this much code written in CameraShake:

using UnityEngine;

public class CameraShake : MonoBehaviour {
    [SerializeField] private float magnitude = 0.05f;
    [SerializeField] private float time = 0.5f;

    private Vector3 initialPos;
    private Camera mainCamera;

void Start() {
    mainCamera = GetComponent<Camera>();
}

Change the time variable at the top of your script to duration without manually initalizing it. Append a Coroutine called CameraShakeCoroutine and set duration to Time.time and add 0.5f to it to timestamp the game time with a half second “duration”.

Write all the same logic as was in StartCameraShake() before. So now we have this much so far:

using System.Collections;
using UnityEngine;

public class CameraShake : MonoBehaviour {

    [SerializeField] private float magnitude = 0.05f;
    [SerializeField] private float duration;

    private Vector3 initialPos;
    private Camera mainCamera;

    private void Start() {
        mainCamera = GetComponent<Camera>();
    }

    private IEnumerator CameraShakeCoroutine() {
        duration = Time.time + 0.5f;
        while (Time.time < duration) {
            float offsetX = Random.value * magnitude * 2 - magnitude;
            float offsetY = Random.value * magnitude * 2 - magnitude;
            Vector3 offsetPos = mainCamera.transform.position;
            offsetPos.x += offsetX;
            offsetPos.y += offsetY;
            mainCamera.transform.position = offsetPos;
            //need a yield statement
        }
        //need to set the mainCamera to the initialPos here
    }
}

Where we need to add a yield statement, write yield return new WaitForSeconds(0.005f);. Then right after the while loop, set the mainCamera’s position to the initialPos by typing mainCamera.transform.position = initialPos;.

The final bit is to write the Shake method. All it needs is to set the initialPos to the mainCamera’s position. Lastly, call StartCoroutine to start running CameraShakeCoroutine().

The final part for us to work on is to now open wherever you manage your player’s health. For us, it’s in the HealthEntity class.

Simply add an instance of CameraShake at the top and then when the player gets damaged, run an if statement for when health is 2 or 3, call cameraShake.Shake();.

public class HealthEntity : MonoBehaviour {
    [SerializeField] private CameraShake cameraShake;

    //code

    private void Damage() {
        if (health == maxHealth || health == 2)
            cameraShake.Shake();
        //code and end of script below

Drag in the Main Camera into the Camera Shake field we created under the Player Health Entity component.

The camera shake works as intended!


#game #gaming #script 
 

Add Camera Shake to Your Games with This Script
1.05 GEEK