Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:00,200 --> 00:00:03,110
Right now our enemy is defeated with a single bullet.
2
00:00:03,110 --> 00:00:07,939
However, we want to implement a health system to give it a certain amount of health to tank a couple
3
00:00:07,939 --> 00:00:08,690
of shots.
4
00:00:08,690 --> 00:00:12,920
We are going to implement this in a very modular way using an actor component.
5
00:00:12,920 --> 00:00:17,690
This would allow us to use the health system on different actors, even if they aren't in the same inheritance
6
00:00:17,690 --> 00:00:21,380
chain, and it actually also makes it easy to create a plugin.
7
00:00:21,380 --> 00:00:26,570
For example, you could export this actor component as a plugin and actually reuse your health system
8
00:00:26,570 --> 00:00:28,400
across all of your different games.
9
00:00:28,400 --> 00:00:33,050
That way you don't have to remake it from scratch every time, but you could use that time to expand
10
00:00:33,050 --> 00:00:35,180
the system and make it perfect over time.
11
00:00:35,180 --> 00:00:38,870
I will attach a video to this lecture that talks more about blueprint reusability.
12
00:00:38,870 --> 00:00:41,390
You can check out if you're more interested in that topic.
13
00:00:41,780 --> 00:00:44,960
For now, let's just close all of these blueprints on the right.
14
00:00:44,960 --> 00:00:51,440
Just close tabs to the right, and we want to go to blueprints characters and do this in the action
15
00:00:51,440 --> 00:00:55,640
chart because this needs to be shared between the player and the enemies.
16
00:00:55,640 --> 00:00:57,770
So first I want to show you the way.
17
00:00:57,770 --> 00:01:01,970
We're not going to do it in this video, but this is the way that most people do the system.
18
00:01:01,970 --> 00:01:05,060
And we're going to talk about like, why this isn't the ideal way.
19
00:01:05,060 --> 00:01:08,030
This is just for demonstration, so you don't have to follow along.
20
00:01:08,030 --> 00:01:12,800
And the way that people usually make a health system is they go into the variables here on the character
21
00:01:12,800 --> 00:01:14,330
and they just make health.
22
00:01:15,850 --> 00:01:17,410
And set this to float.
23
00:01:17,440 --> 00:01:25,390
They make something like Maxhealth as well and have something like is defeated, for example, and make
24
00:01:25,390 --> 00:01:26,350
this a boolean.
25
00:01:26,350 --> 00:01:32,590
And then when taking damage they will do something like health and then they minus uh subtract and set
26
00:01:32,590 --> 00:01:34,210
the new health to this.
27
00:01:34,210 --> 00:01:34,720
Right.
28
00:01:34,720 --> 00:01:35,680
And this is all fine.
29
00:01:35,680 --> 00:01:36,550
This works.
30
00:01:36,550 --> 00:01:40,540
But as you keep on doing this, you're just going to add more and more variables to the player.
31
00:01:40,540 --> 00:01:45,490
And you're also going to add more and more functions and code in the event graph to the player.
32
00:01:45,490 --> 00:01:48,490
And it gets very hard to understand what belongs where.
33
00:01:48,490 --> 00:01:50,530
And later on you might have a stamina system.
34
00:01:50,530 --> 00:01:55,360
So you have stamina, max stamina, you might have mana, and the entire blueprint is going to become
35
00:01:55,360 --> 00:01:55,930
bloated.
36
00:01:55,930 --> 00:02:01,210
So on top of what I said before of actor components being easily reusable through different projects,
37
00:02:01,210 --> 00:02:06,040
even just for organization purposes, they are great because we can put everything that belongs to health
38
00:02:06,040 --> 00:02:09,699
into a single component, and everything is going to be a lot cleaner.
39
00:02:09,699 --> 00:02:12,370
So now I'm just going to delete all of this again, right?
40
00:02:12,370 --> 00:02:14,140
We don't need this anymore.
41
00:02:14,590 --> 00:02:15,760
Don't need this anymore.
42
00:02:15,760 --> 00:02:20,620
And we're going to create something very similar but in a component which we can then attach to this
43
00:02:20,620 --> 00:02:21,370
blueprint.
44
00:02:22,500 --> 00:02:25,560
So in the content drawer we're just going to go to blueprints.
45
00:02:25,560 --> 00:02:28,770
Right click make a new folder called components.
46
00:02:30,910 --> 00:02:31,930
Open it up.
47
00:02:31,930 --> 00:02:34,600
Right click here and go to blueprint class.
48
00:02:34,600 --> 00:02:38,980
And here under common we have an actor component right.
49
00:02:38,980 --> 00:02:44,170
And here it already says an actor component is a reusable component that can be added to any actor.
50
00:02:44,170 --> 00:02:47,710
And a health system is a pretty perfect example for this.
51
00:02:47,710 --> 00:02:50,200
Just click here to create a new actor component.
52
00:02:50,200 --> 00:02:53,110
And I like to call this BPC for blueprint component.
53
00:02:53,110 --> 00:02:58,510
And we're just going to call it vitality because this isn't just going to be health, it is also going
54
00:02:58,510 --> 00:03:00,520
to be tracking our is defeated state.
55
00:03:00,520 --> 00:03:05,110
So I think vitality is just a better overarching concept than just calling it health.
56
00:03:05,320 --> 00:03:08,470
And we actually have already been using components before.
57
00:03:08,470 --> 00:03:08,860
Right.
58
00:03:08,860 --> 00:03:13,810
So if you go to the action share, you can see the character movement component, the animation component.
59
00:03:13,810 --> 00:03:14,380
Right.
60
00:03:14,380 --> 00:03:19,630
And these have all been created by an engineer at Unreal Engine or in the case of the animation component,
61
00:03:19,630 --> 00:03:23,020
by the creator of the paper XSD plugin as a component.
62
00:03:23,020 --> 00:03:28,930
Just like we have been doing it right now and our BPC vitality, we can just go to add here and just
63
00:03:28,930 --> 00:03:34,990
type BPC vitality and we can just add it here as well, just like the animation component, like the
64
00:03:34,990 --> 00:03:38,830
character movement component, if it doesn't show up for you, maybe you have to compile and save first.
65
00:03:39,400 --> 00:03:43,630
And this is how we can create a component and how we can add it to an actor.
66
00:03:43,630 --> 00:03:47,860
But now we still need to implement the actual functionality in here in the BPC vitality.
67
00:03:47,860 --> 00:03:49,180
So let's open it up.
68
00:03:49,540 --> 00:03:55,240
And again we first want to start with our variables here, just like we did before in the demonstration
69
00:03:55,240 --> 00:03:56,980
I'm going to start with.
70
00:03:57,820 --> 00:04:01,900
I'm going to start with Max health and set it to a float.
71
00:04:02,690 --> 00:04:05,210
And next I want to have the current health.
72
00:04:08,440 --> 00:04:10,540
This is already a float, so this is fine.
73
00:04:10,540 --> 00:04:13,900
And then I also want to have the is defeated state.
74
00:04:13,900 --> 00:04:17,529
And this needs to be a boolean because this can either be true or false.
75
00:04:18,470 --> 00:04:23,210
Now we want to compile and save, so we are able to set the default values here on the right.
76
00:04:23,210 --> 00:04:25,370
So is defeated should be false by default.
77
00:04:25,370 --> 00:04:26,480
So this is fine.
78
00:04:26,600 --> 00:04:31,190
But when it comes to the current health and max health we actually create a problem.
79
00:04:31,400 --> 00:04:34,100
So let's say we want to set the max health to ten.
80
00:04:34,810 --> 00:04:38,050
Of course, when we start the game, we also want the current health to be ten.
81
00:04:38,050 --> 00:04:40,540
So we could also just go here and type in ten.
82
00:04:40,540 --> 00:04:46,780
But now a problem is that if we update the max health, let's say we update this to 15 and we forget
83
00:04:46,780 --> 00:04:48,280
to update the current health.
84
00:04:48,280 --> 00:04:52,120
Well, our max health is going to be 15, but when we start the game we only have ten health.
85
00:04:52,120 --> 00:04:55,330
So this is a very common issue that can easily happen.
86
00:04:55,330 --> 00:04:58,810
So what is better to do is to just set a value for the max health.
87
00:04:58,810 --> 00:05:00,880
We want to use ten and the current health.
88
00:05:00,880 --> 00:05:03,070
It doesn't matter what we set here, we can just set to zero.
89
00:05:03,070 --> 00:05:05,950
And we actually just set the current health right.
90
00:05:05,950 --> 00:05:08,590
Set current health on Beginplay.
91
00:05:08,620 --> 00:05:10,690
We just get the max health here.
92
00:05:11,640 --> 00:05:12,420
Like this.
93
00:05:14,160 --> 00:05:16,710
And set the current health when the game starts.
94
00:05:16,710 --> 00:05:20,370
This way, we can always make sure that we only have to change the max health.
95
00:05:20,370 --> 00:05:23,130
There is not an issue that maybe we forget to type it in.
96
00:05:23,130 --> 00:05:24,840
We just set it when the game starts.
97
00:05:25,920 --> 00:05:27,990
Now just to demonstrate how this works.
98
00:05:27,990 --> 00:05:32,280
Well, compile save and we want to go back to our action char base.
99
00:05:32,280 --> 00:05:34,740
And now the edges on Beginplay.
100
00:05:34,740 --> 00:05:37,170
We can just get the BPC vitality.
101
00:05:37,170 --> 00:05:39,900
And here we can just get max health.
102
00:05:40,710 --> 00:05:42,810
And we can just print this out.
103
00:05:43,970 --> 00:05:44,810
Like this.
104
00:05:45,490 --> 00:05:50,290
Just so you can see, this is how we access anything on this component, right?
105
00:05:50,290 --> 00:05:55,030
I start the game and you can see we have ten max health on the player and also ten max health on the
106
00:05:55,030 --> 00:05:55,660
crab.
107
00:05:56,410 --> 00:06:01,720
What I want to do now is to keep ten health on the player and also as the default, but just set the
108
00:06:01,720 --> 00:06:03,190
crab to three health.
109
00:06:03,520 --> 00:06:12,040
So in the content drawer I can go to characters player no enemies and I have the BP enemy crab.
110
00:06:12,040 --> 00:06:13,840
And in here open the full blueprint.
111
00:06:13,840 --> 00:06:17,350
And again here we have the BPC vitality.
112
00:06:17,350 --> 00:06:22,330
And we can actually have access to this default value here Max health Current health is defeated.
113
00:06:22,330 --> 00:06:24,430
And also on the action chart base right.
114
00:06:24,430 --> 00:06:28,930
We have access to these and we can change the values here, the default values as well.
115
00:06:29,140 --> 00:06:33,520
And on the crab BPC vitality I just want to set this to three.
116
00:06:34,150 --> 00:06:36,010
And current health we don't worry about is defeated.
117
00:06:36,010 --> 00:06:36,880
We don't worry about.
118
00:06:38,560 --> 00:06:41,440
But this way we just changed the health on the crab.
119
00:06:41,440 --> 00:06:42,790
Right, on the top left.
120
00:06:43,530 --> 00:06:44,310
On top left.
121
00:06:44,310 --> 00:06:47,550
You can see now ten health on the player, three health on the crab.
122
00:06:47,550 --> 00:06:49,290
And this is how we can make a component.
123
00:06:49,290 --> 00:06:54,600
But just set the default values differently depending on which blueprint we are using this on.
124
00:06:55,670 --> 00:07:00,740
Now that we have the base for the health system setup, we can open up the projectile.
125
00:07:00,740 --> 00:07:06,380
So we go to blueprints, projectiles, and the base Bpy projectile base.
126
00:07:06,380 --> 00:07:13,790
We want to, instead of calling destroy actor on the action char base, we want to apply damage so we
127
00:07:13,790 --> 00:07:16,220
can just drag off here and apply damage.
128
00:07:16,220 --> 00:07:18,650
This is a function that comes with Unreal Engine.
129
00:07:18,650 --> 00:07:20,300
We didn't create this ourselves.
130
00:07:20,300 --> 00:07:22,580
This is something that already is prepared for us.
131
00:07:22,580 --> 00:07:25,190
And the great thing is it is network ready.
132
00:07:25,460 --> 00:07:28,490
So this would even work for online games right out of the box.
133
00:07:29,760 --> 00:07:31,890
Now just get rid of the destroy actor.
134
00:07:32,280 --> 00:07:34,470
Put this up here through branch only.
135
00:07:35,710 --> 00:07:37,210
Connect the rest.
136
00:07:37,210 --> 00:07:39,580
And here we can set the base damage.
137
00:07:39,580 --> 00:07:41,530
How much damage do we want to apply?
138
00:07:41,530 --> 00:07:45,040
The instigator in this case would be the projectile.
139
00:07:45,310 --> 00:07:51,070
Or we could just pass through the instigator of the projectile, which would be the player or the lizard
140
00:07:51,070 --> 00:07:51,850
later on.
141
00:07:53,240 --> 00:07:55,760
And this you only really need if you have plans to use it.
142
00:07:55,760 --> 00:07:59,570
I don't think we're going to use the instigator so we can just leave it empty.
143
00:07:59,570 --> 00:08:01,010
The same was with the damage causer.
144
00:08:01,010 --> 00:08:02,720
Again, this is very similar with the projectile.
145
00:08:02,720 --> 00:08:08,360
We can just pass these things through and then receive them on the other end damage type class.
146
00:08:08,360 --> 00:08:09,950
Also something we don't have to worry about.
147
00:08:09,950 --> 00:08:13,700
You can have like burning damage, different damage types and then use something there.
148
00:08:13,700 --> 00:08:17,180
Again, the only thing we care about here is the base damage.
149
00:08:17,480 --> 00:08:19,880
And again we could just type in a number here right.
150
00:08:19,880 --> 00:08:23,030
Like one damage for the default projectile, which is correct.
151
00:08:23,030 --> 00:08:25,370
But we want to turn this into a variable.
152
00:08:25,370 --> 00:08:30,140
So promote the variable and just call it projectile damage.
153
00:08:30,320 --> 00:08:35,480
And we can then easily just change the default value here later for the charged projectile for the enemy
154
00:08:35,480 --> 00:08:36,350
projectiles.
155
00:08:36,350 --> 00:08:37,340
So compound safe.
156
00:08:37,340 --> 00:08:40,039
But yes the default value should be one.
157
00:08:40,960 --> 00:08:44,380
So now if we shoot the enemy, still nothing happens.
158
00:08:44,380 --> 00:08:46,300
But it doesn't get destroyed anymore.
159
00:08:46,300 --> 00:08:47,440
This is the first step.
160
00:08:47,440 --> 00:08:52,780
We actually need to use another function on the receiving end to get everything we set in the apply
161
00:08:52,780 --> 00:08:57,910
damage, and the place where we want to implement this is the BP action char base.
162
00:08:58,830 --> 00:09:01,440
And we can just find an empty slot here.
163
00:09:01,800 --> 00:09:03,570
We can also get rid of this print string.
164
00:09:03,570 --> 00:09:04,620
We don't need this anymore.
165
00:09:04,620 --> 00:09:06,120
We know this works now.
166
00:09:06,120 --> 00:09:07,500
And here, an empty slot.
167
00:09:07,530 --> 00:09:10,320
We just right click and type in any damage.
168
00:09:10,740 --> 00:09:14,850
And again this is something that Unreal Engine prepares for us gives to us.
169
00:09:14,850 --> 00:09:18,210
And this is paired with the apply damage.
170
00:09:18,210 --> 00:09:20,640
So the apply damage is going to execute.
171
00:09:20,640 --> 00:09:27,990
And on wherever we call this the damaged actor, it is going to execute this any damage event and everything
172
00:09:27,990 --> 00:09:33,540
we pass in here like the base damage event instigator, all of these things are going to come out on
173
00:09:33,540 --> 00:09:36,720
the other side, and we can then decide what we want to do with these.
174
00:09:37,800 --> 00:09:42,120
So first we just want to print the damage to show you that this actually works.
175
00:09:42,120 --> 00:09:43,080
Let's print it out.
176
00:09:44,370 --> 00:09:50,940
And on the grab you can see one because it receives the message that we want to apply one damage here.
177
00:09:52,260 --> 00:09:56,070
Now we need to actually apply this to the BPC vitality though.
178
00:09:56,580 --> 00:09:58,470
And again, this part, you don't have to follow along.
179
00:09:58,470 --> 00:10:01,020
This is just a demonstration of how not to do it.
180
00:10:01,050 --> 00:10:07,260
We could get the BPC vitality, we can get current health, and we can set current health.
181
00:10:07,930 --> 00:10:09,340
Write like this.
182
00:10:09,340 --> 00:10:17,110
And then we can, from the current health, we can, uh, subtract the damage and just set the new current
183
00:10:17,110 --> 00:10:17,590
health.
184
00:10:17,590 --> 00:10:18,880
And this works.
185
00:10:18,880 --> 00:10:20,080
This works just fine.
186
00:10:20,080 --> 00:10:22,690
But again we made this nice component.
187
00:10:22,690 --> 00:10:28,030
So a function like this, we want to put it inside of the component and make it easily reusable.
188
00:10:28,480 --> 00:10:31,930
So even though this works this is not a good way of going about it.
189
00:10:31,930 --> 00:10:33,700
Instead I just want to delete this.
190
00:10:33,700 --> 00:10:41,350
And inside of BPC vitality, I want to create a function and just call it receive damage.
191
00:10:42,230 --> 00:10:46,670
And in here I want to get the current health.
192
00:10:47,540 --> 00:10:49,640
And set the current health.
193
00:10:49,640 --> 00:10:54,710
And by the way, if you drag out here, if you hold control and let go, you get the getter.
194
00:10:54,710 --> 00:10:57,560
And if you hold alt and let go, you get the setter.
195
00:10:57,560 --> 00:10:59,510
And this is just a nice shortcut.
196
00:11:02,720 --> 00:11:08,840
But anyway, yes, we want to receive the damage and we can set the current health, but we need to
197
00:11:08,840 --> 00:11:10,400
have an input here in this function.
198
00:11:10,400 --> 00:11:10,880
Right.
199
00:11:10,880 --> 00:11:14,690
So for the inputs we can click here to create a new one.
200
00:11:14,690 --> 00:11:18,650
Make it a float and just call it damage right.
201
00:11:18,650 --> 00:11:21,230
This is the incoming damage on this function.
202
00:11:21,230 --> 00:11:23,930
And we want to have the current health minus.
203
00:11:24,520 --> 00:11:29,020
The incoming damage and we have to cross lines here because if we do it the other way, it's not going
204
00:11:29,020 --> 00:11:32,200
to work and just connect this to the current health.
205
00:11:34,230 --> 00:11:36,690
And just to show this, we can print string here again.
206
00:11:37,280 --> 00:11:40,640
And just print the remaining current health.
207
00:11:40,640 --> 00:11:43,580
And in the action chart we can now compile and save.
208
00:11:43,580 --> 00:11:48,890
And here on the BPC vitality, we now just call the receive damage.
209
00:11:48,890 --> 00:11:51,320
We don't have to do anything weird outside of here.
210
00:11:51,320 --> 00:11:56,360
We just have this one nice function and just connect the damage here.
211
00:11:57,010 --> 00:12:01,300
And in our case, again, we don't care about the type instigator and all these kind of things.
212
00:12:01,300 --> 00:12:04,450
And now let's just compile and save and try this out.
213
00:12:04,540 --> 00:12:11,200
You can see if I hit them once we have two remaining health one remaining health zero remaining health.
214
00:12:11,200 --> 00:12:12,760
And we can actually go minus.
215
00:12:12,760 --> 00:12:15,490
So this is something we also want to take care of.
216
00:12:15,490 --> 00:12:19,840
So again in the BPC vitality before we set the current health.
217
00:12:20,530 --> 00:12:22,990
We actually want to use a clamp.
218
00:12:23,860 --> 00:12:25,930
So we can clamp here.
219
00:12:25,930 --> 00:12:26,680
Clamp.
220
00:12:26,680 --> 00:12:27,400
Float.
221
00:12:28,350 --> 00:12:29,370
Go like this.
222
00:12:33,330 --> 00:12:35,190
And this will set a limit.
223
00:12:35,780 --> 00:12:38,240
In both directions, so the minimum could be zero.
224
00:12:38,270 --> 00:12:42,470
We cannot go below zero and the maximum should be our max health.
225
00:12:42,500 --> 00:12:46,370
If we get healed or something like this well this is a damage function, so it's probably not going
226
00:12:46,370 --> 00:12:46,700
to happen.
227
00:12:46,700 --> 00:12:52,520
But if we want to heal somebody for example two we can use a clamp to make sure we cannot over heal.
228
00:12:55,140 --> 00:12:57,090
And let's just try this again now, right?
229
00:12:57,090 --> 00:12:58,590
I can shoot multiple times.
230
00:12:58,590 --> 00:12:59,970
It never goes below zero.
231
00:12:59,970 --> 00:13:02,400
So this fixes the minus damage problem.
232
00:13:03,640 --> 00:13:09,100
The next thing you want to do is that if we take damage after this, we want to check that if we are
233
00:13:09,100 --> 00:13:10,120
defeated or not.
234
00:13:10,120 --> 00:13:17,230
So we can then get current health, get current health, and check for smaller equals or less equals
235
00:13:17,230 --> 00:13:18,730
than zero.
236
00:13:18,730 --> 00:13:20,740
And here we have a branch.
237
00:13:22,660 --> 00:13:23,950
Connect this here.
238
00:13:26,410 --> 00:13:28,360
And we are gonna.
239
00:13:28,630 --> 00:13:33,130
In that case, set is defeated to true.
240
00:13:33,610 --> 00:13:34,630
Just like this.
241
00:13:35,990 --> 00:13:42,920
So we know that every time we receive damage, we also update the is defeated state in case the health
242
00:13:42,920 --> 00:13:44,480
is lower equal to zero.
243
00:13:44,480 --> 00:13:47,990
So we can then use this information here in the receive damage.
244
00:13:47,990 --> 00:13:54,320
Here we can just get our BPC vitality and we check for is defeated, get is defeated.
245
00:13:54,320 --> 00:13:56,510
And in this case we have another branch here.
246
00:13:57,340 --> 00:13:58,300
Like this.
247
00:13:58,300 --> 00:14:03,850
And if the character is defeated now, then we want to call destroy actor.
248
00:14:04,090 --> 00:14:04,840
Right.
249
00:14:04,840 --> 00:14:09,850
So first we apply the damage to the vitality component and then we check for the is defeated.
250
00:14:09,850 --> 00:14:12,070
If we are defeated, we destroy the actor.
251
00:14:12,070 --> 00:14:15,880
And this is the way all of these health systems work, right?
252
00:14:15,880 --> 00:14:18,310
Like this I should once, twice, three times.
253
00:14:18,760 --> 00:14:21,580
The health is zero and the character gets deleted.
254
00:14:22,710 --> 00:14:24,300
And in this case, you might think that.
255
00:14:24,300 --> 00:14:29,160
Why do we even need to have this is defeated state if we're going to destroy the actor anyway?
256
00:14:29,160 --> 00:14:35,640
Well, especially for the player we actually later on don't just want to destroy the player right away
257
00:14:35,640 --> 00:14:37,950
because we want to show the defeated animation.
258
00:14:37,950 --> 00:14:40,410
And there should also be a delay between respawning.
259
00:14:40,410 --> 00:14:43,140
And this is why we want to have the defeated state.
260
00:14:43,880 --> 00:14:47,180
The next thing I want to take care of is making the damage feedback.
261
00:14:47,180 --> 00:14:52,310
Good, because now we shoot the enemy, but you don't really see the enemy react to being shot.
262
00:14:52,310 --> 00:14:53,630
And this doesn't feel good.
263
00:14:53,630 --> 00:14:55,610
This doesn't feel satisfying to the player.
264
00:14:55,970 --> 00:14:58,850
And an easy way to do this is to make the sprite flash.
265
00:14:58,850 --> 00:15:00,680
So that's what we're going to do in the next lesson.
24957
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.