- Home /
Camera shake
Hey guys how can i make a simlpe camera shake that returns 2 its original position after shaking
function Update() {
if(Shake < 0){
Shake = 0;
}
if (Shake > 0) {
cam.transform.localPosition = Random.insideUnitSphere * shakeAmount;
Shake -= Time.deltaTime * decreaseFactor;
} else {
shake = 0.0;
}
}
For a simple way, try that. For something a little more heavy, might be a little to much if you just want the camera shake : ShakePosition de iTween.
You could use a sin function with a damping constant. (Sounds scientic!!!)
Ae^(-kt) cos(wt)
e^(-kt) means e to the power of (-kt). This function will creates a large oscillation depending on you A that will reduce in time to finish to 0. The duration and tilting of your camera depends on the (-kt).
That might not be what you want but if that can lead you somewhere.
You have to save the original position bud. There's no other way.
Your randomisation using the unit sphere is perfect: BUT you have to do "two jiggles" at a time. Always move it using your current system, and then in the new step simply return it to where it was.
Just use parity (i.e. odd/even) to know which you are supposed to do, ok
This blog covers it pretty well: http://unitytipsandtricks.blogspot.com/2013/05/camera-shake.html
For the record it is extremely hard to actually program the physics of hand-held camera shake, "wind" shake, tripod shudder, and other versions of camera shake. Note that in unity you can simply attach a spring to the camera and let physX do the work, no coding required. This would be a winning idea since, uh, you pay $4500 for Unity "since it has a physics engine". So use it. By no means does a "spring on a camera" produce really realistic "camera shake", but it's better than using Perlin Noise. Perlin Noise is sort of ok; the other "solutions" on here are silly.
Getting back to the actual question asked by the OP, conceptually yes you have to save the "original" position (indeed the "base" position, which in any non-trivial system will, of course, be moving. You have to have a whole complicated system representing where the camera is "ideally" and so on.)
Answer by insominx · Jun 24, 2015 at 04:50 PM
The solutions on this page work but randomized movement is very poor.
Substituting with noise will improve it dramatically. See here:
http://unitytipsandtricks.blogspot.com/2013/05/camera-shake.html
http://www.youtube.com/watch?v=cDxQEFP-fhM&feature=youtu.be
Perlin Noise is already built-in to Unity of course...
http://docs.unity3d.com/ScriptReference/Mathf.PerlinNoise.html
Answer by mdjasper · Jun 26, 2012 at 07:31 PM
I know this question is bit old, but I thought I'd share my answer for posterity's sake. I also ran into the problem of returning to the original position/rotation after finished shaking, and came up with this solution.
Here is a demo of the camera shake script.
Using two variables shake_intensity
, and shake_decay
the script generates a new random position and rotation within the range (defined by shake_intensity
). With each Update(), shake_intensity
decays until the position and rotation are at their original position.
var originPosition:Vector3;
var originRotation:Quaternion;
var shake_decay: float;
var shake_intensity: float;;
function OnGUI () {
if (GUI.Button (Rect (20,40,80,20), "Shake")) {
Shake();
}
}
function Update(){
if(shake_intensity > 0){
transform.position = originPosition + Random.insideUnitSphere * shake_intensity;
transform.rotation = Quaternion(
originRotation.x + Random.Range(-shake_intensity,shake_intensity)*.2,
originRotation.y + Random.Range(-shake_intensity,shake_intensity)*.2,
originRotation.z + Random.Range(-shake_intensity,shake_intensity)*.2,
originRotation.w + Random.Range(-shake_intensity,shake_intensity)*.2);
shake_intensity -= shake_decay;
}
}
function Shake(){
originPosition = transform.position;
originRotation = transform.rotation;
shake_intensity = .3;
shake_decay = 0.002;
}
Depending on initial shake_intensity and shake_decay the camera might not return to it's exact original position. To return exactly to the original position you need the following modification:
...
shake_intensity -= transform.position;
if (shake_intensity <= 0)
{
transform.position = originPosition;
transform.rotation = originRotation;
}
...
Nice snippet, thats what I found out too after some testing!
Answer by sjaak45 · Jan 12, 2013 at 08:47 PM
Thanks, this works perfectly!
For testing I added a test button which calls the DoShake function:
using UnityEngine;
using System.Collections;
public class CameraShake : MonoBehaviour {
public bool Shaking;
private float ShakeDecay;
private float ShakeIntensity;
private Vector3 OriginalPos;
private Quaternion OriginalRot;
void Start()
{
Shaking = false;
}
// Update is called once per frame
void Update ()
{
if(ShakeIntensity > 0)
{
transform.position = OriginalPos + Random.insideUnitSphere * ShakeIntensity;
transform.rotation = new Quaternion(OriginalRot.x + Random.Range(-ShakeIntensity, ShakeIntensity)*.2f,
OriginalRot.y + Random.Range(-ShakeIntensity, ShakeIntensity)*.2f,
OriginalRot.z + Random.Range(-ShakeIntensity, ShakeIntensity)*.2f,
OriginalRot.w + Random.Range(-ShakeIntensity, ShakeIntensity)*.2f);
ShakeIntensity -= ShakeDecay;
}
else if (Shaking)
{
Shaking = false;
}
}
void OnGUI() {
if (GUI.Button(new Rect(10, 200, 50, 30), "Shake"))
DoShake();
Debug.Log("Shake");
}
public void DoShake()
{
OriginalPos = transform.position;
OriginalRot = transform.rotation;
ShakeIntensity = 0.3f;
ShakeDecay = 0.02f;
Shaking = true;
}
}
EDIT: mdjasper, thanks for coming up with the original solution!
Answer by bgprocks · Jan 11, 2013 at 11:47 PM
using UnityEngine;
using System.Collections;
public class ShakeCamera : MonoBehaviour
{
public bool Shaking;
private float ShakeDecay;
private float ShakeIntensity;
private Vector3 OriginalPos;
private Quaternion OriginalRot;
void Start()
{
Shaking = false;
}
// Update is called once per frame
void Update ()
{
if(ShakeIntensity > 0)
{
transform.position = OriginalPos + Random.insideUnitSphere * ShakeIntensity;
transform.rotation = new Quaternion(OriginalRot.x + Random.Range(-ShakeIntensity, ShakeIntensity)*.2f,
OriginalRot.y + Random.Range(-ShakeIntensity, ShakeIntensity)*.2f,
OriginalRot.z + Random.Range(-ShakeIntensity, ShakeIntensity)*.2f,
OriginalRot.w + Random.Range(-ShakeIntensity, ShakeIntensity)*.2f);
ShakeIntensity -= ShakeDecay;
}
else if (Shaking)
{
Shaking = false;
}
}
public void DoShake()
{
OriginalPos = transform.position;
OriginalRot = transform.rotation;
ShakeIntensity = 0.3f;
ShakeDecay = 0.02f;
Shaking = true;
}
}
Answer by Loorden · Jun 09, 2017 at 06:44 AM
I've used this one, and it works perfectly :) bool flip;
float yPos;
float shakeAmount = 1;
public Transform myCam;
void Update()
{
if(Input.GetKeyDown(KeyCode.Space)) StartCoroutine ("CamShake");
}
IEnumerator CamShake ()
{
yPos = shakeAmount;
while (Mathf.Abs(yPos) > 0.01f )
{
yPos = Mathf.Abs (yPos) - 0.1f;
if (flip) yPos *= -1;
flip = !flip;
//Tripple setup thingo!
Vector3 tempPos = myCam.localPosition;
tempPos.y = yPos;
myCam.localPosition = tempPos;
yield return null;
}
}
Your answer
Follow this Question
Related Questions
Constant camera shake. 1 Answer
How to freeze the rotation or the position on the camera transform? 1 Answer
iTween.ShakePosition freezes Rotation 0 Answers
Why is it moving locally instead of globally? 1 Answer
Loop a script ? 0 Answers