1
00:00:03,840 --> 00:00:06,330
Following all the set up that we did in the last lecture.

2
00:00:06,330 --> 00:00:08,520
In this one, we're going to get our player shooting.

3
00:00:09,160 --> 00:00:14,050
Now the first step to this is to figure out where we want this shooting behavior to be written.

4
00:00:14,290 --> 00:00:20,020
So if we go into our prefabs and have a look at how our player is set up, we're going to be listening

5
00:00:20,020 --> 00:00:22,980
for On Fire as part of our player input.

6
00:00:22,990 --> 00:00:27,750
And if you remember when we were listening for On Move, we were doing that in the player script.

7
00:00:27,760 --> 00:00:32,200
So let's have a look at the player script just to remind ourselves of how we were doing that.

8
00:00:32,500 --> 00:00:39,310
And if we scroll down, we had this on move event which was listening for the input itself, so we could

9
00:00:39,310 --> 00:00:42,690
also listen for our On Fire event in here as well.

10
00:00:42,700 --> 00:00:47,890
However, we don't really want the actual shooting behavior to be part of this script because our enemies

11
00:00:47,890 --> 00:00:50,650
are also going to need to shoot back at the player.

12
00:00:50,800 --> 00:00:56,770
So let's put our on fire method in here to listen for when the player is pressing the fire key.

13
00:00:56,770 --> 00:01:02,710
And then later on we can use this method to set a variable within our shooter script to start that firing

14
00:01:02,710 --> 00:01:03,490
process.

15
00:01:03,700 --> 00:01:08,950
Before we do that, though, I've noticed we've still got a debug log in here for our on mode method.

16
00:01:08,950 --> 00:01:12,340
So let's delete that first just to clean things up a little bit.

17
00:01:12,340 --> 00:01:16,450
And then underneath this, let's write our on fire method.

18
00:01:16,630 --> 00:01:19,930
So just like the one above it, it's going to be void.

19
00:01:19,930 --> 00:01:22,060
We're going to call it on fire.

20
00:01:22,690 --> 00:01:29,740
And because we change the action type to be of type value, we can pass in a type of input value called

21
00:01:29,740 --> 00:01:30,460
value.

22
00:01:30,910 --> 00:01:34,540
And then in here we're going to be setting a boolean from our other script.

23
00:01:34,540 --> 00:01:38,500
We haven't written that script yet though, so let's save this up for now.

24
00:01:38,740 --> 00:01:44,470
And then on our player prefab, let's go down and add a new component called Shooter.

25
00:01:46,510 --> 00:01:50,800
If we open this up, let's now think about what this script is going to need to do.

26
00:01:51,010 --> 00:01:55,450
Well, the way I'm going to do it is I'm going to have the script instantiate some projectiles whenever

27
00:01:55,450 --> 00:01:57,140
that fire key is pressed.

28
00:01:57,160 --> 00:02:02,470
So to start with, let's clean up our comments, but leave our start and update method alone.

29
00:02:02,470 --> 00:02:07,690
For now, we're going to need a serialized field to hold the prefab for our projectile.

30
00:02:07,690 --> 00:02:11,140
So let's have a game object called Projectile Prefab.

31
00:02:11,560 --> 00:02:16,000
And when we create this projectile, we're going to want it to have a certain amount of speed and we're

32
00:02:16,000 --> 00:02:18,610
going to want it to live for a certain amount of time.

33
00:02:18,610 --> 00:02:22,000
So let's control these variables with serialized fields as well.

34
00:02:22,240 --> 00:02:30,460
We can have a float called projectile speed and I think a default value of around ten should be okay

35
00:02:30,490 --> 00:02:31,300
to start with.

36
00:02:31,870 --> 00:02:37,270
And we need a serialized build again of type float called Projectile Lifetime.

37
00:02:37,510 --> 00:02:41,290
And for this I think maybe 5 seconds should be okay.

38
00:02:41,890 --> 00:02:46,870
Finally, let's actually finish setting up that Boolean flag that we're going to need for our player

39
00:02:46,870 --> 00:02:50,170
script because this needs to be accessed from another script.

40
00:02:50,170 --> 00:02:52,180
Let's go ahead and make it public.

41
00:02:52,180 --> 00:02:57,220
Our public variable is going to be of type ball and we're going to call it is firing.

