In this lecture, we're going to make the player feel the weight of being hit by adding some screen
shake to our camera.
So this is an effect relating to our camera.
So let's create a new script, first of all, and let's go into our scripts folder and create a new
C-sharp script called Camera Shake.
And let's apply this to our main camera and essentially how this script is going to work.
It's going to take the current position of the camera and just move it around every frame.
So let's open up our script.
Let's clean up our comments above, start and delete our update method entirely.
And this effect is going to be controlled by two parameters.
So let's create some serialized fields of type float.
The first one is going to be the shake duration.
So how long is the effect going to last?
And we can default that to maybe 1/2 for now.
And the second is going to be of type float and we're going to call it the shake magnitude.
So how far is the camera going to move?
And again, by default, we'll set this up at point five and we can always fine tune and adjust these
numbers later.
Finally, for our variables, we're going to want to know the initial position of our camera, because
once we've finished moving it around, we want to set it back to where it started.
So let's take a vector three called initial position.
And in our stop method, we're going to set our initial position equal to our transform position.
Now, to get this effect working, we're going to be using a CO routine.
This CO routine is then going to be called from another script.
So let's set up that method first and have a public void and we'll call this one play.
So we'll have camera shake play or this is going to do is start a CO routine and we'll call this CO
routine shake.
Now let's create our shake co routine.
So we've got an AI enumerator called Shake.
And writing this CO routine is mostly going to be a challenge for you.
But let's just look at the logic for moving the camera to a random position to start with.
So we're going to be moving our transform position and this is going to be equal to our initial position,
plus a random dot inside unit circle.
And notice here we've got an inside unit circle and an inside unit sphere.
Since our game is 2D, the third axis doesn't really matter.
So let's go with an inside unit circle and a unit circle.
If you're not aware, it's just a circle with a radius of one.
So to give us a bit more control, let's also multiply that by our shake magnitude and this will change
the radius of that circle.
Now this is giving us a red squiggly, and if we hover over it, it's saying that it's having trouble
adding a vector three and a vector to remember our position is a vector three and our random inside
unit circle is a vector two.
So we could either change this to inside units fear or we could cast this to a vector three and to cast
a variable, we're just placing it inside parentheses before the thing we're trying to cast.
And this will tell the compiler to treat this value as a vector three rather than a vector two.
And in this case, the third Z component that isn't in our vector two is just going to be set as zero
in a vector three.
So to explain this line in a little bit more detail, let's break it down in a slide.
We start off with the camera in its initial position and then add a random point within a circle.
This circle is starting with a magnitude of one being a unit circle, but then we're multiplying that
by the shape magnitude, which gives us control over the area in which our camera can move.
And then what we want to do is take our current line of code and place it into a loop so that every
frame we pick a new position for our camera to be.
And if we move the camera around quick enough, it'll make it look like the screen is shaking and not
just being displaced every now and again.
Then, once the loop has finished, we want to place our camera back into its starting location.
So this now brings us onto your challenge.
I want you to complete our shake routine.
If you'd like a couple of hints, then the camera should shake for the shake duration.
So we're going to be adding some kind of loop in here.
And you may or may not want a temporary variable to help control this loop condition on every loop.
Once we've changed the position, we're going to want to yield control until the next frame, and we're
used to waiting 4 seconds, but have a look and see what else we can wait for.
Then once the shake duration has expired and our loop complete, we want to go ahead and reset the camera's
position to its initial position.
So pause the video now and give that a go.
Okay.
Welcome back.
So let's create the loop, first of all.
And to help with this, I'm going to create a temporary variable of type float called elapsed time.
I will set this to zero to start with.
Then for a loop I'm going to use a while loop because we don't know exactly how many iterations we're
going to need.
So let's say while the elapsed time is less than our shake duration, then we want to go ahead and continuously
move our camera position to stop ourselves.
Getting into an infinite loop.
Though, we're going to need to increment our elapsed time every loop.
So let's say elapsed time plus equals our time dot delta time.
And then finally we're going to yield return a new wait for end of frame.
So that will wait for the end of frame before coming back to our routine to check if it needs to do
anything else.
Lastly, once that loop has completed and our elapsed time is greater than or equal to our shake duration,
we can go ahead and reset our transform position to be equal to our initial position.
So that's a very basic camera shaking script.
And now let's look at where to call our play method.
Well, I think a good place to this would again be in our health script.
So let's jump over to our health script at the top.
Let's create some variables.
First of all, we're going to need a camera shake called Camera Shake.
And I'm also going to add a serialized field here of Type Ball to check whether we should apply the
camera shake.
Because remember, the health script is attached to both our player and our enemies, and we don't really
want this camera shake going off whenever we hit anything because it's going to be a bit too much.
So instead, we're going to limit it to just the player and this boolean will let us switch it off for
our enemies.
So with those variables set up, let's grab a reference to our camera, shake script, and we can do
this in our wake method so we can say camera shake and to find the component, we could go and find
the object in the scene.
But remember, the camera has a handy tag attached to it and this tag allows us to say camera dot,
main, dot, get component, and the component we want is our camera shake.
So that's just another way of doing things for our camera because this camera domain already has a find
object of type built into it.
So now let's decide where to actually call this shaking camera.
And again, like how we've got our play hit effect in our on trigger enter.
We're going to do a very similar thing with a camera shake.
So we're going to create a new method called Shake Camera.
And then if we go to the bottom of our script, let's create a new void.
Shake camera.
And in here first of all, we want to check that our camera shake does not equal nul so that we've managed
to find it on the camera and we want to check whether we should be applying this camera shake at all.
If all of that is fine, then we can ask our camera shake to play.
So let's save up our script and test this out in unity.
We can see here on our camera, we've got our two variables for our shake duration and our shake magnitude.
And if we head over to our prefabs and look at our enemy, we want to make sure that the apply camera
shake is switched off in its health script.
And for our player, we want to go and make sure that it's on.
Now, if we go ahead and hit play to test this out, let's get hit by an enemy and I'll screen shake.
It gets applied.
The effect is way too violent though, so let's tone it down just a tad.
So let's come out of play mode.
Let's go over to our main camera and let's maybe reduce the camera shake duration to around half a second
and the magnitude two around 0.25.
Let's play again and test that out.
And flat screen shake is now much more subdued.
But notice when we try and hit our enemies, the screen shake doesn't get applied only when we get hit
by them.
And with that, we now have a nice extra effect in our game to help the player know when they've been
struck by an enemy.
Now, as a word of warning, I would caution you with using this effect too much, because it can make
players feel a little bit sick if it goes on for too long.
And this is also a very simplistic version of a camera shake effect.
If you'd like to play around with this effect and create something a bit more robust, then in the resources.
I've linked to a fantastic GDC talk on this very subject.
We went with this version in our project because it's fairly easy to implement and there's not really
much math involved.
But if you are that way inclined and you enjoy some math, feel free to check out that talk because
it goes through some of the more complicated math that you might need.
So congratulations on implementing this version of a screen shake effect, and I'll see you in the next
lecture.