Skip to content

Instantly share code, notes, and snippets.

@luciditee
Last active February 22, 2017 02:28
Show Gist options
  • Save luciditee/6c8ff710479631b1bd880766e36a8026 to your computer and use it in GitHub Desktop.
Save luciditee/6c8ff710479631b1bd880766e36a8026 to your computer and use it in GitHub Desktop.
A simple Unity script designed to shake the screen both via rotation and position.
/*
* Unity Screen Shake: A simple script designed to shake the
* attached transform using rotation and position; usually parented
* to a camera.
*
* Copyright 2016-2017 Will Preston & Die-Cast Magic Studios, LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using UnityEngine;
public sealed class ScreenShake : MonoBehaviour {
// How rapidly the screenshake finds a new target.
[Range(10f, 100f)]
public float frequency = 10f;
// How large is the delta of each shake?
[Range(.1f, 1f)]
public float intensity = 1f;
// How much influence should we have on the position?
[Range(0.01f, 1f)]
public float positionMultiplier = .2f;
private bool doShake = false; // Internally, are we shaking?
private float timer = 0f; // Frequency timer.
private float opTimer = 0f; // Operation timer (for when we call Shake())
private float maxOpTimer = 0f; // How long should a Shake() last?
private float opIntensity = 1f; // How intense should a Shake() be?
private float lerpIntensity = 0f; // Lerp from 0 to opIntensity and back.
private float propagationSpeed = 1f; // How quickly does the lerp kick in?
private bool sign = false; // Return to original position or new position?
private Quaternion targetRotation = Quaternion.identity; // Lerp target.
private Vector3 targetPosition = Vector3.zero; // Lerp target.
// Create a screenshake based on the intensity set and duration.
public void Shake(float intensity, float duration, float propagation = 3f) {
propagationSpeed = Mathf.Clamp(propagation, 1f, 10f);
opIntensity = intensity;
maxOpTimer = duration;
opTimer = 0f;
doShake = true;
}
// Once per frame, update.
void Update () {
if (doShake) {
// Add to the op timer.
opTimer += Time.deltaTime;
// We 'fake' the frequency by counting up to the reciprocal value of the Hz specified
// by the inspector (this converts from Hz to seconds). When this count-up succeeds,
// we reset the timer.
timer += Time.deltaTime;
if (timer >= (1f/frequency)) {
timer = 0f;
// The 'sign' merely predicts if we're on a tick or tock, i.e. if we are
// moving towards our base position/rotation or towards a randomized one.
if (sign) {
targetRotation = Quaternion.identity;
targetPosition = Vector3.zero;
} else {
float intensity = this.intensity * lerpIntensity;
targetRotation = Quaternion.Euler(Random.Range(-intensity, intensity),
Random.Range(-intensity, intensity), Random.Range(-intensity, intensity));
targetPosition = (new Vector3(Random.Range(-intensity, intensity), Random.Range(-intensity, intensity),
Random.Range(-intensity, intensity)) * positionMultiplier);
}
// Flip the sign.
sign = !sign;
}
// Break out if we are done.
if (opTimer >= maxOpTimer) {
doShake = false;
opIntensity = 0f;
opTimer = 0f;
}
} else {
// If we are not shaking, force this to an identity transform.
targetRotation = Quaternion.identity;
targetPosition = Vector3.zero;
}
// Perform move.
transform.localPosition = Vector3.Lerp(transform.localPosition, targetPosition, Time.deltaTime*propagationSpeed);
transform.localRotation = Quaternion.Slerp(transform.localRotation, targetRotation, Time.deltaTime*propagationSpeed);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment