Indie-Game-Jam / Assets / Carter Games / Utilities / Misc / CameraShakeScript.cs
CameraShakeScript.cs
Raw
using System.Collections;
using UnityEngine;

/****************************************************************************************************************************
 * 
 *  --{   Carter Games Utilities Script   }--
 *							  
 *	Camera Shake Script
 *	    Adds the option to shake the standard unity camera, doesn't work on cinemachine cameras yet.
 *			
 *  Written by:
 *      Jonathan Carter
 *      E: jonathan@carter.games
 *      W: https://jonathan.carter.games
 *			        
 *	Last Updated: 18/12/2020 (d/m/y)						
 * 
****************************************************************************************************************************/

namespace CarterGames.Utilities
{
    /// <summary>
    /// Class | Camera Shake Script, make a camera shake effect.
    /// </summary>
    public class CameraShakeScript : MonoBehaviour
    {
        /// <summary>
        /// Float | Defines how long the camera should shake for.
        /// </summary>
        [Tooltip("The duration for the camera shake effect.")]
        [SerializeField] private float shakeDuration;

        /// <summary>
        /// Bool | Defines whether or not the camera should shake.
        /// </summary>
        [Tooltip("Should the camera be shaken.")]
        [SerializeField] private bool shouldCameraShake;

        /// <summary>
        /// Bool | Should the camera shake it 2d or 3d space?
        /// </summary>
        private bool is2D;

        /// <summary>
        /// Float | How much the camera should shake, is set to the force defined by the user in the Shake Camera Method.
        /// </summary>
        private float shakeAmount;

        /// <summary>
        /// Bool | Used to check if the camera starting position is saved before it is shaked.
        /// </summary>
        private bool isCameraPositionSaved;

        /// <summary>
        /// Bool | Used to check if the coroutine is running or not.
        /// </summary>
        private bool isCoRunning;

        /// <summary>
        /// Vector3 | Used to save the camera position before the shake effect is started, so it can be returned to its starting position.
        /// </summary>
        private Vector3 cameraPosition;

        /// <summary>
        /// GameObject | The camera to shake.
        /// </summary>
        private GameObject mainCamera;


        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Unity OnDisable | Stops all coroutines running on this script when disabled, stops any memory waste.
        /// </summary>
        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        private void OnDisable()
        {
            StopAllCoroutines();
        }


        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Unity Start | Assigns the camera variable to the object in the scene.
        /// </summary>
        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        private void Start()
        {
            mainCamera = gameObject;
        }


        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Unity Update | Checks to see if the camera shake should happen & starts the Coroutine that shakes the camera when called.
        /// </summary>
        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        private void Update()
        {
            if (shouldCameraShake && !is2D)
            {
                mainCamera.transform.localPosition += new Vector3(Random.insideUnitSphere.x * shakeAmount, Random.insideUnitSphere.y * shakeAmount, Random.insideUnitSphere.z * shakeAmount);
            }
            else if (shouldCameraShake && is2D)
            {
                mainCamera.transform.localPosition += new Vector3(Random.insideUnitSphere.x * shakeAmount, Random.insideUnitSphere.y * shakeAmount, mainCamera.transform.position.z);
            }

            if ((shouldCameraShake) && (!isCoRunning))
            {
                StartCoroutine(StopCameraShake());
            }
        }


        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Coroutine | Stops the camera shake effect after the set duration is completed.
        /// </summary>
        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        private IEnumerator StopCameraShake()
        {
            isCoRunning = true;
            yield return new WaitForSeconds(shakeDuration);
            shouldCameraShake = false;
            isCoRunning = false;
            transform.localPosition = cameraPosition;
            isCameraPositionSaved = false;
        }


        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Method | Runs the method will shake the camera with the defined values.
        /// </summary>
        /// <param name="shakeForce">the amount of force to apply. Default = 0.1f</param>
        /// <param name="shakeLenght">the duration for the effect. Default = 0.25f</param>
        /// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        public void ShakeCamera(bool should2D = false, float shakeForce = .1f, float shakeLenght = .25f)
        {
            // Only edited if inputted, otherwise defaulf values are entered
            is2D = should2D;
            shakeAmount = shakeForce;
            shakeDuration = shakeLenght;

            if (!isCameraPositionSaved)
            {
                cameraPosition = transform.localPosition;
                isCameraPositionSaved = true;
            }

            if (!isCoRunning)
            {
                shouldCameraShake = true;
            }
        }
    }
}