42
00:02:57,310 --> 00:03:02,470
And now with that set up, let's jump back over to our player script and just quickly finish off our

43
00:03:02,470 --> 00:03:03,610
on fire method.

44
00:03:03,970 --> 00:03:09,040
Before we do that, we're going to need access to our shooter script from within our player script.

45
00:03:09,040 --> 00:03:15,250
So right at the very top, let's add a new variable of type shooter and we'll call it the shooter.

46
00:03:16,480 --> 00:03:22,660
And then if we create an awake method to grab that component off of the object, we can say shooter

47
00:03:23,140 --> 00:03:26,110
equals get component of type shooter.

48
00:03:27,490 --> 00:03:30,250
Now back down in our on fire method.

49
00:03:30,250 --> 00:03:36,610
First of all, we can check whether we've got that shooter script so we can say if shooter does not

50
00:03:36,610 --> 00:03:37,630
equal null.

51
00:03:37,870 --> 00:03:40,290
In other words, did we find it attached?

52
00:03:40,300 --> 00:03:48,670
And if we did, we can set shooter is firing to be equal to the value dot is pressed.

53
00:03:49,090 --> 00:03:51,760
Now that's really all we need to do for our player script.

54
00:03:51,760 --> 00:03:57,070
So let's head back over into our shooter script and have a think about how we're going to start instantiating

55
00:03:57,070 --> 00:03:58,090
our projectiles.

56
00:03:58,570 --> 00:04:03,850
Well, for things like this, I'm quite a big fan of KO routines and we've seen KO routines once, so

57
00:04:03,850 --> 00:04:06,820
this is very good practice to try writing another one.

58
00:04:07,090 --> 00:04:12,130
Before we do that, let's set up the framework that this routine is going to sit in because we're going

59
00:04:12,130 --> 00:04:17,250
to control the starting and stopping of this routine within a fire method.

60
00:04:17,260 --> 00:04:20,110
This fire method is going to be checked every update.

61
00:04:20,110 --> 00:04:22,990
So let's write a dummy method called fire.

62
00:04:23,080 --> 00:04:25,390
And then under this we're going to write that method.

63
00:04:25,390 --> 00:04:27,220
So void fire.

64
00:04:28,780 --> 00:04:31,420
And this is where we're going to start that code routine.

65
00:04:31,930 --> 00:04:37,570
And since this routine is essentially going to allow us to fire continuously, it would make sense to

66
00:04:37,570 --> 00:04:40,060
call this routine fire continuously.

67
00:04:41,120 --> 00:04:45,800
So finally, let's put the bones of that routine in place as well to get rid of our red squiggly.

68
00:04:45,800 --> 00:04:52,220
And if you remember, a coyote has a return type of eye enumerator, and we're going to call this fire

69
00:04:52,220 --> 00:04:53,120
continuously.

70
00:04:56,530 --> 00:04:58,180
With the bones all set up.

71
00:04:58,180 --> 00:05:00,610
We're not going to worry about the red squiggly there for the moment.

72
00:05:00,610 --> 00:05:03,610
That's just because we don't have the return type set up yet.

73
00:05:03,820 --> 00:05:09,150
But before we go ahead and write that coating, let's just think about the logic in our fire method.

74
00:05:09,160 --> 00:05:14,170
The way this is going to work is that if our player script tells us that we are currently firing, then

75
00:05:14,170 --> 00:05:16,060
we want to start this routine.

76
00:05:16,060 --> 00:05:18,640
Otherwise, we want to stop our routine.

77
00:05:18,940 --> 00:05:21,640
To start our coating will be nice and simple.

78
00:05:21,640 --> 00:05:27,700
We're going to say that if is firing so that's controlled by that public boolean, then we want to go

79
00:05:27,700 --> 00:05:29,680
ahead and start our routine.

80
00:05:30,800 --> 00:05:31,490
Else.

81
00:05:31,490 --> 00:05:33,690
We want to stop our car routine.

82
00:05:33,710 --> 00:05:36,140
Now, how do we stop a routine?

83
00:05:36,170 --> 00:05:40,410
Well, there are a couple of options, depending on how brute force you want to be with it.

84
00:05:40,430 --> 00:05:43,880
One option is to just say stop or kill routines.

85
00:05:44,780 --> 00:05:48,110
This will indiscriminately stop any routine that's running.

