Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple camera shake effect for Unity3d, written in C#. Attach to your camera GameObject. To shake the camera, set shakeDuration to the number of seconds it should shake for. It will start shaking if it is enabled.
using UnityEngine;
using System.Collections;
public class CameraShake : MonoBehaviour
{
// Transform of the camera to shake. Grabs the gameObject's transform
// if null.
public Transform camTransform;
// How long the object should shake for.
public float shakeDuration = 0f;
// Amplitude of the shake. A larger value shakes the camera harder.
public float shakeAmount = 0.7f;
public float decreaseFactor = 1.0f;
Vector3 originalPos;
void Awake()
{
if (camTransform == null)
{
camTransform = GetComponent(typeof(Transform)) as Transform;
}
}
void OnEnable()
{
originalPos = camTransform.localPosition;
}
void Update()
{
if (shakeDuration > 0)
{
camTransform.localPosition = originalPos + Random.insideUnitSphere * shakeAmount;
shakeDuration -= Time.deltaTime * decreaseFactor;
}
else
{
shakeDuration = 0f;
camTransform.localPosition = originalPos;
}
}
}
@nicotroia
Copy link

nicotroia commented Aug 7, 2016

Thanks @ixikos. I expanded on your script to calculate a delta time so the shake duration is retained even when the game gets paused (and Time.deltaTime stops).

`using UnityEngine;
using System.Collections;

public class CameraShake : MonoBehaviour {

public static CameraShake instance;

private Vector3 _originalPos;
private float _timeAtCurrentFrame;
private float _timeAtLastFrame;
private float _fakeDelta;

void Awake()
{
    instance = this;
}

void Update() {
    // Calculate a fake delta time, so we can Shake while game is paused.
    _timeAtCurrentFrame = Time.realtimeSinceStartup;
    _fakeDelta = _timeAtCurrentFrame - _timeAtLastFrame;
    _timeAtLastFrame = _timeAtCurrentFrame; 
}

public static void Shake (float duration, float amount) {
    instance._originalPos = instance.gameObject.transform.localPosition;
    instance.StopAllCoroutines();
    instance.StartCoroutine(instance.cShake(duration, amount));
}

public IEnumerator cShake (float duration, float amount) {
    float endTime = Time.time + duration;

    while (duration > 0) {
        transform.localPosition = _originalPos + Random.insideUnitSphere * amount;

        duration -= _fakeDelta;

        yield return null;
    }

    transform.localPosition = _originalPos;
}

}
`

And of course, call it from anywhere by
CameraShake.Shake(0.25f, 4f);

@26PM
Copy link

26PM commented Sep 2, 2016

Thank you! I am using your script and controlling the camera shake amount over time by keyframing the Shake Amount value in an animation ( for my game Forgotten Passages) Thanks again!

@makdesign
Copy link

makdesign commented Sep 2, 2016

thanks very much, will use it today...also if u can pls recommend someone who can create an animation for a small 3 room building collapsing...i have the googleSketchUp file for the building, just need someone to show it disintegrating and collapsing...i need this urgently 1-2 days....[ready to pay via paypal if the amount is within my student/economy budget]...i need this for a research experiment in which we are exploring if we can convince disadvantaged communities living in seismic zones to build safer buildings using affordable technologies...thnx!

@finefin
Copy link

finefin commented Nov 3, 2016

thanks, works pretty good. the only change I did was to also decrease the shake amount over time. So it shakes strong in the beginning and doesn't shake (that much) in the end. In that way the animation looks way more natural.

if (shakeDuration > 0) {
gameObject.transform.localPosition = originalPos + Random.insideUnitSphere * shakeAmount;
shakeDuration -= Time.deltaTime * decreaseFactor;
shakeAmount -= Time.deltaTime * decreaseFactor;
if (shakeAmount <= 0) shakeAmount = 0;
} else {
shakeDuration = 0f;
gameObject.transform.localPosition = originalPos;
}

Like the position you have to store the original shake amount in the beginning and reset it when the shaking is done or restarted.

@eugis
Copy link

eugis commented Nov 7, 2016

Thanks! It helps a lot!

@yasinjavaid
Copy link

yasinjavaid commented Apr 18, 2017

thanks it helps me too thumbs up for .cs

@NickPax
Copy link

NickPax commented May 4, 2017

@nicotroia - thanks! Nice one.

@PabloSaitua
Copy link

PabloSaitua commented Jun 6, 2017

