Skip to content

Instantly share code, notes, and snippets.

@barleymalt
Created April 5, 2023 13:01
Show Gist options
  • Save barleymalt/e2638b490f634fb1567bf4b5a2e6c2fd to your computer and use it in GitHub Desktop.
Save barleymalt/e2638b490f634fb1567bf4b5a2e6c2fd to your computer and use it in GitHub Desktop.
A simple CameraShake for Unity
using System;
using System.Collections;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Utils
{
public class CameraShake : MonoBehaviour
{
[Serializable]
public class ShakeOptions
{
public float Duration = .3f;
public float MovementStrength = .3f;
public AnimationCurve MovementEase = AnimationCurve.EaseInOut(0, 1, 1, 0);
public float FOVStrength = 3;
public AnimationCurve FOVEase = AnimationCurve.EaseInOut(0, 1, 1, 0);
}
[SerializeField] private Camera cam;
[SerializeField] private ShakeOptions defaultSettings;
private Vector3 originalPos;
private float originalFOV;
private Transform camT => cam.transform;
private void Awake()
{
if (cam == null)
{
cam = GetComponent<Camera>();
}
}
private void OnDisable()
{
if (shakeCo == null)
return;
StopCoroutine(shakeCo);
ResetNStates();
}
/// <summary>
/// Shake your booty!
/// </summary>
/// <param name="overrideDefaultOptions">Override default options</param>
public void Shake(ShakeOptions overrideDefaultOptions = null)
{
overrideDefaultOptions ??= defaultSettings;
shakeCo ??= StartCoroutine(C_Shake(overrideDefaultOptions));
}
private Coroutine shakeCo;
private IEnumerator C_Shake(ShakeOptions options)
{
originalPos = camT.localPosition;
originalFOV = cam.fieldOfView;
float elapsed = 0;
while (elapsed < options.Duration)
{
elapsed += Time.deltaTime;
var t = elapsed / options.Duration;
var moveOffset = options.MovementStrength * options.MovementEase.Evaluate(t);
var fovOffset = options.FOVStrength * options.FOVEase.Evaluate(t);
camT.localPosition = originalPos + Random.insideUnitSphere * moveOffset;
cam.fieldOfView = originalFOV + Random.Range(0f, 1f) * fovOffset;
yield return null;
}
ResetNStates();
}
private void ResetNStates()
{
cam.fieldOfView = originalFOV;
camT.localPosition = originalPos;
shakeCo = null;
}
#if UNITY_EDITOR
[Header("Debug")]
[SerializeField] private bool playDefaultShake;
private void Update()
{
if (playDefaultShake)
{
GetComponent<CameraShake>().Shake();
playDefaultShake = false;
}
}
#endif
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment