donderdag 29 januari 2015

Screen-shake in Unity3D with C#

Ever felt like a game was missing something? Just a little bit more feedback or a cool effect? Or you just wanted to be more like Vlambeer. Screen-shake can be the thing you're looking for.

In my opinion, if screen-shake is used correctly it can instantly make the game feel a lot more polished and "done", even if it's just an early prototype. Same goes for music and sound-effects, but today I'm writing about screen-shake.


The following code may look a little daunting, but it is actually quite simple. Just add this script to your camera and call to the AddShake function from your triggering script.

Be careful though, as the shakes are very sensitive, you may even want to change the code up a little to make it less sensitive if it gets annoying.

CameraEffects.cs:
using UnityEngine;
using System.Collections;
using System.Collections.Generic; //Just importing all the required code

public class CameraEffects : MonoBehaviour
{
 public static CameraEffects CamFX; //To make it easier for other scripts to reference to this camera-shaker, make it static (This won't work if you have multiple cameras

 private List shakes = new List(); //All the requested shakes are stored here
 [SerializeField]private Vector3 originalPos; //Be careful, if you don't want to parent your camera to a moving object if it has to move, move it using this, not the regular transform
 
 private void Awake()
 {
  CamFX = this; //This
  originalPos = transform.localPosition; //When the camera activates, it gets its default position
 }

 private void Update()
 {
  /*if (Input.GetKeyDown(KeyCode.A))
  {
   AddShake(2f,5f) //An example of how to add shakes
  }*/

  Shake();
  ClearLists();
  if(shakes.Count == 0 && originalPos != transform.localPosition) //Return to the original position when you're done shaking, you can see why this would get awkward when you try and move the camera regularly
   transform.localPosition = originalPos;
 }
 
 public void AddShake(float intensity, float duration) //This is the function you call to when you want to trigger a shake
 {
  if(shakes.Count == 0)
  {
   originalPos = transform.localPosition; //Before a shake starts, the current position is noted and returned to when the shake is done
  }
  shakes.Add(new CameraEffects_Shake(intensity, duration)); //This just passes the information you give, on to the actual shaker
 }
 
 private void Shake() //This is where the magic happens, the code is pretty self-explanatory
 {
  if(shakes.Count > 0)
  {
   float finalIntensity = 0;
   foreach(CameraEffects_Shake shake in shakes) //How many shakes does a shake shake if a shake shakes
   {
    finalIntensity += shake.intensity;
   }
   transform.localPosition = new Vector3(
    originalPos.x + Random.Range(-finalIntensity,finalIntensity),
    originalPos.y + Random.Range(-finalIntensity,finalIntensity),
    originalPos.z + Random.Range(-finalIntensity,finalIntensity)
    );
   Debug.Log(shakes.Count + " at " + finalIntensity); //You can remove this when you're done
  }
 }
 
 private void ClearLists() //Clearing up the finished shakes, don't want them cluttering up
 {
  for(int i = 0; i < shakes.Count; i++)
  {
   if(shakes[i] == null) break;
   
   if(Time.time > shakes[i].endTime)
   {
    shakes.RemoveAt(i);
    i--;
   }
  }
 }
}

public class CameraEffects_Shake //Alright now here's where it gets interesting. This allows for shakes to be an actual variable... thingie, which just makes it easier to access them in the rest of the code
{
 public readonly float intensity, endTime;
 
 public CameraEffects_Shake(float temp_intensity, float duration)
 {
  intensity = temp_intensity;
  endTime = duration + Time.time;
 }
}

Now, as you can see, thanks to some intuitive naming, the code is pretty self-explanatory. Experimenting never hurts though, so be sure to try lots of different things. You may also consider putting an adjusted version of this on a character to, for example, make them shake when they're hit. The possibilities are endless.

Geen opmerkingen:

Een reactie posten