Great camera shakes, this is just what I am looking for.
I am still a noob in programming.
Is there a way to enable this script on collision?
Does somebody already have a script to do this?
I am using a fps.
Any help is welcome.
Thanks.

@pravinbudharap
Copy link

pravinbudharap commented Jun 9, 2017

create camerashake.cs file in your project and add the below code in the script then after you can attach this script to the camera object.

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

public class CameraShake : MonoBehaviour {

// Transform of the camera to shake. Grabs the gameObject's transform
// if null.
public Transform camTransform;

// How long the object should shake for.
public float shakeDuration = 0f;

// Amplitude of the shake. A larger value shakes the camera harder.
public float shakeAmount = 0.7f;
public float decreaseFactor = 1.0f;

public bool shaketrue= false;

Vector3 originalPos;

void Awake()
{
	if (camTransform == null)
	{
		camTransform = GetComponent(typeof(Transform)) as Transform;
	}
}

void OnEnable()
{
	originalPos = camTransform.localPosition;
}

void Update()
{
	if (shaketrue) 
	{
		if (shakeDuration > 0) {
			camTransform.localPosition = originalPos + Random.insideUnitSphere * shakeAmount;

			shakeDuration -= Time.deltaTime * decreaseFactor;
		} else {
			shakeDuration = 1f;
			camTransform.localPosition = originalPos;
			shaketrue = false;
		}
	}
}

public void shakecamera()
{
	shaketrue = true;
}

}

after that you can create button and on button click event you can call the shakecamera() public function so camera is shaking on button click you simply call this function ontriggerenter also to shake the camera.
i hope that it is helpful for developers.

@WILEz75
Copy link

WILEz75 commented Sep 4, 2017

For a smooth movement, change

camTransform.localPosition = originalPos + Random.insideUnitSphere * shakeAmount;

with

camTransform.localPosition = Vector3.Lerp(camTransform.localPosition,originalPos + Random.insideUnitSphere * shakeAmount,Time.deltaTime * 3);

@WILEz75
Copy link

WILEz75 commented Sep 4, 2017

but... if you use this line:
shakeDuration = 1f;
to reset the shake duration, after the first shake, it return always to 1.
public float shakeDuration = 0f; becomes useless.
You have to save the original shakeDuration:

`

using UnityEngine;
using System.Collections;

public class CameraShake : MonoBehaviour
{

// Transform of the camera to shake. Grabs the gameObject's transform
// if null.
public Transform camTransform;

// How long the object should shake for.
public float shakeDuration = 0f;

// Amplitude of the shake. A larger value shakes the camera harder.
public float shakeAmount = 0.7f;
public float decreaseFactor = 1.0f;

public bool shaketrue = false;

Vector3 originalPos;
float originalShakeDuration; //<--add this

void Awake()
{
    if (camTransform == null)
    {
        camTransform = GetComponent(typeof(Transform)) as Transform;
    }
}

void OnEnable()
{
    originalPos = camTransform.localPosition;
    originalShakeDuration = shakeDuration; //<--add this
}

void Update()
{
    if (shaketrue)
    {
        if (shakeDuration > 0)
        {
            camTransform.localPosition = Vector3.Lerp(camTransform.localPosition,originalPos + Random.insideUnitSphere * shakeAmount,Time.deltaTime * 3);

            shakeDuration -= Time.deltaTime * decreaseFactor;
        }
        else
        {
            shakeDuration = originalShakeDuration; //<--add this
            camTransform.localPosition = originalPos;
            shaketrue = false;
        }
    }
}

public void shakecamera()
{
    shaketrue = true;
}

}
`

and, if you want call a shake with different parameters, add this function:

    public void shakecamera(float _shakeDuration, float _shakeAmount)
    {
        shaketrue = true;
        shakeDuration = _shakeDuration;
        shakeAmount = _shakeAmount;
    }

@Totoual
Copy link

Totoual commented Nov 9, 2017

Thank you man. It was exactly what I was looking for :)

@RishabhRyber
Copy link

RishabhRyber commented Feb 5, 2018

Thanks man, this helped me a lot. Thanks again.

@Jaemins
Copy link

Jaemins commented Mar 11, 2018

Thank you , It helped a lot.
But I wonder why this is necessary

camTransform = GetComponent(typeof(Transform)) as Transform;

can you answer me ?

@Tanz0rz
Copy link

