In this lecture, we're going to get our enemies shooting back at our player, and we're going to do
this using the exact same shooter script that we used for our player.
Before we go ahead and edit our script though, let's clean up our assets folder by dragging our shooter
script into our scripts folder and then let's head into our prefabs, go into our enemy, and then add
our Shooter component.
In here.
We want to give it the projectile prefab.
So this time we're going to use our enemy projectile.
And for now, we'll just leave all of the other things as default.
We can edit those when we start testing.
With that set, let's open up our shooter script and see what we need to change to get it to work for
our enemies.
Well, we want our enemies to fire automatically.
So it's really just a case of overriding our is firing boolean.
So this is no longer going to be getting set from a different script.
Instead, what we're going to do is we're going to set this to true in our start method, but so this
doesn't affect our player as well.
Let's create a new variable so we can tell the system whether we're using the A control or the player
control.
This is as simple as creating a serialized field of type ball that we're going to call use a I.
So if use IE is true, we're going to automatically set up our is firing ball and if it's false, we're
going to accept input from the player.
So in start, let's say that if we are using the AI then is firing is always going to be true.
So let's save up our script as it is and jump into unity to test this inside of our enemy prefab, let's
go down to our shooter script and check the use option.
Now if we go ahead and hit play, we can now see that our enemies are shooting.
But we've got some very weird behavior here.
First of all, the shooting is very fast.
And secondly, they're shooting in the wrong direction.
So let's come out of play mode and fix both these problems.
So over on our enemy prefab, let's first of all change our firing rate from 0.2 and make that a bit
larger so maybe around one and see how that feels.
And together, projectiles moving in the correct direction.
Remember that in our shooter script we were telling it to use the op vector multiplied by the projectile
speed.
So our enemy is going to be following our up vector, which is still up the screen, even though our
sprite makes it look like we're facing down.
So first of all, let's rotate our sprite.
So it follows more closely what the up direction should be.
So we'll just jump into our enemy Sprite and on the Z component of our rotation, we'll just change
that to 180 degrees.
We'll see that the Green Arrow now points down.
But remember, this is only for our sprite.
So if we click on our enemy, we can see that the up arrow for this is still facing up with that set.
The projectiles will now come out of the front of the ship, but we now need a way of rotating the entire
ship so it faces down the screen.
So to do this, we're going to have to rotate our objects when we instantiate them.
And if we head over to our script folder, this was the job of the enemy spawn.
So let's open up our enemy.
Spawn a script, head down to where we're instantiating our enemies.
And in here we're setting the rotation to cotangent identity.
So no rotation, but we can very easily change this condition.
So instead of using cotangent identity, we want to rotate our enemy 180 degrees when it's created.
There are a few ways to do this, but the easiest way of doing this is to say Quaternions.
Euler So you are.
And if you're wondering about the weird spelling versus the pronunciation, it's because it's named
after the mathematician Leonard Euler.
Then inside the parentheses we need to specify the X, Y and Z rotation and we don't want to rotate
on the X or Y, but we do want to rotate 180 degrees on the Z component.
So if we save this and jump back into unity and then we can go ahead and hit play, we should now find
that our enemies are the right way round and are shooting in the correct direction.
So we now have a way of the enemies shooting back at the player.
But the projectiles are all on a fixed firing schedule, so it's very predictable gameplay and this
is the next thing that I'm going to want to change.
So let's come out of play and head back over into our shooter script one more time.
And then let's just recap on our firing CO routine.
So while true, we're instantiating our object, giving it some velocity, destroying it after a set
amount of time.
And then the piece we're interested in is the weighting.
So to make this more random, we're going to want to pass a random value into this wait 4 seconds.
And because I think you're up to the task, this is going to be your challenge.
I want you to go ahead and modify our routine to wait for a random amount of time between our projectiles.
And as a hint, why not have a look at I'll get random spawn time method from our wave config.
So because the logic here is going to be very, very similar.
So once you've had a look at that method that we've written previously, think about what new variables
we're going to need to add to our shoot script to make this work and potentially what we're going to
need to change.
So pause the video now and give that one a go.
Okay.
Welcome back.
So hopefully you got on well with that challenge.
And here we are in our wave config so we can see how we did it last time.
Well, for our variables, we had a time between enemy spawns, a spawn time variance and a minimum
spawn time.
And if we head down to our get random spawn time method in here, we were getting a random spawn time
between two values.
And then to make sure that we weren't going into negative numbers, we were clamping our result.
So let's essentially replicate this same sort of thing in our shooter script.
We're currently waiting for our fire rate in our routine, but I think this should probably be renamed
and used in a slightly different way.
So I'm going to rename my firing rate to the base firing rate and then I'm going to create two more
serialized fields.
These are both going to be Float, and the first one is going to be called the firing rate variance.
And by default, we're going to set this to zero.
And then for our second variable, we're going to call this one the minimum firing rate.
And we can maybe set that to around point one.
With those set, let's head down to our routine and implement our logic.
So in here we want a temporary variable of type float, which I'm going to call Time to next projectile.
And this is going to be equal to a random range between our base firing rate minus our firing rate variance
and our base firing rate plus our firing rate variance.
Then to make sure that this value doesn't go below zero, because if it does, we're going to be waiting
for negative seconds, which is going to cause us a lot of problems.
So we're going to clamp this value by saying time to next projectile is equal to math.
F Clamp the value we want to clamp is our time to next projectile.
We want our minimum value to be the minimum firing rate and our maximum value is going to be our float
max value.
And then, rather than yielding for the amount of our base firing rate, we want to wait for the time
to next projectile.
So let's save this up and test out.
Let's head into our prefabs and look at our enemy.
We've already set our use AI to be true.
We want our base firing rate to be around one, and we're going to add a variance of maybe around 0.5.
So our projectiles will spawn anywhere between half a second and one half seconds between each other.
Now, before we actually test, there's one more thing I do want to do in my shooting script, because
we're getting a lot of variables in here and it's starting to get very cluttered.
We've got this is firing flag that's public, but we don't ever really need to set it in the inspector.
So it would make sense to hide that away.
And we've also got a bit of a split between generic shooter functionality and other things specifically
related to our air shooting.
So let's jump back into our shooter script for one final time.
And if we head up to our variables at the top, we're going to separate this up with some headers so
we can use the header attribute.
And I'm going to call the first one general and this will include our projectile prefab, its speed
lifetime and maybe our base firing rate as well.
And then we're going to have a second header attribute called I and this will have our use I flag and
the variables that we're using to modify our firing rate.
Finally, we're going to hide away this public variable, and we can do that with another new attribute.
And this is called Hide in Inspector.
And just like a serialized filled, this doesn't really affect the access level of our variable encode.
It only affects the access in the inspector.
So let's save this up and jump back into unity.
And now we can see our shooter component is a lot more manageable if we're just dealing with general
stuff, we can set up our first four variables and if we're interested in AI, then we can set these
up and finally notice that our IS shooting variable is no longer present because we've hidden it in
the inspector.
So with that little bit of clean up a side, let's finally go and test our gain.
We now have our enemies shooting at random intervals, which is a lot nicer and they're shooting a little
bit slower and we can shoot back at them and destroy them.
And with that, our core gameplay is pretty much finished.
It still requires a little bit of tuning and we can add some more enemy waves and enemy types, but
the fundamentals are all there.
However, it is still a little bit boring, so over the next few lectures we're going to start adding
some juice to our game.
And the first piece of juice that I want to add is some particle effects to start selling the impact
of the projectiles on the enemies.
Well, we're starting that in the next lecture, so I'll see you there.