Camera Shake in Unity

Share on Facebook4Share on Reddit0Tweet about this on Twitter2Share on Google+0

After much Googleing for how to do a camera shaking effect in Unity, I decided to write my own small script to accomplish the effect. It combines both positional movement with rotational movement to simulate closely an actual camera shake.

The two key variables are:

shake_intensity

Shake_intensity determines the initial intensity of the shaking — how much variance to allow in the camera position.

shake_decay

Shake_decay controls is the amount that shake_intensity is decremented each update. It determines if the shake is long or short.

 

 

 

 

Unity Web Player. Install now!

 

 

 

JavaScript

C# (c# port by commenter georgeegonut. Thanks George!)

 

Share on Facebook4Share on Reddit0Tweet about this on Twitter2Share on Google+0
  • Sfsdf

    This is so cool! A really simple idea, that will get great results in-game, I’m sure. Nice one! And thanks for sharing your methods.

  • http://www.facebook.com/Zerox911 Chester Liew

     hi.. how to stop the camera from moving from its original position..??

    seems like when i pressed the “shake” button a lot of times.. the camera slowly moves while vibrating..

    is it possible to return the camera to its original place after vibrating..??
    and how to do that..

    thank you..

    • mdjasper

      Great question. I see what you mean. The reason that happens is that when you press shake it grabs the initial position and rotation to return it to when finished. However, when you press it quickly, the second press will grab what it thinks is the initial position – but in fact is the position midway through the first shake.

      The way to solve this is to remove the “grab the original position” bit, and always reset it to Vector3(0,0,0). Then put the camera inside another object as a child, and control the movement through the parent object.

      I will be updating the script and demo to reflect these changes.

      • http://www.facebook.com/Zerox911 Chester Liew

        where exactly is this “grab the original position” in the script that you have stated..??

        what i understood from you reply is..

        i have to somehow remove this “original position” variable to stop it from moving, resetting it in some kind of “function” and make my camera as a child to an empty gameobject to set the position.. am i correct..??

        one more request…

        where should i remove the “original position” and how do i reset the position..

        thank you

      • Aiden

        Might I suggest some sort of boolean check to see– when you press a/the shake button– if it’s already in the process of shaking, it skips (re)acquiring the initial position. Instead, it simply uses the one already defined in the first shake. Some properly scoped variable called “is_shaking” that is set to 1 when the function initiates, and 0 when the function has completed its duty. So if the function is called and the is_shaking variable is 0, it acquires the original position. If it’s 1, it does not, and simply uses values that were previously acquired. In this way, the camera shaking can be initiated at any axis/rotation, instead of having to rely on a pre-defined “Vector3(0,0,0)”

  • Daniel

    Thanks!!!

  • vasant

    Thank you, was looking for this for a while

  • andreadst

    Thank you for this! I’ve been using it in a small prototype and it works great :)

  • http://twitter.com/aerinonfire kumavis

    dat shake

  • georgeegonut

    I’ve converted this to C# if anyone has a use for it. Thanks for the code!

    using UnityEngine;

    using System.Collections;

    public class cameraShake : MonoBehaviour

    {

    private Vector3 originPosition;

    private Quaternion originRotation;

    public float shake_decay;

    public float shake_intensity;

    void OnGUI ()

    {

    if (GUI.Button (new Rect (20,40,80,20), “Shake”))

    {

    Shake ();

    }

    }

    void Update ()

    {

    if (shake_intensity > 0)

    {

    transform.position = originPosition + Random.insideUnitSphere * shake_intensity;

    transform.rotation = new Quaternion(

    originRotation.x + Random.Range (-shake_intensity,shake_intensity) * .2f,

    originRotation.y + Random.Range (-shake_intensity,shake_intensity) * .2f,

    originRotation.z + Random.Range (-shake_intensity,shake_intensity) * .2f,

    originRotation.w + Random.Range (-shake_intensity,shake_intensity) * .2f);

    shake_intensity -= shake_decay;

    }

    }

    void Shake()

    {

    originPosition = transform.position;

    originRotation = transform.rotation;

    shake_intensity = .3f;

    shake_decay = 0.002f;

    }

    }

    • mdjasper

      Thanks George! I’ve included this port in my post. Email mdjasper@gmail.com if you want me to link to your site or something from the mention.

  • http://pedroassuncao.com/ Pedro Assuncao

    Awesome, thanks for sharing :)

  • Guest

    Just a little typo in C3 version line 3 (at the end.)
    shake_intenity -> shake_intensity ( an ‘s’ is missing :) )

  • Alexandre Lake

    Just a little typo in C# version line 3 (at the end.)
    shake_intenity -> shake_intensity ( an ‘s’ is missing :) )

  • Alexandre Lake

    Just a little typo in C# version line 23 (at the end.)
    shake_intenity -> shake_intensity ( an ‘s’ is missing :) )

    ps: God I don’t know how to type this morning… Edited 3 times!!!

  • Brandon

    Thanks so much, Mike! I needed a continual shake, and I needed to apply it to a First Person Controller that was positioned on an animated platform. When I killed the decay, the shaking camera floated off into space, seemingly unaware that the position of the FPC had moved due to platform animation.

    By setting origin in the update, and basing it on the FPS position, not the camera position, everything seems to work out cleanly. Hope this helps someone!

    var originPosition:Vector3;

    var originRotation:Quaternion;

    var shake_decay: float;

    var shake_intensity: float;;

    public var fps: GameObject;

    Shake();

    function Update(){

    if(shake_intensity > 0) {

    transform.position = originPosition + Random.insideUnitSphere * shake_intensity;

    transform.rotation = Quaternion(

    originRotation.x + Random.Range(-shake_intensity,shake_intensity)*.2,

    originRotation.y + Random.Range(-shake_intensity,shake_intensity)*.2,

    originRotation.z + Random.Range(-shake_intensity,shake_intensity)*.2,

    originRotation.w + Random.Range(-shake_intensity,shake_intensity)*.2);

    originPosition = fps.transform.position;

    originRotation = fps.transform.rotation;

    //shake_intensity -= shake_decay;

    }

    else { print (“intensity stable”);}

    }

    function Shake(){

    shake_intensity = .08;

    //shake_decay = 0.1;

    }

    • mdjasper

      Thank you Brandon. I’m sure this updated script will help lots of others!

  • remz

    I wrote an updated version of the c# script that returns your camera in it’s original local rotation/position as it was breaking my 2d game.
    hope this helps :

    public class CameraShake : MonoBehaviour {

    private Vector3 originPosition;

    private Quaternion originRotation;

    public float shake_decay;

    public float shake_intensity;

    private bool shaking;

    private Transform _transform;

    void OnGUI (){

    if (GUI.Button (new Rect (20,40,80,20), “Shake”)){

    Shake ();

    }

    }

    void OnEnable() {

    _transform = transform;

    }

    void Update (){

    if(!shaking)

    return;

    if (shake_intensity > 0f){

    _transform.localPosition = originPosition + Random.insideUnitSphere * shake_intensity;

    _transform.localRotation = new Quaternion(

    originRotation.x + Random.Range (-shake_intensity,shake_intensity) * .2f,

    originRotation.y + Random.Range (-shake_intensity,shake_intensity) * .2f,

    originRotation.z + Random.Range (-shake_intensity,shake_intensity) * .2f,

    originRotation.w + Random.Range (-shake_intensity,shake_intensity) * .2f);

    shake_intensity -= shake_decay;

    } else {

    Debug.Log(“stopped shaking”);

    shaking = false;

    _transform.localPosition = originPosition;

    _transform.localRotation = originRotation;

    }

    }

    void Shake(){

    if(!shaking) {

    originPosition = _transform.localPosition;

    originRotation = _transform.localRotation;

    }

    shaking = true;

    shake_intensity = .1f;

    shake_decay = 0.002f;

    }

    }

  • Pingback: Galawana Studio » Unity3D : Camera Shake Effect (script)

  • GGibson

    Why does the random quaternion only affect left to right motion? I removed the random positioning, because I only want rotation, but the random rotation only affects left to right movement, so shaking is like a vigorous shaking of the head from side to side without up and down movement. Why is this? I thought w,x,y,z would affect all possible rotation.

    • GGibson

      Ah, nevermind. This is the effect if MouseLook is enabled FYI.

  • DaveVoyles

    Great scripts! Thanks guys

    • mdjasper

      Thanks for the feedback. I’ve had some very helpful commentors who have contributed greatly to the shake script. I guess Unity has a good community :-)

  • nallib said tala montenegro

    Thanks man. Awesome

  • Andrew Krischer

    Thanks so much for the script! It’s very simple and works exactly as intended :D.

    Also I’ve found it helpful to overload Shake() with

    Shake(float extraIntensity, float extraDecay) {
    originPosition = transform.position;
    originRotation = transform.rotation;
    shake_intensity = .3f + extraIntensity;
    shake_decay = 0.002 + extraDecayf;
    }

    Easy overload which gives more on-the-fly control.

  • Sindorej

    Works as a charm! A tiny note, at C#, line 18 replace shake_intenity with shake_intensity just a tiny typo. Thanks for sharing!