WEBVTT 1 00:00:24.280 --> 00:00:26.200 Hello, this is Youngho Lee 2 00:00:26.200 --> 00:00:31.280 In this unit, we’ll learn about player hit detection and handling player death 3 00:00:31.280 --> 00:00:35.680 First, we’ll implement player health management 4 00:00:35.680 --> 00:00:39.240 To do this, we’ll develop the logic for player hit detection 5 00:00:39.240 --> 00:00:42.400 and then learn how to display this information in the UI 6 00:00:42.400 --> 00:00:44.100 Additionally, we’ll explore 7 00:00:44.100 --> 00:00:47.000 how to create getter and setter properties to handle health values 8 00:00:47.000 --> 00:00:51.160 which will improve accessibility and readability 9 00:00:51.160 --> 00:00:54.920 Next, we’ll implement the logic for handling player death 10 00:00:54.920 --> 00:00:57.370 We’ll cover how to control the animation blueprint 11 00:00:57.370 --> 00:00:59.840 so that the death animation can play 12 00:00:59.840 --> 00:01:02.480 regardless of the player’s current state 13 00:01:03.280 --> 00:01:06.660 Implementing Player Health 14 00:01:10.720 --> 00:01:14.599 Let’s implement the player health system this time 15 00:01:14.599 --> 00:01:17.360 To implement the player health system 16 00:01:17.360 --> 00:01:21.439 I’ll add members related to player health 17 00:01:21.439 --> 00:01:25.439 Let’s move to Visual Studio 18 00:01:25.439 --> 00:01:27.889 In Visual Studio 19 00:01:27.889 --> 00:01:31.219 let’s navigate to the NetTPS character header file 20 00:01:33.879 --> 00:01:36.659 Let’s navigate to the NetTPS chracter head file 21 00:01:39.919 --> 00:01:42.669 I’ll add health-related properties 22 00:01:42.669 --> 00:01:46.400 and members at the bottom 23 00:01:46.400 --> 00:01:48.300 Let’s move to the public section 24 00:01:50.400 --> 00:01:58.320 First, let’s define the player health property 25 00:01:58.320 --> 00:02:06.279 with the attributes EditDefaultsOnly, Blueprint, and ReadOnly 26 00:02:06.279 --> 00:02:10.919 Should we categorize it under HP? 27 00:02:10.919 --> 00:02:16.040 Next, let’s define another property 28 00:02:16.040 --> 00:02:18.440 as a float and name it MaxHP 29 00:02:18.440 --> 00:02:20.859 Let’s set its value to 3 30 00:02:23.239 --> 00:02:25.820 Next, we should ensure that 31 00:02:27.680 --> 00:02:31.279 the current health resets to MaxHP 32 00:02:31.279 --> 00:02:34.639 whenever the player respawns 33 00:02:34.639 --> 00:02:39.439 or needs to be initialized with full health 34 00:02:41.500 --> 00:02:45.240 Next, let’s set up the current remaining health like this 35 00:02:45.240 --> 00:02:51.279 Let’s define it as a UPROPERTY with BlueprintReadOnly attributes 36 00:02:51.279 --> 00:02:54.979 We’ll categorize it under “hp” as well, just like before 37 00:02:57.000 --> 00:03:01.600 Should we use lowercase for float HP? 38 00:03:01.600 --> 00:03:06.800 Let’s set HP equal to MaxHP like this 39 00:03:06.800 --> 00:03:09.350 Let’s also add a UI value 40 00:03:09.350 --> 00:03:13.150 that displays this HP 41 00:03:13.150 --> 00:03:16.120 to our character 42 00:03:16.120 --> 00:03:18.270 Since the player 43 00:03:18.270 --> 00:03:20.570 appears on the screen 44 00:03:20.570 --> 00:03:23.400 you can add the HP display 45 00:03:23.401 --> 00:03:26.720 to the player’s head 46 00:03:26.720 --> 00:03:31.840 the top left corner of the screen 47 00:03:31.840 --> 00:03:34.640 or in the HUD (head-up-display) area 48 00:03:34.640 --> 00:03:37.200 above the head 49 00:03:37.201 --> 00:03:39.120 If you’re implementing two modes 50 00:03:39.120 --> 00:03:44.599 placing it in the top left corner would be for the main character’s display 51 00:03:44.599 --> 00:03:48.240 Next, in our multiplayer scenario, there’ll be other users 52 00:03:48.240 --> 00:03:50.990 I want to display 53 00:03:50.990 --> 00:03:53.439 their remaining HP here like this 54 00:03:53.440 --> 00:03:58.859 So, let’s add another HP value 55 00:03:58.859 --> 00:04:04.000 to use in the UI related to the HP that this user currently has 56 00:04:04.000 --> 00:04:06.750 Let’s move to Visual Studio 57 00:04:06.750 --> 00:04:09.959 Let’s navigate to MainUI.h 58 00:04:09.959 --> 00:04:13.199 We need to a member here to display the player’s health 59 00:04:13.199 --> 00:04:17.449 This member will be used for UI display purposes 60 00:04:17.449 --> 00:04:21.239 not the actual HP used by the player 61 00:04:21.240 --> 00:04:25.979 I’ll add the health-related section here under public 62 00:04:25.979 --> 00:04:31.360 and organize it accordingly later 63 00:04:31.360 --> 00:04:39.879 Let’s add it as UPROPERTY (EditDefaultsOnly, BlueprintReadWrite) 64 00:04:39.879 --> 00:04:43.739 and let’s set the category to “hp” for this property 65 00:04:44.879 --> 00:04:51.440 We’ll set the value as float and initialize HP with a default value of 1.0 66 00:04:51.441 --> 00:04:54.140 Why? As I showed earlier 67 00:04:54.140 --> 00:04:59.279 there will be an HP bar displayed above the character’s head 68 00:04:59.280 --> 00:05:03.159 This is ProgressBar widget 69 00:05:03.159 --> 00:05:07.479 and the starting point of this ProgressBar widget is 0 70 00:05:07.480 --> 00:05:11.899 The endpoint is 1.0 It’s based on percentage 71 00:05:11.899 --> 00:05:16.679 so to have this player’s HP fully filled at 100% 72 00:05:16.679 --> 00:05:19.499 I’ll set it to 1.0 73 00:05:20.679 --> 00:05:25.799 Alright, let’s create a UI widget to use this HP 74 00:05:27.639 --> 00:05:29.939 Let’s switch over to Unreal Editor 75 00:05:29.939 --> 00:05:36.720 and let’s navigate to WBP_MainUI in this NetTPS widget 76 00:05:40.919 --> 00:05:44.300 We’re inside WBP_MainUI now 77 00:05:45.539 --> 00:05:46.859 Next 78 00:05:48.360 --> 00:05:53.720 let’s add a ProgressBar widget here to represent the user’s HP 79 00:05:53.720 --> 00:05:55.140 If you search for “progress” in the palette 80 00:05:56.959 --> 00:06:00.419 you’ll find the ProgressBar widget 81 00:06:00.419 --> 00:06:03.119 Drag and drop this ProgressBar 82 00:06:03.119 --> 00:06:07.450 as a child of the Canvas Panel in the Hierarchy panel 83 00:06:07.450 --> 00:06:09.220 Then the ProgressBar will appear here 84 00:06:10.360 --> 00:06:13.340 Let’s name this ProgressBar 85 00:06:15.800 --> 00:06:17.220 “HealthBar” 86 00:06:19.240 --> 00:06:21.100 “HealthBar” it is 87 00:06:23.919 --> 00:06:29.479 Let’s position and layout this HealthBar 88 00:06:29.479 --> 00:06:32.320 Alright, let’s anchor it 89 00:06:33.720 --> 00:06:38.820 to the top left corner in the Details panel 90 00:06:38.820 --> 00:06:43.959 by selecting the anchor point Left Top 91 00:06:43.959 --> 00:06:48.399 Then it’ll be anchored to the top left corner 92 00:06:48.400 --> 00:06:54.539 and let’s position it with X=10 and Y=10 93 00:06:54.539 --> 00:06:59.099 to offset it slightly from the top left corner 94 00:07:00.039 --> 00:07:05.360 And let’s set the size with a width (X-axis) of around 570 95 00:07:05.360 --> 00:07:09.019 Next, let’s set the height (Y-axis) to around 50 96 00:07:10.479 --> 00:07:12.329 This way 97 00:07:12.329 --> 00:07:15.360 the player’s HP will be displayed like this at the top left corner 98 00:07:17.019 --> 00:07:22.739 Then, to determine 99 00:07:22.739 --> 00:07:23.989 how this ProgressBar will react 100 00:07:23.989 --> 00:07:26.439 and what percentage it will fill 101 00:07:26.439 --> 00:07:28.259 you can find the % under ‘progress’ 102 00:07:29.599 --> 00:07:33.339 in the right Detail panel 103 00:07:35.019 --> 00:07:37.559 There’s a part about the % of progress 104 00:07:37.559 --> 00:07:42.640 If this value is 100%, or in other words, if it is 1, it’ll be completely filled 105 00:07:42.640 --> 00:07:46.399 If I set the value to 1 here, it’ll all turn blue 106 00:07:46.400 --> 00:07:50.259 The filling of this color is under “Fill Color and Opacity” 107 00:07:50.259 --> 00:07:52.679 If you change this value, you can change the color 108 00:07:52.680 --> 00:07:54.699 We’ll leave it as the default 109 00:07:54.700 --> 00:07:59.239 Whether you set the % value to 0 or not, if you set it to 0, it’ll all disappear 110 00:07:59.239 --> 00:08:02.200 If you set it to 0.5, it’ll be half filled and visible 111 00:08:02.200 --> 00:08:05.040 You can create it like this 112 00:08:05.041 --> 00:08:08.760 So, what will the % value here respond to? 113 00:08:08.760 --> 00:08:13.999 It’ll respond to the HP value 114 00:08:13.999 --> 00:08:16.099 we created in Visual Studio 115 00:08:18.678 --> 00:08:22.478 When you bind it here, the current HP won’t show up 116 00:08:22.478 --> 00:08:25.778 So, let’s build the HP value 117 00:08:25.778 --> 00:08:27.020 that we added in Visual Studio once 118 00:08:31.640 --> 00:08:34.440 After a successful build 119 00:08:34.440 --> 00:08:36.559 go back to Unreal Editor 120 00:08:36.560 --> 00:08:39.510 select the Progress Bar, then choose Health Bar 121 00:08:39.510 --> 00:08:43.299 and on the right side, there should be a binding for % 122 00:08:43.299 --> 00:08:44.559 This binding links them together 123 00:08:44.560 --> 00:08:47.360 When you press bind 124 00:08:47.360 --> 00:08:50.699 you’ll see our added HP value showing up 125 00:08:50.699 --> 00:08:51.799 which will link the ProgressBar’s % value to it 126 00:08:51.799 --> 00:08:55.320 making it responsive 127 00:08:56.440 --> 00:08:59.390 So, we can make the ProgressBar’s % value 128 00:08:59.390 --> 00:09:03.079 responsive to this HP value like this 129 00:09:05.679 --> 00:09:07.879 Got it? Now, first press compile 130 00:09:10.200 --> 00:09:14.079 Now that you’ve compiled, let’s go ahead and run it 131 00:09:15.279 --> 00:09:19.329 When you run it 132 00:09:19.329 --> 00:09:22.320 you’ll see the ProgressBar displayed in the top left corner 133 00:09:22.320 --> 00:09:24.719 and you’ll see it filled completely in blue at 100% 134 00:09:30.760 --> 00:09:31.859 Alright 135 00:09:33.519 --> 00:09:36.469 so you’ve seen your health displayed in the top left corner 136 00:09:36.469 --> 00:09:39.480 Let’s try displaying the opponent’s health next 137 00:09:39.498 --> 00:09:42.078 We said we’ll display the opponent’s health above their head 138 00:09:43.220 --> 00:09:45.399 For example, placing it like this 139 00:09:45.399 --> 00:09:50.539 Here, the opponent will also have the same character as me 140 00:09:50.559 --> 00:09:52.009 In network multiplayer 141 00:09:52.009 --> 00:09:54.209 I’ll temporarily set up the BP Third Person here 142 00:09:54.209 --> 00:09:56.400 and place it for testing 143 00:09:59.160 --> 00:10:01.820 And should I rotate it to face towards me? 144 00:10:04.778 --> 00:10:07.558 I’ll add the HP bar 145 00:10:07.558 --> 00:10:12.279 above this character’s head like this 146 00:10:12.279 --> 00:10:14.099 Like this, above the head, as shown 147 00:10:16.678 --> 00:10:19.978 So, currently, mine is displayed in the top left corner 148 00:10:19.978 --> 00:10:22.258 but for others 149 00:10:22.258 --> 00:10:24.008 we’ll add logic to display it 150 00:10:24.008 --> 00:10:26.118 above their heads here 151 00:10:26.118 --> 00:10:28.658 So, to create the HP bar displayed above the head 152 00:10:29.860 --> 00:10:33.000 let’s first define the content 153 00:10:33.001 --> 00:10:36.120 for this head-mounted HP bar 154 00:10:36.120 --> 00:10:39.480 as a widget in a C++ class 155 00:10:39.480 --> 00:10:42.580 Select the C++ class folder 156 00:10:42.580 --> 00:10:46.300 right-click, and choose “New C++ class” 157 00:10:49.718 --> 00:10:53.478 Next, in the new class wizard 158 00:10:53.478 --> 00:10:58.180 inherit from UserWidget by selecting it as the base class 159 00:10:59.440 --> 00:11:00.500 Next 160 00:11:02.559 --> 00:11:07.659 Let’s name this C++ class “HealthBar” 161 00:11:09.920 --> 00:11:11.200 Create class 162 00:11:14.440 --> 00:11:16.659 Go ahead and click “Reload All” to refresh everything 163 00:11:21.178 --> 00:11:26.858 This HealthBar should have the same attributes 164 00:11:26.858 --> 00:11:28.520 for health as the one in the MainUI 165 00:11:28.521 --> 00:11:31.571 So, you’ll drag this part 166 00:11:31.571 --> 00:11:34.740 select it in MainUI.h 167 00:11:34.740 --> 00:11:37.320 press Ctrl+C 168 00:11:37.320 --> 00:11:42.520 and paste it into the header file of HealthBar.h like this 169 00:11:42.521 --> 00:11:46.060 So, the HP shown in MainUI represents itself 170 00:11:46.060 --> 00:11:48.919 when displayed in MainUI 171 00:11:48.920 --> 00:11:51.699 Then, in the HealthBar 172 00:11:51.699 --> 00:11:53.549 when it’s for someone else (not me) 173 00:11:53.549 --> 00:11:57.400 it’ll represent their HP 174 00:11:57.400 --> 00:12:02.500 Alright, let’s create a widget 175 00:12:02.500 --> 00:12:04.479 that inherits from this HealthBar class 176 00:12:04.479 --> 00:12:05.919 First, let’s build once 177 00:12:10.880 --> 00:12:12.819 and then switch over to Unreal Editor 178 00:12:16.479 --> 00:12:22.000 Alright, let’s go into the UI folder here and create a new widget 179 00:12:22.000 --> 00:12:25.420 In the User Interface section, select Widget Blueprint 180 00:12:27.799 --> 00:12:34.479 Now, in the parent class, choose “All Classes” 181 00:12:34.479 --> 00:12:39.919 If you search for “HealthBar,” you’ll find the HealthBar class that we created here 182 00:12:39.919 --> 00:12:40.760 Select 183 00:12:42.799 --> 00:12:48.800 and let’s name it “WBP_HealthBar 184 00:12:51.799 --> 00:12:53.460 Double-click to open it up 185 00:13:00.739 --> 00:13:03.439 Alright, let’s add a ProgressBar 186 00:13:03.439 --> 00:13:05.300 from the Palette here as well 187 00:13:09.359 --> 00:13:13.259 Then, drag the ProgressBar from the Palette 188 00:13:13.259 --> 00:13:14.799 and drop it into the Hierarchy here to register 189 00:13:14.799 --> 00:13:15.980 The screen appears, right? 190 00:13:18.580 --> 00:13:22.630 So, since we’ll attach this above the user’s head 191 00:13:22.630 --> 00:13:24.840 we’ll need to attach a component to the user 192 00:13:24.840 --> 00:13:28.760 We’ll attach it to the Widget Component 193 00:13:28.761 --> 00:13:32.440 so we won’t attach it directly to the canvas like this 194 00:13:32.440 --> 00:13:34.339 Let’s place the ProgressBar here 195 00:13:36.338 --> 00:13:39.798 Next, select the ProgressBar, then on the right side 196 00:13:39.798 --> 00:13:44.159 you’ll need to bind it to respond to the corresponding values 197 00:13:44.159 --> 00:13:47.138 In the percentage section here, you’ll find the binding option 198 00:13:47.138 --> 00:13:49.817 Just select HP here to bind it accordingly 199 00:13:51.840 --> 00:13:52.640 To do that 200 00:13:52.640 --> 00:13:56.597 select the ProgressBar in the widget, then on the right in the Details panel 201 00:13:56.597 --> 00:13:59.137 choose bind next to the percentage and select HP 202 00:14:01.497 --> 00:14:06.297 For HP to appear 203 00:14:06.297 --> 00:14:09.000 ensure that HealthBar is currently selected as the parent class in the upper right corner 204 00:14:09.000 --> 00:14:10.050 Like this, right? 205 00:14:10.050 --> 00:14:13.100 Because we declared HP as a member in HealthBar 206 00:14:13.100 --> 00:14:15.097 that’s why it appears here 207 00:14:15.097 --> 00:14:16.637 let’s press compile 208 00:14:18.299 --> 00:14:21.599 Then, let’s add a component to the character 209 00:14:21.599 --> 00:14:25.199 so that this HP can react 210 00:14:25.199 --> 00:14:28.159 accordingly 211 00:14:28.159 --> 00:14:31.559 To display this component above the head 212 00:14:31.559 --> 00:14:34.119 we need to switch back to Visual Studio 213 00:14:34.119 --> 00:14:38.280 let’s go to NetTPSCharacter in Visual Studio 214 00:14:38.280 --> 00:14:41.320 Let’s add a component to the character 215 00:14:41.320 --> 00:14:43.139 Alright, let’s add 216 00:14:46.520 --> 00:14:51.320 UWidgetComponent at the bottom 217 00:14:51.320 --> 00:14:58.080 with UPROPERTY and VisibleAnywhere class specifier like this 218 00:14:58.080 --> 00:15:02.520 And let’s name it hpUIComp 219 00:15:02.520 --> 00:15:06.470 Let’s attach the HealthBar widget we just created 220 00:15:06.470 --> 00:15:08.760 to this component 221 00:15:12.039 --> 00:15:15.400 Okay, let’s proceed to the constructor for this 222 00:15:15.400 --> 00:15:20.000 Let’s move the constructor section of NetTPSCharacter 223 00:15:20.000 --> 00:15:22.300 Let’s add this content 224 00:15:22.300 --> 00:15:25.520 to the very bottom 225 00:15:25.520 --> 00:15:27.559 of the constructor function 226 00:15:27.559 --> 00:15:32.739 This is for the HealthBar component 227 00:15:37.880 --> 00:15:39.280 Let’s add it 228 00:15:39.280 --> 00:15:46.080 hpUIComp is added using CreateDefaultSubObject 229 00:15:46.080 --> 00:15:51.359 with UWidgetComponent 230 00:15:51.359 --> 00:15:56.880 Let’s name it TEXT HealthBar 231 00:15:56.880 --> 00:16:00.530 Next, let’s attach the HP bar 232 00:16:00.530 --> 00:16:05.640 as a child of the mesh using hpComp 233 00:16:05.640 --> 00:16:10.459 I’ll put it as SetupAttachment(GetMesh()) 234 00:16:14.479 --> 00:16:19.440 Next, at the very top 235 00:16:19.440 --> 00:16:22.490 we’ll add a header 236 00:16:22.490 --> 00:16:24.220 to use this HP widget component 237 00:16:27.000 --> 00:16:29.120 In the #include section 238 00:16:31.559 --> 00:16:36.459 there should be a widget component 239 00:16:39.080 --> 00:16:41.330 in the Comp component 240 00:16:41.330 --> 00:16:43.100 We’ll add this component 241 00:16:45.400 --> 00:16:50.200 and add the WidgetComponent.h under the include component 242 00:16:53.419 --> 00:16:54.140 Done 243 00:17:00.020 --> 00:17:03.479 If you have trouble finding the WidgetComponent header file 244 00:17:03.479 --> 00:17:08.919 you can check where it is located 245 00:17:08.919 --> 00:17:11.400 or you can search for it on Google 246 00:17:11.400 --> 00:17:16.080 If you Google it 247 00:17:16.080 --> 00:17:18.840 you’ll find the WidgetComponent 248 00:17:18.840 --> 00:17:20.599 If you click and check 249 00:17:20.599 --> 00:17:25.200 you can find which header contains the WidgetComponent 250 00:17:25.239 --> 00:17:26.719 You’ll see the header there 251 00:17:26.719 --> 00:17:29.520 It says to include it in the #include section 252 00:17:29.520 --> 00:17:32.159 You can press Ctrl+C to copy it 253 00:17:35.599 --> 00:17:42.719 Alright, you’ve attached the hpUIComp.h component this way 254 00:17:42.719 --> 00:17:44.299 After doing this, let’s build it 255 00:17:50.759 --> 00:17:53.839 Once the build is complete 256 00:17:53.839 --> 00:17:56.919 and you’ve added the new components 257 00:17:56.919 --> 00:17:59.379 go ahead and restart Unreal Engine Editor 258 00:18:02.359 --> 00:18:04.599 Let’s restart it again 259 00:18:04.599 --> 00:18:06.980 The build error is likely due to lingering issues in memory 260 00:18:20.880 --> 00:18:24.480 If there are people working with older versions 261 00:18:24.480 --> 00:18:25.860 just a quick note 262 00:18:25.860 --> 00:18:28.919 in previous versions 263 00:18:28.919 --> 00:18:33.359 like Unreal Engine 3.2 264 00:18:33.359 --> 00:18:37.180 there might have been issues 265 00:18:37.181 --> 00:18:40.520 like this 266 00:18:40.520 --> 00:18:42.479 If you look now, there’s a Build.cs file 267 00:18:42.479 --> 00:18:47.080 In Solution Explorer, you’ll find the NetTPS.Build.cs file 268 00:18:47.080 --> 00:18:50.880 and if you open it, you’ll see the section where modules are registered for use 269 00:18:50.880 --> 00:18:54.960 If you’re trying to use a widget here 270 00:18:54.960 --> 00:18:57.760 you should add the UMG module 271 00:18:57.760 --> 00:18:59.280 by appending it with a comma 272 00:18:59.280 --> 00:19:03.159 in the PublicDependencyModuleNames section 273 00:19:03.159 --> 00:19:05.940 However, right now 274 00:19:05.940 --> 00:19:08.799 we shouldn’t encounter any compilation issues even if we don’t add that 275 00:19:08.799 --> 00:19:13.960 It’s already built-in as of version 5.3, so there shouldn’t be any issues related to that 276 00:19:13.960 --> 00:19:18.039 So, if you’re encountering issues in older or lower versions 277 00:19:18.039 --> 00:19:21.640 and wondering why 278 00:19:21.640 --> 00:19:25.919 it’s because 279 00:19:25.919 --> 00:19:27.200 we’re currently targeting version 5.3.2 for compilation 280 00:19:27.200 --> 00:19:30.159 Versions 5.3.2 and above should not have any problems 281 00:19:30.159 --> 00:19:32.200 but if you’re working with older versions 282 00:19:32.200 --> 00:19:34.760 you’ll need to explicitly add the UMG module in your Build.cs file 283 00:19:34.760 --> 00:19:37.960 As you saw earlier, it’s mentioned as module.umg there 284 00:19:37.960 --> 00:19:40.799 This module needs to be added to that section 285 00:19:40.799 --> 00:19:42.019 In version 5.3.2 286 00:19:45.719 --> 00:19:48.559 this module is already included by default in the Build.cs file 287 00:19:48.559 --> 00:19:50.580 so you don’t need to worry about adding its contents separately 288 00:19:52.520 --> 00:19:56.499 Alright, since the build was successful and Unreal Engine Editor is open 289 00:20:00.719 --> 00:20:04.920 I’ll open the Player BPThirdPerson Blueprint 290 00:20:08.640 --> 00:20:11.959 Currently, our character looks like this 291 00:20:11.959 --> 00:20:14.079 Let’s add a widget to display HP 292 00:20:14.079 --> 00:20:18.560 above the character’s head 293 00:20:18.560 --> 00:20:21.199 On the left side, if you go to the Components panel 294 00:20:21.199 --> 00:20:25.439 you’ll find hpUIComp there 295 00:20:25.439 --> 00:20:29.119 On the right side in the Details panel 296 00:20:29.119 --> 00:20:33.479 you should see a section where you can register the widget component under HealthBar 297 00:20:34.600 --> 00:20:36.620 In the User Interface section 298 00:20:38.216 --> 00:20:40.036 there’s a Widget class section, right? 299 00:20:43.840 --> 00:20:48.779 Here, it currently says “None” 300 00:20:49.776 --> 00:20:51.176 Select this section 301 00:20:51.176 --> 00:20:55.640 and choose our WBP HealthBar widget 302 00:20:55.640 --> 00:20:56.980 that we’re using 303 00:21:00.620 --> 00:21:01.370 It’s done 304 00:21:01.370 --> 00:21:03.670 Then WBP HealthBar will appear like this 305 00:21:03.670 --> 00:21:04.996 But it looks like the size is too large 306 00:21:04.996 --> 00:21:06.276 correct? 307 00:21:07.960 --> 00:21:12.000 So, let’s adjust the Draw Size settings for it now 308 00:21:12.000 --> 00:21:14.736 The draw size settings are right below 309 00:21:14.736 --> 00:21:19.936 Should we set it to around 100 by 10 for this? 310 00:21:19.936 --> 00:21:23.000 Then if you go down to the feet, it should look like this 311 00:21:27.420 --> 00:21:32.056 The current position of the widget component seems a bit off 312 00:21:32.056 --> 00:21:35.176 Let’s adjust the widget component’s position as well 313 00:21:36.840 --> 00:21:42.090 Select hpUIComp HealthBar in the right Details panel 314 00:21:42.090 --> 00:21:48.400 then in the Transform section, set the Z value to 200 to move it upward 315 00:21:48.400 --> 00:21:50.439 Then it should now appear above the head 316 00:21:50.439 --> 00:21:53.920 Since it’s partially rotated, let’s rotate it 90 degrees 317 00:21:53.936 --> 00:21:56.296 By rotating it 90 degrees around the Z-axis 318 00:21:58.380 --> 00:22:02.920 the HealthBar will face forward 319 00:22:02.920 --> 00:22:03.979 Compile it now 320 00:22:09.239 --> 00:22:12.139 Let’s run it to see how it looks 321 00:22:12.139 --> 00:22:15.600 Then it should appear above the user’s head now, right? 322 00:22:15.600 --> 00:22:16.239 You can see 323 00:22:17.716 --> 00:22:20.496 how the HP bar is represented 324 00:22:24.396 --> 00:22:27.936 Now that we have the HP bar set up 325 00:22:27.936 --> 00:22:29.936 we need to add functionality 326 00:22:29.936 --> 00:22:31.479 to handle getting hit 327 00:22:31.480 --> 00:22:34.639 when the user is shot 328 00:22:34.639 --> 00:22:38.799 So, let’s proceed to add functionality 329 00:22:38.800 --> 00:22:40.350 to shoot the user and handle the hit response 330 00:22:40.350 --> 00:22:42.739 Let’s switch over to Visual Studio 331 00:22:42.739 --> 00:22:46.200 Let’s navigate to NetTPSCharacter 332 00:22:46.200 --> 00:22:47.800 Let’s register the hit handling function 333 00:22:49.976 --> 00:22:52.800 at the bottom part 334 00:22:52.800 --> 00:22:56.540 and add void DamageProcess as the function name 335 00:22:59.800 --> 00:23:03.700 Alright, let’s add DamageProcess and implement its functionality 336 00:23:05.040 --> 00:23:10.379 You’ve added DamageProcess to NetTPSCharacter.cpp file 337 00:23:12.836 --> 00:23:15.996 Alright, the task here is straightforward 338 00:23:15.999 --> 00:23:17.249 If the user shoots me 339 00:23:17.249 --> 00:23:21.920 and I get hit, then I should decrease the health 340 00:23:21.921 --> 00:23:23.680 We’ll do this right away 341 00:23:23.680 --> 00:23:26.959 You can decrease the HP by subtracting from its current value 342 00:23:29.600 --> 00:23:32.340 Let’s simply reduce the HP value 343 00:23:34.416 --> 00:23:38.296 When will this DamageProcess function be called then? 344 00:23:38.296 --> 00:23:42.519 Where does it happen when the user shoots me? 345 00:23:42.519 --> 00:23:45.696 They’re going to shoot me when they fire 346 00:23:45.696 --> 00:23:48.156 so let’s go to the fire function 347 00:23:50.536 --> 00:23:52.856 Move to the fire function 348 00:23:54.120 --> 00:23:57.680 In NetTPSCharacter 349 00:23:57.680 --> 00:24:00.280 if you scroll down to the fire function 350 00:24:00.280 --> 00:24:02.460 you’ll see that it mentions displaying particles at the hit location 351 00:24:03.760 --> 00:24:07.359 Shall we add it right below this section? 352 00:24:07.359 --> 00:24:12.459 Let’s handle damage processing here 353 00:24:14.476 --> 00:24:16.896 if the target is an opponent 354 00:24:16.896 --> 00:24:19.346 If the shot hits the ground or a wall 355 00:24:19.346 --> 00:24:22.159 the opponent shouldn’t bleed or fall down 356 00:24:22.160 --> 00:24:25.619 I’ll set it up 357 00:24:25.619 --> 00:24:30.059 so that damage processing occurs only when the target is oneself or a Pawn 358 00:24:31.376 --> 00:24:34.616 There are several ways to validate this 359 00:24:34.616 --> 00:24:37.140 You can detect the target by its name 360 00:24:37.879 --> 00:24:41.200 or by casting it to see 361 00:24:41.201 --> 00:24:43.240 what it hits 362 00:24:43.240 --> 00:24:44.390 If you check the HitInfo 363 00:24:44.390 --> 00:24:48.519 you can use GetActor to retrieve the hit actor 364 00:24:48.520 --> 00:24:50.270 You can cast this actor 365 00:24:50.270 --> 00:24:51.820 to determine its type 366 00:24:51.820 --> 00:24:52.619 How? 367 00:24:52.619 --> 00:24:54.269 NetTPSCharacter 368 00:24:54.269 --> 00:24:59.019 To determine if the actor is of type NetTPSCharacter, you can cast it to check if it’s the opponent you want to process 369 00:24:59.019 --> 00:25:01.760 So let’s proceed with casting it to the type 370 00:25:01.761 --> 00:25:07.020 Use auto and Cast to attempt casting to otherPlayer 371 00:25:07.020 --> 00:25:11.999 I’ll cast it 372 00:25:12.000 --> 00:25:15.259 to ANetTPSCharacter here 373 00:25:15.259 --> 00:25:18.059 If the casting is done correctly 374 00:25:18.059 --> 00:25:19.240 the value will be assigned 375 00:25:19.240 --> 00:25:24.460 If it fails to cast to the NetTPSCharacter type, it’ll be null 376 00:25:26.879 --> 00:25:31.600 So, if otherPlayer exists, the type casting was successful 377 00:25:31.600 --> 00:25:35.950 I will call DamageProcess 378 00:25:35.950 --> 00:25:37.480 on otherPlayer 379 00:25:43.840 --> 00:25:46.155 I’ll call DamageProcess like this 380 00:25:46.155 --> 00:25:48.215 Let’s build it next 381 00:25:58.900 --> 00:26:03.600 Alright, it’s done. We have now modified the hp value here 382 00:26:03.600 --> 00:26:07.980 However, the hp value we modified is 383 00:26:09.879 --> 00:26:15.679 actually the hp in NetTPSCharacter 384 00:26:15.680 --> 00:26:17.330 For the UI to update 385 00:26:17.330 --> 00:26:21.539 the hp in the healthbar needs to be refreshed, right? 386 00:26:21.539 --> 00:26:24.920 Or the hp in the MainUI needs to be updated 387 00:26:24.921 --> 00:26:30.680 or in any case, the hp value in the UI class needs to reflect the changes 388 00:26:30.680 --> 00:26:34.959 but currently, we’re modifying the hp in the NetTPSCharacter 389 00:26:34.959 --> 00:26:37.409 They’re different sets of data 390 00:26:37.409 --> 00:26:39.800 They have different data sets 391 00:26:39.801 --> 00:26:42.360 My name and everyone else’s names are different, right? 392 00:26:42.360 --> 00:26:45.399 The variable name is the same, but the values inside are different 393 00:26:45.399 --> 00:26:47.249 Changing my name 394 00:26:47.249 --> 00:26:49.439 doesn’t change your names 395 00:26:49.440 --> 00:26:52.759 So, think that as this kind of format now 396 00:26:52.759 --> 00:26:56.009 So, to ensure that these values are updated correctly 397 00:26:56.009 --> 00:26:59.920 we need to update the values in the UI 398 00:26:59.921 --> 00:27:03.040 that contain this hp as well 399 00:27:03.040 --> 00:27:06.140 Then I need to add this content here 400 00:27:06.140 --> 00:27:11.939 and we can add it when DamageProcess is called 401 00:27:11.939 --> 00:27:14.480 For example, we would do it like this 402 00:27:14.480 --> 00:27:16.519 Let’s implement it here 403 00:27:18.659 --> 00:27:25.959 I’ve reduced the hp Now let’s calculate the float percentage after reducing it 404 00:27:25.959 --> 00:27:32.055 Calculating the % to assign to the UI 405 00:27:32.055 --> 00:27:34.555 If we set float % 406 00:27:36.279 --> 00:27:42.240 and divide hp by MaxHP, what happens? 407 00:27:42.240 --> 00:27:48.720 We have an initial value of 408 00:27:50.640 --> 00:27:53.140 3 for hp, right? 409 00:27:53.140 --> 00:27:55.440 It’s 3 now 410 00:27:55.440 --> 00:27:57.760 Then, when MaxHP is 3 411 00:27:57.761 --> 00:28:00.611 float % becomes 1, representing 100% 412 00:28:00.611 --> 00:28:02.860 Then, if it’s currently decreased to 2 413 00:28:02.860 --> 00:28:06.600 then, it would reflect the decreased percentage 414 00:28:07.940 --> 00:28:10.890 I’ll calculate it in this way 415 00:28:10.890 --> 00:28:12.800 Alright, then if there’s 416 00:28:15.535 --> 00:28:17.995 a MainUI 417 00:28:18.415 --> 00:28:24.200 we’ll insert the percentage 418 00:28:25.760 --> 00:28:28.399 into the hp 419 00:28:28.839 --> 00:28:31.959 on the MainUI 420 00:28:32.339 --> 00:28:36.660 Using MainUI means referring to itself 421 00:28:36.660 --> 00:28:39.510 For the opponent, things like crosshairs or bullets 422 00:28:39.510 --> 00:28:41.200 don’t need to be displayed 423 00:28:41.200 --> 00:28:44.700 Here, you can see that I’ve played 424 00:28:44.700 --> 00:28:45.800 When I’m playing 425 00:28:48.095 --> 00:28:51.035 my bullets are displayed like this 426 00:28:51.035 --> 00:28:54.959 and I can also show my hp at the top like this 427 00:28:54.959 --> 00:28:56.909 But for the opponent 428 00:28:56.909 --> 00:28:59.119 it’s enough to display things like their headshot indicator 429 00:28:59.120 --> 00:29:01.220 there’s no need to show details 430 00:29:01.220 --> 00:29:03.159 like remaining bullets at the bottom, right? 431 00:29:03.159 --> 00:29:05.609 So, for them 432 00:29:05.609 --> 00:29:08.510 while they’re using the same class 433 00:29:08.510 --> 00:29:11.900 only my side needs MainUI, right? 434 00:29:11.900 --> 00:29:15.040 The opponent doesn’t need MainUI 435 00:29:15.041 --> 00:29:18.260 So, if there’s MainUI, it’s for me 436 00:29:18.260 --> 00:29:21.920 If there’s no MainUI, we’ll distinguish it as being for the opponent 437 00:29:21.921 --> 00:29:25.600 So, we won’t create MainUI widget unconditionally 438 00:29:25.601 --> 00:29:29.440 we’ll create it only when it’s for myself 439 00:29:29.440 --> 00:29:34.360 When it’s the opponent’s turn, we’ll ensure that the MainUI widget isn’t created 440 00:29:34.360 --> 00:29:37.660 Alright, let’s handle the cases where MainUI exists and where it doesn’t 441 00:29:37.660 --> 00:29:40.600 by writing it separately 442 00:29:40.600 --> 00:29:45.319 If MainUI exists, then when my health decreases 443 00:29:46.319 --> 00:29:51.260 we’ll set up an “auto hpUI” and cast it to 444 00:29:51.260 --> 00:29:54.680 the HealthBar on my head, which is UHealthBar 445 00:29:58.360 --> 00:30:03.500 We’ve registered hpUIComp with get-widget 446 00:30:05.895 --> 00:30:09.555 we should link hp from hpUI 447 00:30:09.555 --> 00:30:15.279 to correspond with this percentage here 448 00:30:15.280 --> 00:30:18.299 We set the hp value according to this percentage 449 00:30:18.299 --> 00:30:22.839 You need to include UHealthBar at the top 450 00:30:24.839 --> 00:30:30.599 Please include the HealthBar header file using #include 451 00:30:32.880 --> 00:30:35.160 In the NetTPSCharacter.cpp file 452 00:30:45.759 --> 00:30:49.719 as mentioned earlier, MainUI isn’t created unconditionally 453 00:30:49.720 --> 00:30:52.399 It’s only created when it’s for oneself 454 00:30:52.399 --> 00:30:56.719 So, the place where MainUI is created 455 00:30:56.759 --> 00:30:58.859 is in InitUIWidget 456 00:30:58.859 --> 00:31:03.039 You’re creating MainUI in InitUIWidget right now 457 00:31:03.040 --> 00:31:05.659 You need to handle 458 00:31:05.659 --> 00:31:09.820 some conditional branching before InitUIWidget 459 00:31:12.120 --> 00:31:15.870 One way to distinguish whether it’s the main character or the opponent character is 460 00:31:15.870 --> 00:31:17.560 by using methods like this 461 00:31:17.561 --> 00:31:20.140 For the player 462 00:31:20.141 --> 00:31:23.380 how it’s structured is 463 00:31:23.380 --> 00:31:26.360 typically visible in the right-hand outliner 464 00:31:26.361 --> 00:31:31.780 If I search for “PlayerController” here 465 00:31:31.780 --> 00:31:35.839 I can see that there’s exactly one PlayerController in the world 466 00:31:35.839 --> 00:31:40.960 What do we call these characters we see on the screen now? 467 00:31:42.719 --> 00:31:46.880 We call these characters Pawns, and this is also a Pawn 468 00:31:48.834 --> 00:31:51.894 Oh, isn’t it a character? Doesn’t it inherit from Character? 469 00:31:51.894 --> 00:31:53.744 Characters also inherit from Pawn 470 00:31:53.744 --> 00:31:55.120 So, we refer to it as a Pawn 471 00:31:55.121 --> 00:31:58.380 However, this Pawn doesn’t move independently 472 00:31:58.380 --> 00:32:00.630 it’s set up to receive user input 473 00:32:00.630 --> 00:32:01.319 and process actions accordingly 474 00:32:01.320 --> 00:32:04.359 So, it’s set up to receive user control 475 00:32:04.359 --> 00:32:08.079 So, PlayerController is responsible for receiving and handling user input 476 00:32:08.080 --> 00:32:10.699 It directly represents you and others 477 00:32:10.699 --> 00:32:16.120 The object that represents the user in this virtual space is the PlayerController 478 00:32:16.134 --> 00:32:19.394 The PlayerController directly possesses this Pawn 479 00:32:20.720 --> 00:32:22.870 When we possess this Pawn 480 00:32:22.870 --> 00:32:26.040 we finally gain control over it 481 00:32:26.041 --> 00:32:29.700 This structure means that since it’s ours 482 00:32:29.701 --> 00:32:33.300 I directly possess it 483 00:32:33.300 --> 00:32:36.480 and move it forward, backward, left, and right by pressing the arrow keys 484 00:32:36.481 --> 00:32:39.960 Right? I can shoot the gun 485 00:32:39.960 --> 00:32:41.959 but since I’m not possessing this guy 486 00:32:43.814 --> 00:32:47.554 I can’t control him 487 00:32:47.560 --> 00:32:51.440 This is typically how we use AI for control 488 00:32:51.441 --> 00:32:55.320 So, currently, it doesn’t have a PlayerController 489 00:32:55.320 --> 00:32:58.079 but this does have a PlayerController 490 00:32:58.080 --> 00:33:01.759 Then we can distinguish whether this is me or not 491 00:33:01.759 --> 00:33:05.839 based on the presence of the PlayerController 492 00:33:05.840 --> 00:33:10.239 So if the PlayerController is present, you create the MainUI 493 00:33:10.239 --> 00:33:13.020 and if the PlayerController is absent, you create this instead 494 00:33:17.234 --> 00:33:20.414 Then let’s switch back to Visual Studio 495 00:33:20.440 --> 00:33:27.259 In teh InitUIWidget, if the player is not in control 496 00:33:27.260 --> 00:33:30.639 do we process the section below? No we don’t need to 497 00:33:30.639 --> 00:33:33.189 Because we’re not going to create the MainUI 498 00:33:33.189 --> 00:33:38.560 I will ensure that it doesn’t process if the player isn’t in control 499 00:33:38.560 --> 00:33:42.180 First, declare auto PlayerController pc 500 00:33:42.180 --> 00:33:46.319 Then, cast it as APlayerController 501 00:33:46.320 --> 00:33:49.599 I’ll get the Controller object 502 00:33:49.599 --> 00:33:53.549 This Pawn is also said to be a NetTPSCharacter 503 00:33:53.549 --> 00:33:55.060 When the Pawn is spawned 504 00:33:55.060 --> 00:33:59.110 it’s curently set to 505 00:33:59.110 --> 00:34:01.174 automatically possess the PlayerController 506 00:34:01.174 --> 00:34:02.024 So, because of that setup 507 00:34:02.024 --> 00:34:05.534 the variable “Controller” here has a value assigned to it 508 00:34:05.534 --> 00:34:09.819 But if it doesn’t have a value or if something like an AI controller is assigned instead 509 00:34:09.820 --> 00:34:11.270 then it’s not a PlayerController 510 00:34:11.270 --> 00:34:14.279 So, here it won’t have a value 511 00:34:14.279 --> 00:34:16.429 If the PlayerController is properly assigned 512 00:34:16.429 --> 00:34:18.300 pc will have a value 513 00:34:18.301 --> 00:34:21.920 So, if pc is a null pointer 514 00:34:21.920 --> 00:34:25.570 then we’ll implement it so that we won’t process the following content 515 00:34:25.570 --> 00:34:26.940 in the return statement if pc is null 516 00:34:29.314 --> 00:34:30.680 Oh, then what atbout the healthbar? 517 00:34:30.680 --> 00:34:34.140 Since I’ve just attached it to myself as a component, it’s definitely there 518 00:34:35.940 --> 00:34:37.200 That’s how it’s set up 519 00:34:39.180 --> 00:34:41.939 Let’s go ahead and give it a try by playing it first 520 00:34:43.094 --> 00:34:45.394 I’ll go ahead and build it first, then we can play 521 00:34:52.600 --> 00:34:53.365 Press Play 522 00:34:58.819 --> 00:35:04.880 Go grab the gun and shoot 523 00:35:04.881 --> 00:35:08.400 Hmm, that does sound odd 524 00:35:08.401 --> 00:35:09.560 Let’s try reloading 525 00:35:10.920 --> 00:35:14.770 and aiming at the target again 526 00:35:14.770 --> 00:35:17.579 It feels like it’s hitting the back instead of the front, right? 527 00:35:17.580 --> 00:35:20.679 It seems like it’s hitting the wrong side 528 00:35:20.680 --> 00:35:24.279 like hitting the wall or the opposite side of the body 529 00:35:24.279 --> 00:35:27.380 Why is that happening? 530 00:35:27.381 --> 00:35:32.580 Let’s try the capsule component of this BPThirdPersonCharacter when we shoot 531 00:35:32.580 --> 00:35:34.230 Select the capsule component 532 00:35:34.230 --> 00:35:37.139 then scroll down in the details panel on the right 533 00:35:37.139 --> 00:35:38.839 until you find the “Collision” section 534 00:35:38.839 --> 00:35:41.174 There’s a collision presets section in the collision settings 535 00:35:41.174 --> 00:35:43.754 Let me expand that for you 536 00:35:44.880 --> 00:35:46.980 Under “Collision Presets” 537 00:35:48.060 --> 00:35:51.360 you’ll find Trace Response under Collision Response 538 00:35:51.360 --> 00:35:54.819 The Trace Response in the Collision Presets 539 00:35:54.819 --> 00:35:59.919 determines how the capsule component reacts when the gun fires 540 00:35:59.919 --> 00:36:04.109 I’m performing a line trace with visibility option in the trace channel 541 00:36:04.109 --> 00:36:06.879 to check for collisions 542 00:36:06.879 --> 00:36:10.060 So, currently 543 00:36:10.061 --> 00:36:12.520 in the Collision Presets of the capsule component 544 00:36:12.520 --> 00:36:16.499 the Trace Response under Visibililty is set to Ignore 545 00:36:16.499 --> 00:36:18.349 which means it’s ignoring collisions when performing the line trace 546 00:36:18.349 --> 00:36:20.620 That’s why collisions are not being detected 547 00:36:20.621 --> 00:36:23.171 So, let’s change it to block collisions 548 00:36:23.171 --> 00:36:24.340 How? 549 00:36:24.340 --> 00:36:26.940 In the Collision Presets, select Pawn 550 00:36:26.940 --> 00:36:29.380 from the dropdown and change it to Custom 551 00:36:31.620 --> 00:36:35.839 Now that you’ve selected Custom, go ahead and change it to Block 552 00:36:37.779 --> 00:36:38.719 and compile 553 00:36:41.253 --> 00:36:45.113 go grab it again and shoot 554 00:36:45.113 --> 00:36:48.780 Then you should be able to confirm that the health points decrease correctly 555 00:36:53.819 --> 00:36:57.579 So now you should be able to see the health points decreasing properly 556 00:36:57.579 --> 00:37:00.759 If you want to 557 00:37:02.579 --> 00:37:04.680 change the hp value 558 00:37:06.459 --> 00:37:10.479 in a more sophisticated way 559 00:37:12.659 --> 00:37:16.120 let’s briefly move to the DamageProcess 560 00:37:17.659 --> 00:37:22.813 When we move to the DamageProcess, we decrease the health value 561 00:37:22.813 --> 00:37:24.833 it’s processed there in this way 562 00:37:27.939 --> 00:37:33.860 Is there a way we can make this value a bit more elegant? 563 00:37:33.860 --> 00:37:36.910 In DamageProcess, changing the hp 564 00:37:36.910 --> 00:37:40.059 in a way that automates everything up to that point 565 00:37:40.059 --> 00:37:43.609 and this is commonly referred to as 566 00:37:43.609 --> 00:37:45.539 using getters and setters without directly manipulating the property 567 00:37:45.540 --> 00:37:49.440 If we refactor it using getter and setter functions 568 00:37:49.440 --> 00:37:51.779 to handle it 569 00:37:51.779 --> 00:37:55.660 we might be able to make the code more sophisticated 570 00:37:55.660 --> 00:37:57.610 This is a tip 571 00:37:57.610 --> 00:37:59.939 so let’s work on creating the content here 572 00:37:59.939 --> 00:38:03.939 Typically provided in C# language 573 00:38:03.939 --> 00:38:06.589 now in Windows C++ 574 00:38:06.589 --> 00:38:09.939 it can be used 575 00:38:09.939 --> 00:38:12.699 because Unreal Engine is also using the same grammar 576 00:38:12.699 --> 00:38:14.599 So, using this approach 577 00:38:14.599 --> 00:38:16.199 let’s create getters and setters 578 00:38:16.199 --> 00:38:18.660 to modify the hp a bit 579 00:38:18.660 --> 00:38:22.380 If you go to NetTPSCharacter, you’ll find this section here 580 00:38:22.380 --> 00:38:24.630 Currently, the hp are set up like this 581 00:38:24.630 --> 00:38:28.620 but you prefer not to directly manipulate the property 582 00:38:28.621 --> 00:38:32.000 If you want to prevent 583 00:38:32.000 --> 00:38:34.500 direct manipulation of this part 584 00:38:34.500 --> 00:38:37.780 you can set it up like this 585 00:38:38.819 --> 00:38:40.619 Since this is within its own clasd 586 00:38:40.619 --> 00:38:44.740 it doesn’t matter whether you place private or public 587 00:38:44.740 --> 00:38:48.140 However, problems may arise when trying to access it from other classes 588 00:38:48.141 --> 00:38:50.660 Restricting access is done by 589 00:38:50.660 --> 00:38:51.960 marking it as private 590 00:38:51.960 --> 00:38:54.500 This way, other classes will be constrained from accessing it directly 591 00:38:54.500 --> 00:38:59.219 Since we’re working within the class itself, let’s leave it as is for now 592 00:38:59.339 --> 00:39:02.789 Let’s create getter and setter methods 593 00:39:02.789 --> 00:39:04.980 so that we don’t directly access the hp variable 594 00:39:04.980 --> 00:39:07.330 This is a helpful tip, so when you work on other projects 595 00:39:07.330 --> 00:39:09.500 you might find it useful to use this approach 596 00:39:11.500 --> 00:39:16.620 Alright, let’s add the getter and setter right below the hp variable 597 00:39:19.259 --> 00:39:22.000 There’s a thing called decl spec 598 00:39:24.699 --> 00:39:28.860 You can register a getter for this property 599 00:39:31.140 --> 00:39:35.590 by using underscores and the declspec 600 00:39:35.590 --> 00:39:39.579 then adding the property, and then putting a get 601 00:39:39.579 --> 00:39:40.879 If you define GetHP like this 602 00:39:40.879 --> 00:39:47.299 it means you want the function named GetHP to be callable 603 00:39:47.300 --> 00:39:51.079 If you add a comma after GetHP, it signifies that you’re now defining the setter 604 00:39:51.079 --> 00:39:55.300 So here, you’re associating it with a function named SetHP 605 00:39:56.813 --> 00:39:59.653 You close it with a single closing parenthesis 606 00:39:59.653 --> 00:40:02.603 So, this property with the getter and setter can be used 607 00:40:02.603 --> 00:40:05.339 by specifying what will use get and set 608 00:40:05.339 --> 00:40:10.099 You can also specify float here 609 00:40:10.100 --> 00:40:13.219 by pressing Enter 610 00:40:13.219 --> 00:40:14.519 I’ll use it here 611 00:40:14.519 --> 00:40:17.619 with Float HP, using capital letters 612 00:40:17.619 --> 00:40:20.100 to differentiate it from a variable like hp 613 00:40:20.101 --> 00:40:24.800 you can format it like this 614 00:40:24.801 --> 00:40:25.951 This variable would internally fetch its value 615 00:40:25.951 --> 00:40:30.332 using the GetHP function 616 00:40:30.332 --> 00:40:33.882 When you assign a value to HP 617 00:40:33.882 --> 00:40:36.092 it’ll invoke the SetHP function to separate the handling 618 00:40:36.092 --> 00:40:41.732 Underneath, you would add float GetHP 619 00:40:44.173 --> 00:40:47.053 Go ahead and place it right here 620 00:40:47.053 --> 00:40:50.253 While you could use forceinline to place it here 621 00:40:50.253 --> 00:40:53.212 let’s move the implementation to the separate definition section instead 622 00:40:53.212 --> 00:40:59.892 Let’s define the setter as void SetHP(float value) 623 00:40:59.892 --> 00:41:01.392 There was an error now 624 00:41:01.392 --> 00:41:03.592 because I closed the parenthesis prematurely 625 00:41:03.592 --> 00:41:06.562 let’s remove that closing parenthesis 626 00:41:07.562 --> 00:41:09.562 Let’s remove the closing parenthesis 627 00:41:09.562 --> 00:41:12.612 from GetHP 628 00:41:12.612 --> 00:41:13.931 since it was added by mistake 629 00:41:13.932 --> 00:41:16.791 So, you group the property declaration properly 630 00:41:16.791 --> 00:41:21.292 and then define GetHP 631 00:41:21.293 --> 00:41:26.472 Then, it’s correctly created with the scope resolution operator in front 632 00:41:26.472 --> 00:41:29.812 Let’s also create the SetHP function 633 00:41:29.812 --> 00:41:36.852 In the cpp file, you’ll create the HP property along with the GetHP and SetHP functions 634 00:41:36.853 --> 00:41:42.752 If you look again, you write the declspec like this 635 00:41:42.752 --> 00:41:46.011 _ _declspec, one underscore doesn’t matter 636 00:41:46.011 --> 00:41:53.091 Then property, put GetHP in getter 637 00:41:53.092 --> 00:41:56.491 Next, you put the variable name to be used 638 00:41:56.491 --> 00:42:00.132 So, when you call HP, it invokes the GetHP function here 639 00:42:00.132 --> 00:42:02.882 and setting a value will invoke the SetHP function 640 00:42:02.882 --> 00:42:04.731 with the registered value 641 00:42:04.731 --> 00:42:08.372 You can create and use getters and setters like C# language like this 642 00:42:10.652 --> 00:42:13.372 Let’s see how convenient this becomes 643 00:42:16.252 --> 00:42:18.872 Let’s move to the cpp file 644 00:42:18.872 --> 00:42:23.932 In the getter, simply pass over with returnHP 645 00:42:23.932 --> 00:42:29.572 In the SetHP function, we’ll pass over the part 646 00:42:29.572 --> 00:42:33.751 that was handled in DamageProcess 647 00:42:36.032 --> 00:42:40.392 Okay, so in DamageProcess, we’re only decreasing HP 648 00:42:40.392 --> 00:42:44.852 So, when HP decreases, the SetHP function will handle the value separation 649 00:42:44.852 --> 00:42:47.932 The value parameter will contain the updated HP value when it comes in 650 00:42:50.432 --> 00:42:53.572 If you’re looking at something like 651 00:42:53.591 --> 00:42:57.932 When you do hp -- 652 00:42:57.932 --> 00:42:59.482 what happens in the code? 653 00:42:59.482 --> 00:43:03.891 HP is subtracted by 1 from HP 654 00:43:03.892 --> 00:43:06.131 So first, you need to retrieve the current value of HP 655 00:43:06.131 --> 00:43:09.411 On the right side, rvalue retrieves the value 656 00:43:09.412 --> 00:43:13.511 So GetHP will be called here to retrieve the value 657 00:43:13.511 --> 00:43:17.811 And then, the -1 will be applied within the created GetHP 658 00:43:17.811 --> 00:43:19.292 and the value will then be inserted here 659 00:43:19.292 --> 00:43:21.692 That’s how value comes in here 660 00:43:21.692 --> 00:43:24.391 This is typcial usage of a property 661 00:43:24.392 --> 00:43:26.592 So, here we simply assign the value 662 00:43:26.592 --> 00:43:28.391 to HP 663 00:43:28.391 --> 00:43:30.791 Since the modified value comes in as value 664 00:43:30.791 --> 00:43:32.472 we directly assign it to HP 665 00:43:34.932 --> 00:43:37.052 And this lowercase HP here 666 00:43:37.052 --> 00:43:40.891 In DamageProcess, I’ll change the lowercase HP to the uppercase HP 667 00:43:40.892 --> 00:43:47.051 Why? Because the GetHP we’re creating is 668 00:43:47.051 --> 00:43:49.891 using the uppercase HP, right? 669 00:43:49.891 --> 00:43:52.741 The lowercase HP is the variable we originally use 670 00:43:52.741 --> 00:43:54.671 and want to utilize here 671 00:43:54.672 --> 00:43:56.511 So, when you call this 672 00:43:56.531 --> 00:44:00.581 it naturally invokes the getter and setter functions 673 00:44:00.581 --> 00:44:02.991 as structured 674 00:44:02.992 --> 00:44:03.892 Done 675 00:44:03.892 --> 00:44:05.792 Then, when you decrease the uppercase HP 676 00:44:05.792 --> 00:44:08.491 in decreases the health 677 00:44:08.491 --> 00:44:12.132 the getter and setter will automatically be called, allowing this action to execute 678 00:44:15.172 --> 00:44:18.992 This is a convenient feature commonly seen in C# language 679 00:44:18.992 --> 00:44:21.971 which significantly enhances readability and usability 680 00:44:21.971 --> 00:44:25.291 Just by doing this, the function will execute 681 00:44:25.292 --> 00:44:27.891 It gives it a Sphinx-like appearance 682 00:44:27.891 --> 00:44:31.852 It looks like a human with the body of a lion, like a sphinx 683 00:44:31.853 --> 00:44:34.372 It feels like the body and head are mismatched 684 00:44:34.372 --> 00:44:36.772 The head used is treated like a variable 685 00:44:36.772 --> 00:44:40.051 but actually functions as a function that runs in a structure 686 00:44:40.051 --> 00:44:43.271 involving getter and setter functions related to property 687 00:44:44.611 --> 00:44:45.931 Let’s build this 688 00:44:53.991 --> 00:44:56.772 and then re-run Unreal Engine Editor 689 00:44:56.772 --> 00:45:01.371 If you aim and shoot the gun, you should see the health decreasing correctly 690 00:45:03.852 --> 00:45:06.911 You’ve completed handling the player’s health up to this point 691 00:45:08.272 --> 00:45:10.792 Player death handling 692 00:45:12.391 --> 00:45:15.852 Let’s proceed with handling player death 693 00:45:20.211 --> 00:45:23.061 I’ll set up animation handling for 694 00:45:23.061 --> 00:45:24.971 when the player gets hit for player death processing 695 00:45:24.971 --> 00:45:30.132 If you try playing now, even if you shoot until the HP is depleted 696 00:45:30.133 --> 00:45:32.132 the player character remains as is 697 00:45:32.132 --> 00:45:33.782 So, let’s handle it such that when the player dies 698 00:45:33.782 --> 00:45:37.092 the death animation plays first 699 00:45:38.612 --> 00:45:42.712 Select ABP Manny from the animation folder 700 00:45:42.712 --> 00:45:45.411 and open it up 701 00:45:46.172 --> 00:45:48.431 Then navigate to the Animation graph 702 00:45:49.812 --> 00:45:51.172 In the animation graph 703 00:45:52.771 --> 00:45:55.411 select the Main States node 704 00:45:55.411 --> 00:45:58.861 from the Main States state machine 705 00:45:58.861 --> 00:45:59.692 Double-click 706 00:46:02.712 --> 00:46:04.162 Then it should look like this 707 00:46:04.162 --> 00:46:07.691 So, within this, locomotion and such were carried out 708 00:46:07.691 --> 00:46:10.741 Jumping off the ground or landing 709 00:46:10.741 --> 00:46:12.892 these are all handled within locomotion 710 00:46:12.893 --> 00:46:15.112 right here 711 00:46:15.112 --> 00:46:18.892 and motion inside 712 00:46:18.892 --> 00:46:20.792 Alright, so to make sure that 713 00:46:20.792 --> 00:46:25.572 when the player dies 714 00:46:25.573 --> 00:46:27.852 the death animation 715 00:46:27.852 --> 00:46:30.292 plays across all states 716 00:46:30.292 --> 00:46:33.531 let’s add a death state within this 717 00:46:33.532 --> 00:46:37.791 So, whether running in motion, holding a gun 718 00:46:37.791 --> 00:46:41.761 or not, death should be possible 719 00:46:41.761 --> 00:46:44.811 Similarly, the opponent when falling on the ground should be the same 720 00:46:44.811 --> 00:46:47.451 So, to allow death from any state 721 00:46:47.452 --> 00:46:49.511 let’s right-click here 722 00:46:49.531 --> 00:46:52.691 and select “Add States Alias” 723 00:46:56.491 --> 00:47:01.091 And name it “Any State” 724 00:47:04.132 --> 00:47:06.832 Name it “Any State” 725 00:47:06.832 --> 00:47:10.091 and check “Global Alias” 726 00:47:10.091 --> 00:47:12.811 to ensure it can be called from anywhere 727 00:47:12.811 --> 00:47:16.911 So, this will allow transitions from all motions like 728 00:47:16.911 --> 00:47:20.091 jump, fall loop, and land into this state 729 00:47:20.091 --> 00:47:21.972 It allows for signaling from any of those motions 730 00:47:25.412 --> 00:47:30.711 Let’s set it like this, and then you see Asset Browser on the right side 731 00:47:30.711 --> 00:47:33.572 Go ahead and search in the Asset Browser 732 00:47:33.573 --> 00:47:35.412 You will find an animation sequence file names “MM_Death Front 01” 733 00:47:35.412 --> 00:47:41.491 under the search results for “Death” 734 00:47:41.491 --> 00:47:43.971 Drag and drop this into the workspace 735 00:47:43.971 --> 00:47:46.871 and rename it to Die 736 00:47:50.021 --> 00:47:54.771 From any state, when the character dies 737 00:47:54.771 --> 00:47:56.732 it transitions to the “Die” state 738 00:47:56.732 --> 00:47:59.792 Connect the transition arrow 739 00:47:59.801 --> 00:48:02.401 from “Any State” to “Die” 740 00:48:06.091 --> 00:48:10.572 Alright? Then, when does it transition from Any State to Die? 741 00:48:10.572 --> 00:48:11.472 When it dies 742 00:48:11.472 --> 00:48:14.012 Since we can’t know exactly when it dies 743 00:48:14.012 --> 00:48:18.332 if we compile it first, a warning will appear here 744 00:48:18.332 --> 00:48:22.691 Why? Because this condition hasn’t been set yet 745 00:48:22.692 --> 00:48:24.751 To set this condition 746 00:48:24.751 --> 00:48:29.732 I’ll add a member variable to the animation class 747 00:48:29.733 --> 00:48:31.852 Let’s switch to Visual Studio 748 00:48:31.852 --> 00:48:36.851 and navigate to the NetPlayerAnimInstance header file 749 00:48:40.831 --> 00:48:45.772 So here, we need to add the content for when it dies 750 00:48:45.772 --> 00:48:52.691 It should be accessible from Blueprint 751 00:48:52.691 --> 00:48:59.211 so we’ll set it as EditDefaultsOnly and BlueprintReadWrite 752 00:48:59.211 --> 00:49:02.692 and the category will be 753 00:49:02.693 --> 00:49:05.572 MyAnimSetting 754 00:49:05.572 --> 00:49:12.251 Like this, we set bool IsDead to false 755 00:49:12.251 --> 00:49:16.892 This will handle whether it’s dead or alive 756 00:49:16.892 --> 00:49:20.851 With this option and property set 757 00:49:20.852 --> 00:49:22.691 we’ll register it and handle the animation transition accordingly 758 00:49:22.691 --> 00:49:23.631 Let’s build it now 759 00:49:31.201 --> 00:49:32.801 Let’s switch over to Unreal Editor 760 00:49:32.801 --> 00:49:36.701 and double-click on the transition condition button 761 00:49:36.701 --> 00:49:39.591 from AnyState to Die 762 00:49:39.592 --> 00:49:42.151 Here, now that the result value is registered 763 00:49:42.151 --> 00:49:47.171 if you open MyAnimSetting, there should be a variable called IsDead, right? 764 00:49:47.171 --> 00:49:50.912 Let’s drag and drop IsDead to attach it 765 00:49:53.101 --> 00:49:55.501 Next, when we compile 766 00:49:55.501 --> 00:50:00.112 if IsDead is set to true 767 00:50:00.132 --> 00:50:03.782 it’ll automatically transition to the Die animation state 768 00:50:03.782 --> 00:50:05.172 from any state 769 00:50:07.371 --> 00:50:11.811 So we need to set the condition where IsDead becomes true 770 00:50:11.812 --> 00:50:14.291 Let’s switch to Visual Studio 771 00:50:14.291 --> 00:50:18.511 and come to the header file 772 00:50:20.212 --> 00:50:24.512 of NetTPSCharacter 773 00:50:24.512 --> 00:50:27.851 to enable storing the death status here 774 00:50:27.851 --> 00:50:30.572 Death status 775 00:50:30.572 --> 00:50:35.772 AllIsDead now means not dead 776 00:50:35.772 --> 00:50:41.171 When this character’s Hp reaches 0, what happens next? 777 00:50:41.171 --> 00:50:44.652 Let’s handle it by setting it to true 778 00:50:46.041 --> 00:50:49.481 Let’s go inside the DamageProcess 779 00:50:49.492 --> 00:50:52.532 to see when it’ll become dead 780 00:50:52.532 --> 00:50:54.112 Here, when it 781 00:50:56.611 --> 00:51:03.131 enters the DamageProcess function, so if the Hp value is 0 or below, that means it’s dead 782 00:51:04.721 --> 00:51:10.681 If the HP value is 0 or below, then what happens? 783 00:51:10.681 --> 00:51:15.212 Since it means the character is dead, we set IsDead to true 784 00:51:15.213 --> 00:51:20.162 Then we need to synchronize the IsDead variable in NetTPSCharacter 785 00:51:20.162 --> 00:51:24.051 with the IsDead variable in the animation class 786 00:51:24.051 --> 00:51:28.201 There’s the cpp file of NetPlayerAnimInstance 787 00:51:28.201 --> 00:51:29.632 Move to that file 788 00:51:31.532 --> 00:51:36.251 Here, from NetTPS to the NetPlayerAnimInstance class 789 00:51:36.251 --> 00:51:39.851 In the NetPlayerAnimInstance class 790 00:51:39.851 --> 00:51:42.972 if we go up, we find NativeUpdateAnimation 791 00:51:42.972 --> 00:51:46.851 It handles similar content to T 792 00:51:46.852 --> 00:51:51.151 I’ll add the applicatino of death status below bHasPistol 793 00:51:51.152 --> 00:51:56.211 to synchronize IsDead 794 00:51:56.211 --> 00:51:58.891 with the IsDead in the player 795 00:51:58.891 --> 00:52:04.451 ensuring they’re linked 796 00:52:07.361 --> 00:52:11.441 In NetTPSCharacter, when the player shoots 797 00:52:11.441 --> 00:52:15.092 they inflict damage on the opponent 798 00:52:15.092 --> 00:52:16.392 causing them to take damage 799 00:52:16.392 --> 00:52:17.992 So, from the perspective of the opponent who gets hit 800 00:52:17.992 --> 00:52:20.972 the DamageProcess function is called 801 00:52:20.972 --> 00:52:26.412 So, their HP decreases, and if it reaches 0 or below, they’re considered dead 802 00:52:26.413 --> 00:52:29.452 And then in the animation, this value is received 803 00:52:29.452 --> 00:52:33.851 and applied to oneself, completing the structure 804 00:52:33.851 --> 00:52:35.091 Let’s build it 805 00:52:40.811 --> 00:52:44.531 and switch over to Unreal Editor to playtest it 806 00:52:48.740 --> 00:52:51.220 Alright, let’s go ahead and play to see how it works 807 00:52:51.231 --> 00:52:54.092 Go ahead and press the play button, then grab the gun 808 00:52:54.093 --> 00:52:58.012 When you shoot 809 00:52:58.012 --> 00:53:01.572 you should see the death animation playing 810 00:53:01.572 --> 00:53:05.972 So you’ve confirmed that the death animation is working as intended 811 00:53:05.972 --> 00:53:10.051 and implemented the overall functionality for player death handling 812 00:53:10.051 --> 00:53:13.680 Let’s summarize what we’ve learned in this section 813 00:53:13.680 --> 00:53:14.900 Implemented player health management Implemented logic for handling player damage 814 00:53:14.900 --> 00:53:16.200 Set up UI elements for own health and differentiate UI elements for opponents 815 00:53:16.200 --> 00:53:17.500 Created UI components using a ProgressBar widget for self-health in the MainUI 816 00:53:17.500 --> 00:53:18.980 Implemented a separate HealthBar widget to handle opponents’ health when they’re encountered 817 00:53:18.980 --> 00:53:20.747 Created getter and setter properties for the health member variable to enhance flexibility in access 818 00:53:20.747 --> 00:53:23.127 Implemented player death handling and death state animation 819 00:53:23.128 --> 00:53:25.840 Added animation state using State Alias to ensure death animation can be triggered from any state 820 00:53:25.840 --> 00:53:28.360 Set conditions for [is Dead] to become true, triggering the death animation when HP is depleted 821 00:53:28.360 --> 00:53:29.360 The End