86
00:05:48,230 --> 00:05:53,030
But it is kind of like taking a hammer to the problem, and we want to be a little bit more surgical.

87
00:05:53,150 --> 00:05:56,510
So the other option is to stop routine.

88
00:05:57,200 --> 00:06:02,570
And then tell it what coating to stop and to tell it which Curry team to stop.

89
00:06:02,570 --> 00:06:08,810
What we're actually going to do is when we start our routine, we're going to store this as a variable.

90
00:06:08,810 --> 00:06:12,770
So this is another really powerful thing that you can do with curry taint.

91
00:06:13,130 --> 00:06:18,350
If we head to the top of our class and create a new variable, this variable is going to be of type

92
00:06:18,350 --> 00:06:22,070
CO routine and we're going to call it our foreign CO routine.

93
00:06:23,370 --> 00:06:29,520
Then we can set this variable by again heading down into fire and where we're starting our routine.

94
00:06:29,730 --> 00:06:35,400
We just want to say that our firing routine is equal to that started routine.

95
00:06:35,580 --> 00:06:40,920
Then with that variable set in our block, we can stop our firing routine.

96
00:06:41,190 --> 00:06:45,030
Now, whilst this will do something, it isn't going to be quite what we want.

97
00:06:45,030 --> 00:06:50,790
So we will have to come back and adjust our if and our else statement, add some extra information in

98
00:06:50,820 --> 00:06:51,140
there.

99
00:06:51,150 --> 00:06:56,910
But before we do that, let's go ahead and actually write our code routine, get some projectiles instantiating

100
00:06:56,910 --> 00:07:02,430
into the world, and then we can see the flaws in this current setup and how we might fix it.

101
00:07:02,880 --> 00:07:06,660
And writing this routine is going to be a challenge for you.

102
00:07:07,020 --> 00:07:14,340
I want you to write the logic for our fire continuously routine, and this chi routine will loop indefinitely.

103
00:07:14,340 --> 00:07:17,670
So think about how to create an infinite loop intentionally.

104
00:07:17,700 --> 00:07:22,260
It will instantiate a projectile for every loop around this infinite loop.

105
00:07:22,260 --> 00:07:28,020
And we also want to set up the destruction of this instantiated projectile after the projectile lifetime

106
00:07:28,020 --> 00:07:29,160
has expired.

107
00:07:29,160 --> 00:07:34,470
And as a hint for this one, check out the overloaded versions of the destroy method that we've used

108
00:07:34,470 --> 00:07:35,190
before.

109
00:07:35,520 --> 00:07:40,860
Finally, we want to wait for the time specified by a variable we're going to call fire rate, and we

110
00:07:40,860 --> 00:07:42,270
haven't actually written this variable yet.

111
00:07:42,270 --> 00:07:44,800
So go ahead and add this one as well.

112
00:07:44,820 --> 00:07:49,860
So quite a big challenge with a lot of moving parts, but pause the video now and give it your very

113
00:07:49,860 --> 00:07:50,700
best shot.

114
00:07:56,170 --> 00:07:56,620
Okay.

115
00:07:56,620 --> 00:07:57,470
Welcome back.

116
00:07:57,490 --> 00:08:02,830
So the first thing I'm going to do is add our missing variable for our delaying of our routine.

117
00:08:02,980 --> 00:08:06,250
We're going to set this as a serialized field so we have some control.

118
00:08:06,640 --> 00:08:10,480
It's going to be of Type Float and we're going to call it the firing rate.

119
00:08:10,810 --> 00:08:14,230
And by default, let's set that to maybe around 0.2.

120
00:08:14,260 --> 00:08:20,410
Then down in our routine, we said we wanted this to loop indefinitely because we are going to be controlling

121
00:08:20,410 --> 00:08:24,410
the starting and stopping of our routine within our fire method.

122
00:08:24,430 --> 00:08:29,530
And to intentionally create an infinite loop, we can say while true.

123
00:08:30,280 --> 00:08:34,380
So inside of our infinite loop, we wanted to create a new projector.

124
00:08:34,390 --> 00:08:39,850
And for this I'm going to instantiate it directly into a temporary variable of type game object.

125
00:08:39,850 --> 00:08:47,170
And I'll call this the instance, and this is going to be equal to instantiate our projectile prefab.

126
00:08:47,410 --> 00:08:53,080
And while I'm here, I'm going to set the position to the transform dot position so it'll be created

127
00:08:53,080 --> 00:08:55,240
at the position of the player's ship.

128
00:08:55,240 --> 00:09:01,360
And because we've specified a position, we also need to specify a rotation and we can specify no rotation

129
00:09:01,360 --> 00:09:03,730
with Quaternions identity.

130
00:09:04,300 --> 00:09:07,900
Now this line is a little long, so let's break it up then.

131
00:09:07,900 --> 00:09:14,170
I said we wanted to destroy this instantiated object after its lifetime had expired so we can use the

132
00:09:14,170 --> 00:09:15,820
destroy method for this.

133
00:09:15,820 --> 00:09:21,160
The thing we want to destroy is our instance and we want to destroy it after the projectile lifetime

134
00:09:21,160 --> 00:09:22,270
has expired.

135
00:09:22,390 --> 00:09:26,650
Finally, we want to yield our routine and wait for the firing rate.

136
00:09:26,650 --> 00:09:30,010
Time to elapse so we can say yield return.

137
00:09:30,340 --> 00:09:34,000
Remember, routines always have to yield rather than just return.

138
00:09:34,000 --> 00:09:39,310
And we want to return a new wait for seconds of the firing rate.

139
00:09:39,850 --> 00:09:44,290
So let's give that a save and jump into unity to test out what happens.

140
00:09:44,290 --> 00:09:48,400
Like I mentioned before, this, if else block isn't quite what we need.

141
00:09:48,400 --> 00:09:52,630
So let's have a look at what actually happens in this circumstance before we go and fix it.

142
00:09:53,850 --> 00:09:58,230
First of all, let's reopen our play prefab and go down to our shooter script.

143
00:09:58,380 --> 00:10:00,380
This needs a projectile prefab.

144
00:10:00,390 --> 00:10:03,150
So let's drag in our projectile player.

145
00:10:03,660 --> 00:10:08,700
Then if we go ahead and hit play to test this out, we can still move around just fine.

146
00:10:08,730 --> 00:10:12,780
We are getting another reference exception, so we'll look at that in just a moment.

147
00:10:12,990 --> 00:10:20,730
And if we try on fire, we get a whole bunch of projectiles all getting spammed out at once and it's

148
00:10:20,730 --> 00:10:22,380
all going a little bit wrong.

149
00:10:23,190 --> 00:10:24,860
So let's come out of play mode.

150
00:10:24,870 --> 00:10:30,570
And before we fix that dodgy car routine, let's just have a look at the console log error and this

151
00:10:30,570 --> 00:10:34,840
is giving us a null reference exception saying that the routine is null.

152
00:10:34,860 --> 00:10:40,290
Now both of these problems are very easily fixed with our if else, block So let's have a look at what's

153
00:10:40,290 --> 00:10:40,980
happening.

154
00:10:41,100 --> 00:10:45,990
What we're doing is when we press the space bar we're setting is firing to true.

155
00:10:45,990 --> 00:10:48,960
And remember, fire is happening in our update loop.

156
00:10:48,960 --> 00:10:51,030
So it's being called every single frame.

157
00:10:51,030 --> 00:10:54,000
So when we hit our space bar, this is set to true.

158
00:10:54,000 --> 00:10:57,180
And then every single frame we're starting a new routine.

159
00:10:57,570 --> 00:11:03,210
The error in the console, on the other hand, comes from our else block in the time before we hit our

160
00:11:03,210 --> 00:11:03,690
space bar.

161
00:11:03,690 --> 00:11:07,470
So right at the beginning of the game, this variable is going to be null.

162
00:11:07,470 --> 00:11:10,830
So we're trying to stop a routine that hasn't been set.

163
00:11:11,040 --> 00:11:13,350
Now, how do we fix both of these problems?

164
00:11:13,350 --> 00:11:15,990
Well, the first step is to look at our if statement.

165
00:11:15,990 --> 00:11:22,980
What we need to say is that if we are firing and our firing co routine equals null.

166
00:11:22,980 --> 00:11:28,590
So if we haven't set this up already, i.e. we've not called start routine yet, then we're going to

167
00:11:28,590 --> 00:11:29,520
start firing.

