Skip to content

Instantly share code, notes, and snippets.

@slonermike
Created March 5, 2018 23:44
Show Gist options
  • Save slonermike/40cb25549b4428ec9221c00b0b73e570 to your computer and use it in GitHub Desktop.
Save slonermike/40cb25549b4428ec9221c00b0b73e570 to your computer and use it in GitHub Desktop.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
// TODO: Is there really anything about this that makes it
// specific to cameras? This logic could be used to shake
// anything. Only thing tying it to that is the ShakeAllCameras
// functionality but we could work that out by tagging things by
// generic categories, and shaking all objects in a category.
//
public class CameraShaker : MonoBehaviour {
private static List<CameraShaker> shakers = new List<CameraShaker>();
public float rotationFactor = 1f;
float maxMagnitude = 0.0f;
float timeLeft_s = 0.0f;
float timeTotal_s = 0.0f;
// Activate every CameraShaker in the scene.
//
// time_s: Time (in seconds) for the shake to take.
// magnitude: distance (in game units) for the shake to move the camera at its most extreme.
//
public static void ShakeAllCameras(float time_s, float magnitude)
{
foreach (CameraShaker s in shakers) {
s.Shake (time_s, magnitude);
}
}
void Start () {
// Add it to the global list of camera shakers.
shakers.Add (this);
}
void OnDestroy() {
shakers.Remove (this);
}
void Update () {
// Subtract time until it reaches zero, then the shake is done. Reset the system.
timeLeft_s -= Time.deltaTime;
if (timeLeft_s <= 0.0f) {
timeLeft_s = 0.0f;
timeTotal_s = 0.0f;
maxMagnitude = 0.0f;
}
// Set the local position to the shaken offset.
transform.localPosition = GetOffset ();
Vector3 rotation = GetRotation(transform.localPosition);
transform.localRotation = Quaternion.Euler (rotation);
}
// Generates a random camera offset based on the current state of the shake.
//
Vector2 GetOffset()
{
// Default offset is zero -- no shake.
Vector2 offset = Vector2.zero;
// If there is a current shake in play.
if (timeLeft_s > 0f && timeTotal_s > 0f) {
// Choose a random direction.
float direction = Random.Range (0.0f, 360.0f);
// Create a vector (relative to camera orientation) with a random direction rotated around the forward axis.
offset = Quaternion.AngleAxis (direction, transform.forward) * transform.right;
// Determine the current effective spread (between 0 and maxSpread) and multiply the offset by that.
offset *= Mathf.Lerp (0.0f, maxMagnitude, timeLeft_s / timeTotal_s);
}
return offset;
}
Vector3 GetRotation(Vector2 offset)
{
return new Vector3 (offset.y * rotationFactor, offset.x * rotationFactor, 0f);
}
// Begin a new shake.
//
// time_s: Time (in seconds) for the shake to take.
// magnitude: distance (in game units) for the shake to move the camera at its most extreme.
//
public void Shake(float time_s, float magnitude)
{
if (magnitude >= maxMagnitude) {
maxMagnitude = magnitude;
timeLeft_s = Mathf.Max(time_s, timeLeft_s);
timeTotal_s = timeLeft_s;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment