Last active
September 26, 2024 07:16
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
Thanks! It worked well. The only thing I added to the script was a line that turns CinemachineBrain false because camera shaker didn't work with cinemachine.
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
Here's my script to shake, feel free to use and modify.
Here's the amplitude curve i'm using right now.
Please notice that the curve value is not the actual amplitude value so I recommend that it always goes from 0 to 1.