Tanz0rz commented Apr 1, 2018

Good starter code! I modified this and was off to the races in about 15 minutes

@victor-guillermo
Copy link

victor-guillermo commented May 2, 2018

Dear User FTVS,

I am currently working with a team of college students to make a video game for our senior thesis. We intend to ship this project onto steam and there is a possibility it will be released onto Xbox One.

For this project, we need a camera shake script and the script you made is perfect for our game.

Would it be possible for us to use your script for our game?

@GustavoBernardi
Copy link

GustavoBernardi commented May 15, 2018

Nice! Now how can I control the speed of the shake?

@AndySum
Copy link

AndySum commented Jul 4, 2018

Amazing thanks!

@Ztuu
Copy link

Ztuu commented Feb 24, 2019

Thanks for this!

@rootste000
Copy link

rootste000 commented Mar 5, 2019

This worked great for a stationary camera. The only issue that I have is that I made an on-rails shooter and my camera is keyframed to a timeline so the shake will not override that. Any idea how to make it work with the camera being on a timeline?

@rivax95
Copy link

rivax95 commented Apr 17, 2019

Thanks !

@stickylabdev
Copy link

stickylabdev commented Aug 15, 2019

doesnot work at all

@krupasknr
Copy link

krupasknr commented Dec 7, 2019

thanks,.. so simple

@hergaiety
Copy link

hergaiety commented May 23, 2020

Good stuff!

@sauravrao637
Copy link

sauravrao637 commented Jun 6, 2020

Thanks @ixikos. I expanded on your script to calculate a delta time so the shake duration is retained even when the game gets paused (and Time.deltaTime stops).

using UnityEngine;
using System.Collections;

public class CameraShake : MonoBehaviour {
    public static CameraShake instance;

    private Vector3 _originalPos;
    private float _timeAtCurrentFrame;
    private float _timeAtLastFrame;
    private float _fakeDelta;

    void Awake() {
        instance = this;
    }

    void Update() {
        // Calculate a fake delta time, so we can Shake while game is paused.
        _timeAtCurrentFrame = Time.realtimeSinceStartup;
        _fakeDelta = _timeAtCurrentFrame - _timeAtLastFrame;
        _timeAtLastFrame = _timeAtCurrentFrame; 
    }

    public static void Shake (float duration, float amount) {
        instance._originalPos = instance.gameObject.transform.localPosition;
        instance.StopAllCoroutines();
        instance.StartCoroutine(instance.cShake(duration, amount));
    }

    public IEnumerator cShake (float duration, float amount) {
        float endTime = Time.time + duration;

        while (duration > 0) {
            transform.localPosition = _originalPos + Random.insideUnitSphere * amount;

            duration -= _fakeDelta;

            yield return null;
        }

        transform.localPosition = _originalPos;
    }
}

And of course, call it from anywhere by
CameraShake.Shake(0.25f, 4f);

@sauravrao637
Copy link

sauravrao637 commented Jun 6, 2020

Thanks :)

@Ultroman
Copy link

Ultroman commented Feb 17, 2021

Thanks @ixikos. I expanded on your script to calculate a delta time so the shake duration is retained even when the game gets paused (and Time.deltaTime stops).

Couldn't you just have replaced Time.deltaTime with Time.unscaledDeltaTime and had the same functionality?

@krlosrokr
Copy link

krlosrokr commented Apr 2, 2021

Thanks man!

@stewheart123
Copy link

stewheart123 commented Jun 30, 2021

really freaking cool! modified it to run whenever an in-game explosion happens. Added tonnes of feeling to my project!

@Radall
Copy link

Radall commented Jan 12, 2022

Thank you! I put your script in a small Coroutine. Makes my prototypes instantly more fun!

    // used fields
    private Camera mainCamera;
    [SerializeField] private float cameraShakeDuration = 0.5f;
    [SerializeField] private float cameraShakeDecreaseFactor = 1f;
    [SerializeField] private float cameraShakeAmount = 1f;
    // coroutine
    IEnumerator ShakeCamera()
    {
        var originalPos = mainCamera.transform.localPosition;
        var duration = cameraShakeDuration;
        while(duration > 0)
        {
            mainCamera.transform.localPosition = originalPos + Random.insideUnitSphere * cameraShakeAmount;
            duration -= Time.deltaTime * cameraShakeDecreaseFactor;
            yield return null;
        }
        mainCamera.transform.localPosition = originalPos;
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment