Shaking the Camera when the Player takes damage.
I am going to make My Camera Shake when a Game Event happens. In this Case the Game Event that I will be listening to is the Player Damage Event, so every time the player takes damage it will shake the camera.
Just like my power ups I will add a Game Event Listener that will get called automatically so I do not have to assign it in the Inspector. I renamed the Power Up Class to Coded Game Event Listener, since I am using this code for more then just power ups. Since I renamed the Class I also renamed the Game Event to Event. I added the
FormerlySerializedAs Attribute, so I do not loos the serialized value on any game objects that was using the old name.
I created a new Behavior called Camera Sake and added it to the Main Camera in the Scene. I am using the Coded Game Event Listener for the game event to trigger the Camera Shake. The Event Listeners Requires a Unity Action that gets called every time the Game Event happens. I am using a Method called Response. In the Response Method I am starting a Corutine Called Shake Camera. In the Shake Camera Routine I am starting the camera shake cool down timer.
While the timer is active I am going to set the local position to a random value.
I need to get the original position of the camera. I make sure that I set the local transform of the camera back to the original position after stopping the Coroutine. I then set the original position before starting the timer.
While the timer is active I set local position to the original position plus a random amount multiplied by the amplitude (strength of the shake). I use
Random.insideUnitSphere to get the random amount, this gives me a
Vector3 between 0 and 1.
Once the timer is no longer active i set the position back to the original position.
I now have a problem, the camera shakes when the game first starts and will shake when I collect the Lives Power Up. The reason for this is that The Player Lives Stat is triggering the player damaged event every time it updates. To fix this I need to add A Game Event for the Player Lives Update and use this new event on the Player Lives Stat and the Player Lives Display.
Now I need to trigger the Player Damaged Event. I am going to do this by modifying the Stat Behavior. I am going to add 2 Game Events. One for when the Stat is increased and on for when the Stat is decreased.
I connected the Player Damage Event to the Player Lives Stat
Next I added in Perlin noise and a frequency to a much better result.
Camera Shake with Cineamachine
I installed Cinemachine and then added a Cinemachine 2D camera to the scene. Now there are all kinds of things you can do with Cinemachine but I am only using it for the Camera Shake portion.
Cinemachine Impulse generates and manages camera shake in response to game events. For example, you can use Impulse to make a Cinemachine Virtual Camera shake when one GameObject collides with another, or when something in your Scene explodes.
Impulse has three parts:
Raw vibration signal: a vibration curve in up to 6 dimensions: X, Y, Z, pitch, roll, yaw.
Impulse Source: a component that emits the raw vibration signal from a point in Scene space, and defines signal characteristics such as duration, intensity, and range.
Impulse Listener: a Cinemachine extension that allows a Virtual Camera to “hear” an impulse, and react to it by shaking.
It’s useful to think about this in terms of individual “impulses.” An impulse is a single occurrence of an Impulse Source emitting a raw vibration signal. Collisions and events in your Scenes trigger impulses, Impulse Sources generate impulses, and Impulse Listeners react to impulses.
The Impulse Source contains the Raw vibration signal. The Impulse Listener listens for the source and reacts to it.
The impulse source can be a Cinemachine Collision Impulse Source (this triggers the Impulse when the Game Object attached has a collision with another object), or a Cinemachine Impulse Source (Ones that are not collisions or collider triggers, your own scripted Behavior). Since I already have a Game Event that is happening that I want to use to trigger the Impulse I will be using the latter.
On the Virtual Camera I added the Impulse Listener, by adding the Extension. The only setting I changed was the Use 2D Distance since my game is a 2D game I want to use this. I also Changed the Body of the Camera to Do Nothing, this setting is not related to the Impulse.
Cinemachine Game Event Impulse Source
I have a newly created C# script. I override the Cinemachine Impulse Source. I added the Coded Game Event Listener which contains the Game event to listen for. In the Awake method I call the Game Event Init Method, I use the Generate Impulse for the callback. The Generate Impulse is one of the Methods provided by the Cinemachine Impulse Source. No fancy code, no complicated math, Unity did all the heavy lifting for us.
I add a new Game Object for my player and added the newly created Behavior to it.
I use one of the presets for the Signal, the signal has a lot of fine tuning that you can do.
Cinemachine Impulse Source Settings
Changing the Frequency Gain on makes the camera shake faster or slower. changing the Amplitude Gain changes the amount of movement on the screen. I think that I will be using 0.25 for the Amplitude and 100 for the frequency.