168
00:11:29,520 --> 00:11:32,790
Once we've done that, once, this statement will be false.

169
00:11:32,790 --> 00:11:38,490
So even if we're continuously holding down the fire key, we won't continue to start more routines.

170
00:11:38,490 --> 00:11:42,090
So that should slow down our firing rate to the correct speed.

171
00:11:42,090 --> 00:11:48,990
And for the second one, what we're going to say is else if because we need to specify some conditions

172
00:11:48,990 --> 00:11:57,120
and we want to specify that we're not currently firing and our firing routine does not equal null.

173
00:11:57,570 --> 00:12:02,790
Now, this sounds fine in principle, but when we stop a routine like this, we're still going to have

174
00:12:02,790 --> 00:12:05,640
something in our firing routine variable.

175
00:12:05,790 --> 00:12:12,570
So to add to our elseif block, once we've stopped our routine, we're going to set our firing protein

176
00:12:12,570 --> 00:12:14,010
equal to null.

177
00:12:14,340 --> 00:12:17,490
So hopefully the logic checks out there and it all makes sense.

178
00:12:17,610 --> 00:12:22,620
Our projectiles aren't moving anywhere though, so let's make that on next priority and we're going

179
00:12:22,620 --> 00:12:24,630
to do this down in our routine.

180
00:12:24,690 --> 00:12:28,350
If you recall, our projectiles do have a rigid body attached.

181
00:12:28,350 --> 00:12:33,450
So what I'm going to do is once we've created the instance of our projectile, we're going to grab that

182
00:12:33,450 --> 00:12:37,680
reference to the rigid body, and then we're going to apply a velocity to it.

183
00:12:37,680 --> 00:12:42,930
So let's start by grabbing that reference to the rigid body, and so we can do a little bit of extra

184
00:12:42,930 --> 00:12:43,380
checking.

185
00:12:43,380 --> 00:12:49,470
We're going to store this in a temporary variable of type rigid body 2D, and we'll call this r b.

186
00:12:49,740 --> 00:12:55,840
Now we want to go ahead and grab the rigid body component off of our object so we can say instant dot,

187
00:12:55,920 --> 00:12:59,820
get component of type, rigid body, 2D.

188
00:13:00,090 --> 00:13:04,740
And for the extra checking that I was talking about, we're just going to say that if our rigid body

189
00:13:04,740 --> 00:13:10,590
are B does not equal null, then we're going to set the rigid body velocity.

190
00:13:10,590 --> 00:13:17,280
And to set our velocity, we need to give it a direction and a speed well for the direction we can use,

191
00:13:17,280 --> 00:13:19,710
transform, dot up.

192
00:13:19,860 --> 00:13:25,020
And if we hover over this, it says it's the green axis of the transform in world space.

193
00:13:25,440 --> 00:13:29,910
So to explain this in real terms, let's jump back over into unity and click on our player.

194
00:13:29,910 --> 00:13:32,040
And here we can see the green up arrow.

195
00:13:32,040 --> 00:13:35,970
So Transform Up is going to follow this green arrow.

196
00:13:36,330 --> 00:13:43,590
So back in our code we can take our transform up, which has a magnitude of one and multiply it by our

197
00:13:43,590 --> 00:13:45,090
projectile speed.

198
00:13:45,630 --> 00:13:49,710
So with that set, let's save that up and jump back into unity one more time.

199
00:13:50,490 --> 00:13:51,930
Let's jump into play mode.

200
00:13:52,230 --> 00:13:58,560
And as if by magic, we now have projectiles shooting at our enemies, and if we hit them enough times,

201
00:13:58,560 --> 00:14:00,690
then we can destroy our enemies as well.

202
00:14:00,690 --> 00:14:04,170
So we've now got a pretty solid game on our hands.

203
00:14:04,170 --> 00:14:06,450
If we hit the enemies, then we die.

204
00:14:06,450 --> 00:14:10,080
But we now have a way of fighting back and scoring some points.

205
00:14:10,080 --> 00:14:13,770
So congratulations on getting the player projectiles working.

206
00:14:13,770 --> 00:14:18,300
And in the next lecture, we're going to look at amending our code to get the enemies firing back at

207
00:14:18,300 --> 00:14:19,050
the player.

208
00:14:19,050 --> 00:14:22,620
So fantastic work and I'll see you in the next lecture.

