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;
}
}
}
@bolabola

This comment has been minimized.

bolabola commented Aug 29, 2014

good job

@ReyNarvaez

This comment has been minimized.

ReyNarvaez commented Oct 24, 2014

Great job! It helped me alot

@Lyudmil-Kovachev

This comment has been minimized.

Lyudmil-Kovachev commented Oct 27, 2014

Thank you! Nice and simple

@iamcsharper

This comment has been minimized.

iamcsharper commented Nov 2, 2014

how to make it without decreasing?:C

@iamcsharper

This comment has been minimized.

iamcsharper commented Nov 2, 2014

So it's a crap holy shit.
All you need is
public float targetTime = 0.2f; // Время на один шаг в секундах
public float Smooth = 10; // Мягкость
public float AmplitudeHeight = 0.1f; // Амлитуда покачивания вверх-вниз
public float AmplitudeRot = 1.5f; // Амплитуда поворота

private float Progress; // Прогресс
private int PassedStep = 1; // Шаг
private float DefCamPos = 0; // Изначальная позиция камеры
private float DefCamRot = 0; // Изначальный поворот камеры
private Transform MyTransform; // Наш трансформ


void Start() {
    MyTransform = transform; // Ну, я где-то прочитал что так будет работать быстрей
    DefCamPos = MyTransform.localPosition.y; // Изначальная позиция камеры
    DefCamRot = MyTransform.localEulerAngles.z; // Изначальный поворот камеры
}


void Update() {
    float Pssd = Passed(); // Наш прогресс

    // Позиция в Vector3, к которой мы стримимся
    Vector3 GoalPos = new Vector3(MyTransform.localPosition.x, Pssd * AmplitudeHeight + DefCamPos, MyTransform.localPosition.z);
    // Position interpolation (smooth)
    MyTransform.localPosition = Vector3.Lerp(MyTransform.localPosition, GoalPos, Time.deltaTime * Smooth);


    // Vector3 rotation in way we need to go
    if(Mathf.Abs(Input.GetAxis("Horizontal")) == 1 && Mathf.Abs(Input.GetAxis("Vertical")) == 0) {
        Pssd = 0; // Equals to zero if we would go to side ways
    }
    Vector3 GoalRot = new Vector3(MyTransform.localPosition.x, MyTransform.localPosition.y, Pssd * AmplitudeRot + DefCamRot);
    // Rotation smooth
    MyTransform.localEulerAngles = Vector3.Lerp(MyTransform.localPosition, GoalRot, Time.deltaTime * Smooth);
}


private float Passed(){

    // Если мы вообще никуда не двигаемся (право, лево, вперед, назад)
    // То возвращаем ноль
    if(Mathf.Abs(Input.GetAxis("Horizontal")) == 0 && Mathf.Abs(Input.GetAxis("Vertical")) == 0) {
        PassedStep = 1; // Сбрасываем шаг
        return (Progress = 0); // Прогресс сводим к нулю и возвращаем его
    }

    // Умножаем прогресс на шаг (PassedStep)
    // Если step = 1, то тогда значение не меняется. 
    // А если step = -1, то тогда значение формулы становится отрицательным и мы начинаем вычитать из Progress
    Progress += (Time.deltaTime * (1f / targetTime)) * PassedStep;
    if(Mathf.Abs(Progress) >= 1) { // Если Progress больше или равно 1, или меньше или равно -1
        PassedStep *= -1; // Инвертируем шаг
    }

    //Return progress, it's about from 0 to 1
    return Progress;
}
@zahid--ali

This comment has been minimized.

zahid--ali commented Aug 15, 2015

Helped me too thanks

@jplebre

This comment has been minimized.

jplebre commented Jan 28, 2016

Thank you! this saved me a good hour of work! great job!

@thekolapo

This comment has been minimized.

thekolapo commented Mar 8, 2016

Thanks!...really helpful

@darpan1118

This comment has been minimized.

darpan1118 commented Apr 27, 2016

Thanks!

@pandakub

This comment has been minimized.

pandakub commented Jun 23, 2016

awesome work!!!

@ixikos

This comment has been minimized.

ixikos commented Jun 26, 2016

This class is static, you can call it from anywhere. Put it on the camera or a parent to the camera.

`using UnityEngine;
using System.Collections;

public class CameraShake : MonoBehaviour
{

private Vector3 _originalPos;
public static CameraShake _instance;

void Awake()
{
    _originalPos = transform.localPosition;

    _instance = this;
}

public static void Shake (float duration, float amount) {
            _instance.StopAllCoroutines();
    _instance.StartCoroutine(_instance.cShake(duration, amount));
}

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

    while (Time.time < endTime) {
        transform.localPosition = _originalPos + Random.insideUnitSphere * amount;

        duration -= Time.deltaTime;

        yield return null;
    }

    transform.localPosition = _originalPos;
}

}`

@nicotroia

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

eugis commented Nov 7, 2016

Thanks! It helps a lot!

@yasinjavaid

This comment has been minimized.

yasinjavaid commented Apr 18, 2017

thanks it helps me too thumbs up for .cs

@NickPax

This comment has been minimized.

NickPax commented May 4, 2017

@nicotroia - thanks! Nice one.

@PabloSaitua

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Totoual commented Nov 9, 2017

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

@RishabhRyber

This comment has been minimized.

RishabhRyber commented Feb 5, 2018

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

@Jaemins

This comment has been minimized.

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 ?

@TannerMoore

This comment has been minimized.

TannerMoore commented Apr 1, 2018

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

@victor-guillermo

This comment has been minimized.

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

This comment has been minimized.

GustavoBernardi commented May 15, 2018

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

@AndySum

This comment has been minimized.

AndySum commented Jul 4, 2018

Amazing thanks!

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