Skip to content

Instantly share code, notes, and snippets.

@ftvs
Last active September 26, 2024 07:16
Show Gist options
  • Save ftvs/5822103 to your computer and use it in GitHub Desktop.
Save ftvs/5822103 to your computer and use it in GitHub Desktop.
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;
}
}
}
@Ar-Ess
Copy link

Ar-Ess commented Apr 17, 2024

This is my modification, I made it completely generic. Just copy paste on any object and you're good to go.

How it works:

  • Duration: the duration of the shake in seconds
  • Amplitude: the amount of Unity units that the shake uses to move
  • Soft Level: The higher it is, the slower will run the shake. Internally, the soft level int acts as "how many frames do I skip for the next shake"
  • Decrease: If false, the shake will be constant. If true, the shake will linearly shift its amplitude.
  • Animation: Same as decrease, but here you can choose which amplitude animation you want

Flaws:

  • The soften parameter does its job, but the shake is not really smooth... I tried implementing the "Vector3.Lerp" option, but it does not work really well... If someone can come up with a solution to smooth the movement, so then we can acquire a kind of "frequency" parameter.
public void Shake(float duration, float amplitude, int softLevel = 0, bool decrease = false)
{
    AnimationCurve animation = decrease ? AnimationCurve.Linear(0, 1, 1, 0) : AnimationCurve.Constant(0, 1, 1);
    StartCoroutine(Shake_Internal(duration, amplitude, softLevel, animation));
}

public void Shake(float duration, float amplitude, int softLevel = 0, AnimationCurve animation = null)
{
    if (animation == null) animation = AnimationCurve.Linear(0, 1, 1, 0);
    StartCoroutine(Shake_Internal(duration, amplitude, softLevel, animation));
}

private IEnumerator Shake_Internal(float duration, float amplitude, int softLevel, AnimationCurve animation)
{
    Vector3 initialPosition = transform.position;
    float amp = amplitude;
    if (softLevel < 0) softLevel = 0;
    int softCount = 0;

    for (float i = 0; i < duration; i += Time.deltaTime)
    {
        if (softLevel != 0 && softCount < softLevel)
            softCount++;
        else
        {
            transform.position = initialPosition + Random.insideUnitSphere * amp;
            amp = amplitude * animation.Evaluate(i);
            softCount = 0;
        }
        yield return null;
    }

    transform.position = initialPosition;
}

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