WEBVTT 1 00:00:27.640 --> 00:00:29.660 Hello, this is Youngho Lee 2 00:00:29.660 --> 00:00:33.560 In this lesson, you will learn about player state synchronization 3 00:00:33.561 --> 00:00:36.020 First, we will learn 4 00:00:36.021 --> 00:00:38.700 how to synchronize player health 5 00:00:38.701 --> 00:00:41.180 By replicating health properties 6 00:00:41.181 --> 00:00:45.060 We'll learn how to synchronize and how to billboard the UI 7 00:00:45.060 --> 00:00:47.820 to rotate while facing the camera 8 00:00:47.821 --> 00:00:51.041 Second, we learn how to handle player shooting 9 00:00:51.042 --> 00:00:53.341 In shooting processing 10 00:00:53.341 --> 00:00:55.260 to give the player the effect of being shot 11 00:00:55.260 --> 00:00:59.320 we will learn how to create UI and apply UI animation 12 00:00:59.321 --> 00:01:01.481 We will also learn how to maximize 13 00:01:01.481 --> 00:01:05.140 expression using the camera shake effect 14 00:01:05.141 --> 00:01:08.260 Third, learn player death handling 15 00:01:08.260 --> 00:01:10.779 When the player enters the death state 16 00:01:10.780 --> 00:01:12.419 We will add a visual expression 17 00:01:12.420 --> 00:01:14.959 and a UI to allow the player 18 00:01:14.959 --> 00:01:16.957 to exit the game and retry 19 00:01:17.457 --> 00:01:20.737 Health Property Synchronization 20 00:01:22.360 --> 00:01:26.599 This time, we will look at player health 21 00:01:26.600 --> 00:01:29.640 Player health synchronization will be processed 22 00:01:29.640 --> 00:01:33.879 As for how the player's health is currently configured 23 00:01:33.880 --> 00:01:37.119 in the actual network state, the two health values ​​are 24 00:01:37.119 --> 00:01:39.639 not synchronized between 25 00:01:39.640 --> 00:01:41.259 the client and the server 26 00:01:41.260 --> 00:01:43.059 Let's come to Visual Studio 27 00:01:43.059 --> 00:01:46.360 and first move to NetTPSCharacter's Tick function 28 00:01:46.360 --> 00:01:49.680 Let's move to the Tick function in cpp 29 00:01:51.200 --> 00:01:53.499 Here, we are recording printNetLog 30 00:01:53.499 --> 00:01:56.839 We'll comment on it 31 00:01:56.840 --> 00:02:00.100 After that, the network information 32 00:02:00.100 --> 00:02:02.959 will not be displayed on the screen 33 00:02:02.960 --> 00:02:05.399 Next, we will implement content 34 00:02:05.399 --> 00:02:07.780 to synchronize the player's health 35 00:02:07.800 --> 00:02:12.060 HP is used to indicate physical health 36 00:02:12.061 --> 00:02:14.880 Here, we will use this HP value 37 00:02:14.880 --> 00:02:18.839 to synchronize in the network state like this 38 00:02:18.840 --> 00:02:22.080 First, this HP variable is 39 00:02:22.080 --> 00:02:24.459 now properly declared as UPROPERTY 40 00:02:24.459 --> 00:02:27.059 but the option to be replicated 41 00:02:27.059 --> 00:02:29.639 in the network state is missing 42 00:02:29.639 --> 00:02:33.980 So, let's put the Replicated option in front of this 43 00:02:33.980 --> 00:02:37.380 Let's add the Replicated option like this 44 00:02:37.380 --> 00:02:38.930 It's very simple 45 00:02:38.930 --> 00:02:41.380 Once HP is replicated like this 46 00:02:41.380 --> 00:02:43.420 What happens to the network status? 47 00:02:43.420 --> 00:02:45.920 It is declared as a target for synchronization processing 48 00:02:45.920 --> 00:02:47.980 Well, this has only been declared 49 00:02:47.980 --> 00:02:51.960 but the processing structure that synchronizes this data 50 00:02:51.960 --> 00:02:59.480 needs to be registered in this function called GetLifetimeReplicatedProps in cpp 51 00:03:00.820 --> 00:03:03.180 So, at the bottom 52 00:03:03.180 --> 00:03:06.980 let's add the HP value 53 00:03:06.981 --> 00:03:10.580 to the GetLifetimeReplicatedProps function 54 00:03:10.581 --> 00:03:15.080 If you do this, you can even include the implementation of ensuring 55 00:03:15.080 --> 00:03:18.399 that the HP value is synchronized in the network state 56 00:03:18.399 --> 00:03:19.549 There you go 57 00:03:19.549 --> 00:03:24.439 Now, the part that is currently touching this HP will be the SetHP part 58 00:03:25.479 --> 00:03:29.219 This is how SetHP currently handles HP values 59 00:03:29.219 --> 00:03:34.119 Now, where do we handle this part of setting HP like this? 60 00:03:34.119 --> 00:03:37.919 It has to be processed on the server 61 00:03:37.919 --> 00:03:41.959 Where do you create data on the server and visualize this value? From the client 62 00:03:42.880 --> 00:03:46.299 Now, let's first look at where SetHP is called again 63 00:03:46.299 --> 00:03:49.719 The part where SetHP is now called is 64 00:03:49.720 --> 00:03:51.680 not called directly 65 00:03:51.680 --> 00:03:54.780 but using getSet Property 66 00:03:54.780 --> 00:03:56.759 That's DamageProcess 67 00:03:56.759 --> 00:04:00.909 In other words, where is this SetHP running now? 68 00:04:00.909 --> 00:04:02.939 In DamageProcess 69 00:04:02.939 --> 00:04:07.859 In this DamageProcess, we are now changing the HP value 70 00:04:07.860 --> 00:04:10.999 Next, where is the damaged processor being called now? 71 00:04:10.999 --> 00:04:13.319 When the server RPC gun is fired 72 00:04:13.320 --> 00:04:16.199 a part of the server RPC creates this data, right? 73 00:04:16.199 --> 00:04:20.199 This part of configuring logic and creating data is 74 00:04:20.200 --> 00:04:23.039 the part that causes damage to users 75 00:04:23.039 --> 00:04:25.939 In other words, when a client and a server exist 76 00:04:25.939 --> 00:04:30.299 this DamageProcess HP stamina reduction part is executed somewhere 77 00:04:30.300 --> 00:04:34.959 It's happening on the server, so this part of DamageProcess 78 00:04:34.959 --> 00:04:38.000 that reduces HP like this is 79 00:04:38.000 --> 00:04:40.950 working normally on the server 80 00:04:40.950 --> 00:04:43.000 Then there is the part below here 81 00:04:43.000 --> 00:04:45.719 This part below updates the UI 82 00:04:45.719 --> 00:04:48.399 This part can be done on the server or not? 83 00:04:48.400 --> 00:04:50.679 That's not possible Where should I move this part? 84 00:04:50.679 --> 00:04:53.920 This will be something that needs to be implemented on the client 85 00:04:53.920 --> 00:04:58.139 Now, where does SetHP run now? Only on servers 86 00:04:58.140 --> 00:05:00.919 But we want to do this to express it 87 00:05:00.919 --> 00:05:03.319 on the server and all clients 88 00:05:03.320 --> 00:05:05.439 So, let's move 89 00:05:05.439 --> 00:05:09.800 this active part of this UI in SetHP to the tick function 90 00:05:10.600 --> 00:05:13.400 Let's leave HP's value part 91 00:05:13.400 --> 00:05:16.279 and move to the tick function 92 00:05:16.279 --> 00:05:20.379 I'll paste it at the bottom of the tick function like this 93 00:05:20.379 --> 00:05:24.619 Then, the part that updates the UI will now be executed in places 94 00:05:24.619 --> 00:05:29.139 where the client and server are located on the client-server and listen to the server 95 00:05:29.139 --> 00:05:32.959 And then this content will also be executed in those clients 96 00:05:32.960 --> 00:05:35.239 running only in the client window 97 00:05:35.239 --> 00:05:38.399 Right? When there is a MainUI 98 00:05:38.400 --> 00:05:41.659 its UI is expressed in the upper left corner 99 00:05:41.659 --> 00:05:43.519 so that content will be expressed 100 00:05:43.519 --> 00:05:48.219 When there is no MainUI, the UI floats above the other person's head 101 00:05:48.220 --> 00:05:50.019 Then, this part of the HP UI just below 102 00:05:50.019 --> 00:05:55.519 created using the health bar, will be updated on the screen 103 00:05:56.720 --> 00:06:00.919 Are you done? Now, let's do this and build it 104 00:06:01.559 --> 00:06:05.959 Now, let's go ahead and build it, so let's go ahead and run it 105 00:06:05.959 --> 00:06:10.099 Do play, and the client came out like this 106 00:06:11.279 --> 00:06:16.379 Now, make the other client see me 107 00:06:16.379 --> 00:06:21.759 On the server side screen, I'm going to go grab my gun and go ahead and shoot 108 00:06:23.179 --> 00:06:24.419 What happens when you bang? 109 00:06:24.419 --> 00:06:29.439 You can see that the opponent's HP is currently decreasing like this 110 00:06:29.440 --> 00:06:31.179 On the server screen 111 00:06:31.179 --> 00:06:34.179 and then on the client screen, the person who gets hit is the main character 112 00:06:34.179 --> 00:06:38.380 You can see that the hit target's HP is reduced like this 113 00:06:38.381 --> 00:06:39.820 The two are in sync 114 00:06:39.820 --> 00:06:43.140 and are working properly 115 00:06:43.140 --> 00:06:45.939 Now, let's go and grab a gun on the client as well 116 00:06:46.880 --> 00:06:52.819 Let's grab it and try to hit the character on the other side's server 117 00:06:52.819 --> 00:06:57.599 If you bang, it shrinks, and you can see it shrinks normally 118 00:06:58.899 --> 00:06:59.639 Okay? 119 00:07:01.140 --> 00:07:05.880 Now, we made sure that HP is expressed properly 120 00:07:05.881 --> 00:07:09.520 What about the part that keeps updating 121 00:07:09.520 --> 00:07:13.959 this UI even though I haven't changed this HP value? 122 00:07:13.959 --> 00:07:16.759 They said it was a waste of computational processing on the CPU 123 00:07:16.759 --> 00:07:18.899 So, what are we going to do about this? 124 00:07:18.900 --> 00:07:22.259 Let's process it like this 125 00:07:22.259 --> 00:07:25.919 so that the UI can be updated only when the HP changes 126 00:07:25.919 --> 00:07:28.679 Go to NetTPSCharacter.h 127 00:07:29.999 --> 00:07:34.619 Now, it says Replicated here, and change this part to using 128 00:07:34.619 --> 00:07:37.559 which means you will use the function 129 00:07:37.560 --> 00:07:41.339 I'll put it as OnRep_HP 130 00:07:41.339 --> 00:07:47.379 At to bottom, put UFUNCTION, void 131 00:07:48.519 --> 00:07:54.539 Now, let's add this OnRep_HP function to the implementation part 132 00:07:54.539 --> 00:07:57.999 Now, let's move the code that updates 133 00:07:58.000 --> 00:08:01.040 the UI on the screen to this OnRep_ part 134 00:08:01.040 --> 00:08:05.479 Now, I implemented it in the tick I put it in the tick like this 135 00:08:06.359 --> 00:08:07.759 This part 136 00:08:08.459 --> 00:08:11.419 I will add this part to OnRep_HP 137 00:08:12.654 --> 00:08:17.734 OnRep_HP, I will add the relevant information to this part 138 00:08:18.694 --> 00:08:22.844 If you do this, the OnRep_HP function will be called 139 00:08:22.844 --> 00:08:25.559 when the HP value changes and the screen is updated 140 00:08:25.559 --> 00:08:28.219 Do this, and play, then to find out what problem is there 141 00:08:28.220 --> 00:08:30.270 I've already explained before 142 00:08:30.270 --> 00:08:34.420 but let's try to figure it out again by looking at the screen 143 00:08:34.420 --> 00:08:36.239 So, let's press the play button 144 00:08:38.359 --> 00:08:42.859 go to the client side, and shoot a character on the server 145 00:08:42.859 --> 00:08:44.979 Bang! Character number 1 146 00:08:44.979 --> 00:08:46.529 How's this look like? 147 00:08:46.529 --> 00:08:50.429 The HP on the client is being modified 148 00:08:50.429 --> 00:08:55.679 but is the HP on the server currently being modified or not? 149 00:08:55.679 --> 00:08:56.559 It's not working 150 00:08:56.560 --> 00:09:02.579 If you look now, the HP above the client's head changes normally 151 00:09:02.579 --> 00:09:07.320 ut the HP of the character on the server is 152 00:09:07.321 --> 00:09:08.760 not changing properly 153 00:09:08.761 --> 00:09:10.640 It worked in Tick earlier 154 00:09:10.640 --> 00:09:12.919 but has not worked since moving to OnRep 155 00:09:12.919 --> 00:09:17.860 This OnRep_HP This function is called only from where this event is 156 00:09:18.439 --> 00:09:21.059 This is a function that is called only on the client 157 00:09:21.060 --> 00:09:22.760 Since the change was made on the server 158 00:09:22.760 --> 00:09:26.059 the client receives and processes the change event 159 00:09:26.059 --> 00:09:27.519 which is only called on the client 160 00:09:27.519 --> 00:09:30.719 So, what should I do to fix this part? 161 00:09:30.719 --> 00:09:35.280 OnRep_HP is a code from the server 162 00:09:35.281 --> 00:09:37.840 if you explicitly call it once like this 163 00:09:37.840 --> 00:09:44.100 At that time, let's rebuild it so that OnRep_HP can be executed and the results can be seen 164 00:09:46.179 --> 00:09:50.638 Try running both the server and the client 165 00:09:50.638 --> 00:09:55.779 Now, let's see if it works What happens if you bang the server character? 166 00:09:56.697 --> 00:10:00.077 The HP bar on the character's head is decreasing 167 00:10:00.077 --> 00:10:03.380 You can also see that the HP bar 168 00:10:03.381 --> 00:10:05.900 in the left server window decreases 169 00:10:05.900 --> 00:10:11.291 Now, similarly, let's go and use the server character here 170 00:10:11.292 --> 00:10:15.291 Bang! Then, you can see that the HP bar in the left server window is now decreasing 171 00:10:15.291 --> 00:10:18.031 and on the right, you can also see 172 00:10:18.031 --> 00:10:23.220 that the character's HP is decreasing along with this part at the top 173 00:10:24.100 --> 00:10:29.320 You can see that this and this are being synchronized with each other 174 00:10:29.320 --> 00:10:35.478 As I'm playing now, I think this part is very annoying to the eyes 175 00:10:35.478 --> 00:10:40.128 So, let's go ahead and put the character on this side first 176 00:10:40.128 --> 00:10:42.118 Next, let's say the server character 177 00:10:42.118 --> 00:10:45.568 shoots the character on the client 178 00:10:45.568 --> 00:10:47.500 It's the server window on the left now 179 00:10:47.501 --> 00:10:49.700 Bang! I'm going to shoot 180 00:10:49.701 --> 00:10:53.600 But on the left, you can see that the user's HP bar is displayed normally 181 00:10:53.600 --> 00:10:55.760 So that the user's HP bar is decreasing like this 182 00:10:55.778 --> 00:10:58.518 But oh, on the right, in the client window 183 00:10:58.540 --> 00:11:03.559 Is the character's HP bar visible or invisible in the server window on the left? 184 00:11:03.560 --> 00:11:04.799 You can't see it 185 00:11:04.799 --> 00:11:06.299 Why is that so? 186 00:11:06.299 --> 00:11:07.899 Because your back is turned 187 00:11:07.899 --> 00:11:12.239 If you go to the front, you can see it 188 00:11:12.240 --> 00:11:14.539 What if you go to the back? You won't see the HP bar 189 00:11:14.539 --> 00:11:18.498 Let's continue to modify this by using a technique 190 00:11:18.499 --> 00:11:22.378 to display HP according to the character 191 00:11:22.378 --> 00:11:24.538 We call this billboarding 192 00:11:24.538 --> 00:11:27.138 Go to Visual Studio 193 00:11:27.138 --> 00:11:31.520 Let's move to the Tick function and process this 194 00:11:31.520 --> 00:11:35.140 Let's try processing the billboarding using the Tick function 195 00:11:38.038 --> 00:11:44.078 There is no need for this content at the bottom of the Tick function when it is the main character, right? 196 00:11:44.079 --> 00:11:45.079 What kind of character? 197 00:11:45.079 --> 00:11:47.398 If it's not the main character but an opponent 198 00:11:47.398 --> 00:11:49.200 It has to be shown on this screen 199 00:11:49.201 --> 00:11:52.460 You have to process HP bar to look at me 200 00:11:52.460 --> 00:11:56.239 So, if there is hpUIComp 201 00:11:58.119 --> 00:12:03.920 only when hpUIComp is showing on the screen 202 00:12:03.921 --> 00:12:05.880 you can handle it like this so that it looks at the camera 203 00:12:05.880 --> 00:12:13.359 If you look at this value now, getVisibleFlag returns a bool value 204 00:12:13.360 --> 00:12:16.759 So, if this HP bar is shown on the screen 205 00:12:16.759 --> 00:12:19.438 and the HUD above the character's head is shown 206 00:12:19.438 --> 00:12:22.718 I will process the billboarding and add this content 207 00:12:23.358 --> 00:12:26.498 Then how can you get it? 208 00:12:26.500 --> 00:12:28.600 You can get it using vectors 209 00:12:28.600 --> 00:12:30.359 You can use simple subtraction of vectors 210 00:12:30.359 --> 00:12:33.509 Now, we need the first camera's location and the UI's location 211 00:12:33.509 --> 00:12:35.879 So first, in the vector 212 00:12:37.558 --> 00:12:40.338 Please enter the cam location 213 00:12:40.340 --> 00:12:45.678 It does not get the camera in NetTPSCharacter, but the camera is on the other side 214 00:12:45.678 --> 00:12:48.618 You can get the camera on the other side like this 215 00:12:48.619 --> 00:12:52.719 All you have to do is find out which character is using the main camera on the screen 216 00:12:52.720 --> 00:12:54.599 and bring it to them 217 00:12:54.600 --> 00:12:56.339 So they can be obtained like this 218 00:12:56.339 --> 00:13:03.760 If you look at UGameplayStatics, you will find something called getPlayerCameraManager 219 00:13:03.760 --> 00:13:08.438 Using this camera manager, we can determine 220 00:13:08.438 --> 00:13:13.998 which cameras use the viewport 221 00:13:13.999 --> 00:13:17.018 You can find out which camera is active 222 00:13:17.018 --> 00:13:20.919 Now, let's put the world here 223 00:13:20.919 --> 00:13:23.369 So here is the player index 224 00:13:23.369 --> 00:13:27.978 I'm going to find the 0th PlayerController 225 00:13:27.978 --> 00:13:32.178 Then, if you look there, you can get getCameraLocation information 226 00:13:32.178 --> 00:13:38.718 Since we need this location information, the camera's location information 227 00:13:38.718 --> 00:13:42.118 Next, he said he would subtract the camera's location, who? 228 00:13:42.118 --> 00:13:49.159 Since the UI is looking for the direction toward the camera's position, from the f vector 229 00:13:49.160 --> 00:13:51.560 I will get a direction vector 230 00:13:51.560 --> 00:13:52.759 How do you get this? 231 00:13:52.759 --> 00:13:56.960 Subtract from camera location 232 00:13:56.960 --> 00:14:04.939 If you enter getComponentLocation information in hpUIComp, the direction is obtained 233 00:14:05.899 --> 00:14:07.040 Let's set the z value 234 00:14:09.239 --> 00:14:11.239 to 0 235 00:14:14.599 --> 00:14:22.159 Then, add the setWorldRotation information 236 00:14:22.160 --> 00:14:23.779 and the direction to hpUIComp 237 00:14:23.779 --> 00:14:28.439 We'll put it in normalize getSafeNormalize 238 00:14:29.840 --> 00:14:35.000 Get it with getSafeNormal like this 239 00:14:35.000 --> 00:14:41.718 Let's add ToOrientRotator to it like this 240 00:14:41.718 --> 00:14:46.718 Then, change the vector to this rotation and add it 241 00:14:46.719 --> 00:14:52.198 This means that normalization makes the size one 242 00:14:52.198 --> 00:14:56.478 Let's make it like this: make it a rotator and put it in 243 00:14:58.039 --> 00:14:59.219 Now, let's build 244 00:15:01.159 --> 00:15:05.400 Now, if you go and play and play again 245 00:15:07.280 --> 00:15:13.219 No matter which direction your character goes, what is the opponent's UI like? 246 00:15:13.220 --> 00:15:15.239 It's 247 00:15:15.239 --> 00:15:19.713 looking at us correctly, right? But there's a downside 248 00:15:19.714 --> 00:15:22.473 Ah, why wasn't it visible to us until now? 249 00:15:22.473 --> 00:15:25.913 Because my back was turned, my main character's 250 00:15:25.914 --> 00:15:29.013 UI bar didn't show the HP bar like this 251 00:15:29.013 --> 00:15:32.440 but when I forced it to look at the camera and made it look at me 252 00:15:32.441 --> 00:15:34.440 this was finally revealed 253 00:15:34.440 --> 00:15:38.740 It was just that it wasn't visible 254 00:15:38.740 --> 00:15:41.118 When I made him look at the camera 255 00:15:41.118 --> 00:15:42.538 this problem arose 256 00:15:44.139 --> 00:15:46.539 So, should I show this or not? 257 00:15:46.539 --> 00:15:47.598 you don't have to show it 258 00:15:47.598 --> 00:15:52.038 You only need to show this HP bar, not this one 259 00:15:53.520 --> 00:15:55.920 So, let's try to process this 260 00:15:58.598 --> 00:16:01.038 Now, let's go to Visual Studio 261 00:16:01.038 --> 00:16:06.160 When should this hpUIComp be shown, and when not shown? 262 00:16:06.161 --> 00:16:09.440 When MainUI is on the screen 263 00:16:09.440 --> 00:16:12.998 should this hpUIComp be shown or not? 264 00:16:12.998 --> 00:16:15.238 You shouldn't show it 265 00:16:15.960 --> 00:16:20.260 And when there is no hpUI since it is the other person's 266 00:16:20.261 --> 00:16:24.000 the hpUI health bar must be shown above his head 267 00:16:24.000 --> 00:16:28.239 So, I will edit the part that handles this 268 00:16:28.240 --> 00:16:32.039 Now, what the function is is InitUIWidget 269 00:16:32.039 --> 00:16:34.639 What are we doing in InitUIWidget? 270 00:16:34.639 --> 00:16:38.060 I'm doing this part to create the MainUI 271 00:16:39.320 --> 00:16:40.470 Right 272 00:16:40.470 --> 00:16:48.879 Then, since there is a MainUI, let's make the health bar above my head invisible 273 00:16:50.159 --> 00:16:54.200 This content should be included 274 00:16:54.201 --> 00:16:57.440 Because the MainUI makes the health bar visible 275 00:16:57.440 --> 00:17:00.290 The UI displayed above my head must be processed like this 276 00:17:00.290 --> 00:17:03.119 which is invisible 277 00:17:03.119 --> 00:17:06.469 If there is hpUIComp, it will be there 278 00:17:06.469 --> 00:17:09.497 but just in case, I am checking it like this 279 00:17:09.497 --> 00:17:17.579 How about adding false to the SetVisibility property in hpUIComp? 280 00:17:18.379 --> 00:17:21.880 If it is an opponent's character other than the main character 281 00:17:22.817 --> 00:17:26.977 it will be displayed, and the presence of a main character means that there is a MainUI 282 00:17:26.977 --> 00:17:30.557 In this case, we will process hpUIComp so that it is not visible 283 00:17:30.557 --> 00:17:33.417 but the default is now set to true, so it is shown 284 00:17:34.959 --> 00:17:37.309 so that we will handle it like this 285 00:17:37.309 --> 00:17:39.559 Now, let's build it like this 286 00:17:43.657 --> 00:17:46.057 Now, if you succeed, let's go and play again 287 00:17:46.057 --> 00:17:49.839 So now, will the HUD appear above my head or not? 288 00:17:49.840 --> 00:17:51.239 It doesn't show up, does it? 289 00:17:51.239 --> 00:17:53.389 If you play now, you can see that 290 00:17:53.389 --> 00:17:56.599 only the opponent's HP bar appears above their head 291 00:17:56.599 --> 00:18:01.197 Now, no matter which way I go, the UI is rotating while looking at me 292 00:18:01.197 --> 00:18:06.977 We even processed the billboarding so that the player's health bar can be seen 293 00:18:07.000 --> 00:18:10.557 Using this, I completed all player stamina processing 294 00:18:10.557 --> 00:18:12.837 Shooting and Death Effect 295 00:18:14.740 --> 00:18:17.760 This time, we will look at handling player shoots 296 00:18:17.760 --> 00:18:20.660 Among the provided assets, if you look here now 297 00:18:20.660 --> 00:18:25.117 there is an image file called DamageBloodScreen.png 298 00:18:25.117 --> 00:18:28.877 Let's add this image to our project 299 00:18:28.877 --> 00:18:34.920 Let's add DamageBloodScreen to the UI folder by dragging and dropping it like this 300 00:18:34.920 --> 00:18:38.399 Then it came in like this 301 00:18:40.119 --> 00:18:43.499 Now, let's add some UI actions 302 00:18:43.500 --> 00:18:46.359 to show this DamageBloodScreen 303 00:18:46.359 --> 00:18:52.480 So here is WBP MainUI Open the WBP MainUI blueprint 304 00:18:53.839 --> 00:18:57.240 Now, let's add an image from the palette 305 00:18:58.280 --> 00:19:01.800 Let's search for an image in the palette 306 00:19:01.801 --> 00:19:04.640 and add it under the canvas panel 307 00:19:04.640 --> 00:19:07.540 Then, it is added at the bottom like this 308 00:19:07.540 --> 00:19:12.360 Let's name it DamageUI 309 00:19:13.220 --> 00:19:16.560 Then, go to the details window on the right 310 00:19:16.561 --> 00:19:19.000 and since the anchor value will fill the entire screen 311 00:19:19.000 --> 00:19:23.050 let's select this part at the bottom right 312 00:19:23.050 --> 00:19:24.140 Let's 313 00:19:25.020 --> 00:19:27.299 set offset left and top to 0 314 00:19:27.300 --> 00:19:30.439 offset right, and bottom to 0 315 00:19:30.439 --> 00:19:35.079 This will result in this image being filled 316 00:19:35.079 --> 00:19:38.017 Next, we will drag and drop the DamageBloodScreen 317 00:19:38.018 --> 00:19:40.097 that we added to the project as an image 318 00:19:40.097 --> 00:19:43.847 into this brush part like this 319 00:19:43.847 --> 00:19:45.977 Then it will look like this 320 00:19:45.978 --> 00:19:47.437 So, when we are shot 321 00:19:47.437 --> 00:19:51.119 we will process it like this to display it on the screen with this look 322 00:19:51.120 --> 00:19:54.139 Now, it's good to show it like this 323 00:19:54.139 --> 00:19:57.237 but let's add an animation to this UI that 324 00:19:57.237 --> 00:20:00.087 shows it suddenly and then slowly disappears 325 00:20:00.087 --> 00:20:03.197 There will be an animation in the window menu 326 00:20:03.197 --> 00:20:05.739 If you look fourth from the top, there is an animation 327 00:20:05.740 --> 00:20:08.479 Select it, and the animation window will open 328 00:20:08.480 --> 00:20:11.379 Here, click the animation button 329 00:20:11.379 --> 00:20:16.119 Let's name this animation DamageAnim 330 00:20:18.097 --> 00:20:22.537 DamageAnim, this is why it goes into DamageUI 331 00:20:22.538 --> 00:20:24.937 Select DamageAnim and press 332 00:20:24.937 --> 00:20:29.380 the track button on the right, then DamageUI will appear at the top 333 00:20:29.380 --> 00:20:32.920 We have selected several UI widgets here 334 00:20:32.921 --> 00:20:35.140 and among them, we have selected DamageUI 335 00:20:35.140 --> 00:20:39.740 hen DamageUI appears 336 00:20:39.740 --> 00:20:43.760 Here, to make this UI visible or invisible on the screen 337 00:20:43.761 --> 00:20:46.340 you can change the Render Opacity property 338 00:20:46.340 --> 00:20:49.240 Let's add a Render Opacity property 339 00:20:49.240 --> 00:20:51.980 and its contents to the animation 340 00:20:51.980 --> 00:20:54.130 There's DamageUI on the track here 341 00:20:54.130 --> 00:20:56.300 Shall we press the plus button? 342 00:20:56.301 --> 00:20:58.880 Then, a pop-up window will appear 343 00:20:58.880 --> 00:21:01.280 and it will say Render Opacity 344 00:21:01.280 --> 00:21:03.619 When you click, it will appear like this 345 00:21:03.619 --> 00:21:07.820 You can see that a keyframe was registered here at the very beginning 346 00:21:07.820 --> 00:21:11.160 We want it to fade out over 2 seconds 347 00:21:11.161 --> 00:21:13.700 so we'll put this timeline bar at 2 seconds 348 00:21:13.700 --> 00:21:16.619 and click the plus button in Render Opacity 349 00:21:16.620 --> 00:21:19.939 There is a plus button Click the plus button 350 00:21:19.939 --> 00:21:25.099 Then, you can see a keyframe inserted at the 2-second mark 351 00:21:25.099 --> 00:21:30.420 Now, you can add it to the 2 second part like this 352 00:21:30.460 --> 00:21:35.219 Now, it's like this Then, what do you want to happen in these 2 seconds? 353 00:21:35.219 --> 00:21:39.597 As time goes by like this, I want to 354 00:21:39.597 --> 00:21:43.647 increase the transparency of this Opacity value and process it like this so that it gradually becomes blurry 355 00:21:43.647 --> 00:21:45.197 In other words 356 00:21:45.197 --> 00:21:50.020 what do you want the keyframe value to be in the last 2 seconds? 357 00:21:50.021 --> 00:21:53.380 I hope it becomes 0 Select it here 358 00:21:53.380 --> 00:21:55.580 select the keyframe at 2 seconds 359 00:21:55.580 --> 00:21:58.280 and if you look down here, there's Render Opacity 360 00:21:58.280 --> 00:22:02.017 Let's change the value of this part to 0 361 00:22:02.017 --> 00:22:04.767 Now, if you do this 362 00:22:04.767 --> 00:22:08.077 the current value of the keyframe at the beginning is set to 1 363 00:22:08.078 --> 00:22:09.378 It is set to 1 like this 364 00:22:09.378 --> 00:22:17.020 As this value gradually decreases to 0 as the animation timeline progresses 365 00:22:17.020 --> 00:22:19.120 it becomes 0, right? 366 00:22:19.120 --> 00:22:22.537 I want to make it so that it is processed like this 367 00:22:22.537 --> 00:22:26.737 Should the damage effect be shown on the screen first? 368 00:22:26.737 --> 00:22:29.177 At first, it must be 0 369 00:22:29.177 --> 00:22:32.527 So, if you select anywhere in the blank space like this 370 00:22:32.527 --> 00:22:34.420 how about making a selection in the animation window? 371 00:22:34.421 --> 00:22:36.060 It is not checked right now 372 00:22:36.061 --> 00:22:38.740 Now select DamageUI, and again 373 00:22:38.740 --> 00:22:42.300 the animation window is currently disabled 374 00:22:42.300 --> 00:22:45.857 The details window on the right will have a Render Opacity value 375 00:22:45.857 --> 00:22:47.937 In the search section of the details window 376 00:22:47.937 --> 00:22:52.777 If you search for Render Opacity, it is currently set to 1 377 00:22:52.777 --> 00:22:54.677 Let me change this to 0 378 00:22:54.677 --> 00:22:57.956 Then, of course, the initial default value will be 0 379 00:22:57.956 --> 00:22:59.356 But the animation plays 380 00:22:59.356 --> 00:23:01.856 So, let me select DamageAnim here 381 00:23:01.856 --> 00:23:07.780 In the animation window, it will appear on the screen and then, when you press play 382 00:23:07.780 --> 00:23:09.819 it gradually disappear 383 00:23:11.379 --> 00:23:12.119 Are you done? 384 00:23:13.860 --> 00:23:18.760 Now, we made an animation like this 385 00:23:20.216 --> 00:23:22.776 Now, let's click compile 386 00:23:22.776 --> 00:23:27.976 and display this UI called DamageAnim on the screen 387 00:23:27.976 --> 00:23:29.580 and when we got damaged 388 00:23:29.580 --> 00:23:33.630 I will do shoot process effect appear on the screen 389 00:23:33.630 --> 00:23:35.459 Let's move to Visual Studio 390 00:23:35.459 --> 00:23:38.009 and move on to the new MainUI 391 00:23:38.009 --> 00:23:41.159 Come to the MainUI h header file 392 00:23:41.159 --> 00:23:46.409 and at the bottom I will make it public 393 00:23:46.409 --> 00:23:50.500 and add the DamageUI animation 394 00:23:50.500 --> 00:23:56.459 Now, enter the UPROPERTY and enter Edit Default Only 395 00:23:56.459 --> 00:23:59.500 Next, we will use the meta keyword 396 00:24:01.300 --> 00:24:05.050 and enter BindWidgetAnim 397 00:24:05.050 --> 00:24:09.619 Generally, when we bind UI, we only use BindWidget 398 00:24:09.619 --> 00:24:12.016 But since we want to play animation 399 00:24:12.016 --> 00:24:14.416 we need to add BindWidgetAnim 400 00:24:15.739 --> 00:24:23.940 Then, add a transient to the back 401 00:24:23.940 --> 00:24:26.239 and put the category My Settings 402 00:24:27.700 --> 00:24:32.459 class UWidgetAnimation 403 00:24:33.420 --> 00:24:40.099 I'll put it in DamageAnim Oh, I put it in capital letters DamageAnim like this 404 00:24:41.059 --> 00:24:44.679 It must have the same name as the DamageAnim created here 405 00:24:47.659 --> 00:24:50.999 If it comes out like this, it will bind automatically 406 00:24:53.016 --> 00:24:56.596 Now, let's create a function that plays the shoot handling animation 407 00:24:56.596 --> 00:25:01.819 that plays animation through the UI animation 408 00:25:01.819 --> 00:25:09.539 Void PlayDamageAnimation, let's create a function like this 409 00:25:09.539 --> 00:25:12.489 Shall we add the implementation part? 410 00:25:12.489 --> 00:25:16.339 Add PlayAnimation to the bottom of the Main UI CPP 411 00:25:16.339 --> 00:25:22.020 Here, PlayAnimation 412 00:25:22.021 --> 00:25:24.080 Here 413 00:25:24.080 --> 00:25:27.980 UWidgetAnim is designed to insert animation here 414 00:25:27.981 --> 00:25:30.740 Let's add DamageAnim like this 415 00:25:30.740 --> 00:25:33.956 Then, when the PlayDamageAnim function is called 416 00:25:33.956 --> 00:25:37.936 the DamageAnim shooting processing animation will be called internally 417 00:25:40.096 --> 00:25:42.516 So when should this be called? 418 00:25:42.516 --> 00:25:46.866 What happens when a player's HP decreases? 419 00:25:46.866 --> 00:25:48.499 It means that you were shot 420 00:25:48.499 --> 00:25:50.199 It means you were attacked 421 00:25:50.199 --> 00:25:53.399 So where does this part go? 422 00:25:54.339 --> 00:25:57.789 OnRapHP to NetTPSCharacter 423 00:25:57.789 --> 00:25:59.989 What OnRapHP does is 424 00:25:59.989 --> 00:26:02.420 that it is code that runs on the client 425 00:26:02.421 --> 00:26:04.440 Why is it running on the client? 426 00:26:04.440 --> 00:26:07.840 Since this has been shot, the HP value is changed 427 00:26:07.840 --> 00:26:10.539 OnRapHP is called 428 00:26:10.539 --> 00:26:14.980 and then we update this UI 429 00:26:16.036 --> 00:26:19.296 And who should I show the damage effects to? 430 00:26:19.297 --> 00:26:21.180 Only when you're the main player, right? 431 00:26:21.180 --> 00:26:25.099 That means when MainUI is present 432 00:26:25.099 --> 00:26:31.356 MainUI is the screen where the user's HP is displayed at the top left of the screen 433 00:26:31.356 --> 00:26:36.456 You only need to show the damage effect only for the characters with this MainUI 434 00:26:37.700 --> 00:26:42.159 So, under this MainUI's HP 435 00:26:42.159 --> 00:26:44.180 shoot process effect 436 00:26:46.099 --> 00:26:48.849 Let's play this part 437 00:26:48.849 --> 00:26:55.940 Let's call PlayDamageAnimation in MainUI 438 00:26:56.860 --> 00:26:58.039 Build it 439 00:27:00.379 --> 00:27:02.879 There you go 440 00:27:02.879 --> 00:27:05.229 Let's go and play it now 441 00:27:05.229 --> 00:27:07.539 You need two players 442 00:27:07.539 --> 00:27:13.460 I will make the server mode window appear separately to make it visible on the screen 443 00:27:13.460 --> 00:27:16.780 The server window opens, and then the client window opens 444 00:27:18.576 --> 00:27:22.416 I'll grab the gun on the server first and shoot the client 445 00:27:22.416 --> 00:27:25.800 Look at the client window on the right What happens when you bang? 446 00:27:26.900 --> 00:27:30.450 The shooting process effect is playing properly 447 00:27:30.450 --> 00:27:32.599 and let's check it out on the server 448 00:27:34.856 --> 00:27:37.459 This time, you have to look at the window on the left of the server character 449 00:27:37.459 --> 00:27:40.600 Since it is fired from the client, if you fire from the client 450 00:27:40.600 --> 00:27:43.300 you can see that the server window on the left 451 00:27:43.300 --> 00:27:46.459 properly shows the shoot processing effect 452 00:27:48.356 --> 00:27:51.076 If you get to this point 453 00:27:51.077 --> 00:27:54.616 the effect of dealing with hits when you get shot a little more 454 00:27:54.616 --> 00:27:56.300 may be a bit ambiguous as it maximizes immersion 455 00:27:56.301 --> 00:27:59.520 So we'll add one more thing to this 456 00:27:59.520 --> 00:28:03.740 I will shake the camera like this, and when I get shot 457 00:28:03.741 --> 00:28:06.740 I will shake the camera slightly to make the damaging effect 458 00:28:06.740 --> 00:28:09.339 look more realistic 459 00:28:09.339 --> 00:28:13.456 It's called a camera shake, and in the Blueprints folder 460 00:28:13.457 --> 00:28:15.716 in NetTPS Blueprints folder 461 00:28:15.716 --> 00:28:19.376 we'll handle this part by creating a camera shake Blueprint 462 00:28:21.059 --> 00:28:24.296 Now, right-click on the Blueprints folder 463 00:28:24.296 --> 00:28:26.416 Then click on the Blueprint class 464 00:28:27.920 --> 00:28:33.060 Let's search for a camera shake in AllClass 465 00:28:34.276 --> 00:28:36.796 Then, CameraShakeBase appears 466 00:28:36.796 --> 00:28:40.396 Select CameraShakeBase 467 00:28:40.396 --> 00:28:45.676 Let's name it BP_CameraShake 468 00:28:46.580 --> 00:28:50.319 Let's double-click BP_CameraShake to open it 469 00:28:54.259 --> 00:28:57.816 Now, what we're doing is very simple In this detail window 470 00:28:58.656 --> 00:29:03.696 there's a RootShakePattern on the right Let's change this part to a wave 471 00:29:03.699 --> 00:29:07.000 Select Wave Osillator Camera Shake Pattern 472 00:29:08.382 --> 00:29:09.422 and open it 473 00:29:10.836 --> 00:29:14.476 I want to shake the screen in all directions 474 00:29:14.476 --> 00:29:15.576 when I get shot 475 00:29:17.356 --> 00:29:21.420 I'm trying to change the position value like this 476 00:29:21.421 --> 00:29:24.220 and shake it around 477 00:29:24.220 --> 00:29:27.820 So, using only the location information without processing the rotation value 478 00:29:27.821 --> 00:29:29.820 let's shake the screen 479 00:29:29.820 --> 00:29:37.579 In Location, there is a Location Amplitude Multiplier 480 00:29:37.580 --> 00:29:40.999 It has become amplitude, which means how much should we shake? 481 00:29:41.000 --> 00:29:43.719 Next, Frequency refers to how often 482 00:29:43.719 --> 00:29:45.380 and how quickly to shake 483 00:29:45.395 --> 00:29:46.835 Let's set the amplitude to 2 484 00:29:48.075 --> 00:29:51.415 the Location Amplitude Multiplier to 2 485 00:29:51.415 --> 00:29:56.580 and then the Frequency Multiplier to 15 486 00:29:57.955 --> 00:30:00.335 Leave the rest alone 487 00:30:00.336 --> 00:30:04.015 Then, since the timing part needs to be moved to the bottom and shaken very briefly 488 00:30:04.015 --> 00:30:07.539 I do this for about 0.25 seconds 489 00:30:07.539 --> 00:30:13.559 Next, we will set the Blend In and Blend Out Time to 0.05 seconds each 490 00:30:14.315 --> 00:30:15.375 Like this 491 00:30:18.615 --> 00:30:22.595 I'll set the duration to a very short 0.25 seconds 492 00:30:22.595 --> 00:30:24.895 so that it can be played right when the blend switches 493 00:30:24.895 --> 00:30:28.715 set the Blend in Time and out to 0.05 seconds 494 00:30:29.615 --> 00:30:33.755 You can click compile and close BP CameraShake now 495 00:30:33.755 --> 00:30:38.420 Then, the Blueprint did all the work so that this CameraShake could be called 496 00:30:38.420 --> 00:30:40.835 Let's move to Visual Studio 497 00:30:40.835 --> 00:30:45.035 To the bottom of NetTPSCharacter in Visual Studio 498 00:30:48.135 --> 00:30:49.575 let's add this 499 00:30:49.576 --> 00:30:52.515 Now, let's keep adding it separately by making it public 500 00:30:52.515 --> 00:30:56.420 I will add the part related to the camera shake here 501 00:30:56.420 --> 00:31:00.275 UPROPERTY(EditDefaultsOnly) 502 00:31:01.135 --> 00:31:04.075 Now, let's put the category as UI 503 00:31:07.420 --> 00:31:12.579 Shall we put in damage? Since this has nothing to do with the UI 504 00:31:12.580 --> 00:31:14.720 I'll put it like this The category, damage 505 00:31:14.720 --> 00:31:22.380 Next, let's use TSubclassOf class UCameraShakeBase 506 00:31:22.380 --> 00:31:28.180 and add damageCameraShake here 507 00:31:28.181 --> 00:31:30.660 This will allow us to put our Blueprint 508 00:31:30.660 --> 00:31:33.655 into this variable called damageCameraShake 509 00:31:33.655 --> 00:31:37.555 o let's do this, and now let's move on to the cpp file 510 00:31:37.555 --> 00:31:39.735 Coming to NetTPSCharacter.cpp 511 00:31:39.736 --> 00:31:40.636 When? 512 00:31:40.636 --> 00:31:42.775 We will play the shooting processing effect 513 00:31:42.775 --> 00:31:47.260 and then process it here in OnRep HP to shake the screen 514 00:31:47.261 --> 00:31:52.180 to play the camera shake effect 515 00:31:52.180 --> 00:31:56.520 So I'm going to handle damageCameraShake 516 00:31:58.955 --> 00:32:00.680 when it exists 517 00:32:00.680 --> 00:32:05.659 Now, just put the auto in it and call it using PlayerController on your PC 518 00:32:05.659 --> 00:32:12.659 It's called Cast APlayerController, and this is a Controller 519 00:32:12.660 --> 00:32:15.339 Of course, there is a Controller if there is a MainUI 520 00:32:15.340 --> 00:32:16.340 Now, the PC has 521 00:32:17.659 --> 00:32:21.779 ClientStartCameraShake on it 522 00:32:21.780 --> 00:32:26.279 Here, you can add damageCameraShake like this 523 00:32:26.279 --> 00:32:29.479 This will create the effect of shaking the screen 524 00:32:30.539 --> 00:32:31.900 Let's build 525 00:32:33.940 --> 00:32:35.699 and go to Unreal Editor 526 00:32:38.579 --> 00:32:43.639 Now, open BP ThirdPerson in the Blueprint folder 527 00:32:43.640 --> 00:32:47.659 If you search for damageCamera, damageCameraShake will now appear 528 00:32:47.659 --> 00:32:49.499 It is set to none here 529 00:32:49.500 --> 00:32:53.139 but select this part with BP CameraShake like this 530 00:32:53.139 --> 00:32:57.340 Shall we click compile and go and play? 531 00:32:58.735 --> 00:33:00.635 Now, if you pick up a gun and shoot an opponent 532 00:33:00.635 --> 00:33:03.685 see what happens on the client screen on the right 533 00:33:03.685 --> 00:33:08.539 You can see the screen shaking along with the damage effect 534 00:33:08.539 --> 00:33:14.620 This is how I worked on the camera shake 535 00:33:14.620 --> 00:33:15.760 for being shot 536 00:33:17.980 --> 00:33:21.415 Then, the processing of the player being shot has been completed 537 00:33:21.416 --> 00:33:24.615 Now, we will look at handling player death 538 00:33:24.615 --> 00:33:27.975 I will change the screen to a gray tone 539 00:33:27.976 --> 00:33:30.875 then, such as whether the game should restart or end 540 00:33:30.875 --> 00:33:34.600 I will implement this content, which even displays a UI 541 00:33:37.095 --> 00:33:40.315 So currently, when the screen is like this 542 00:33:40.315 --> 00:33:42.819 the character looks like this 543 00:33:44.155 --> 00:33:48.275 and when the player dies, it is shocked to a gray tone like this 544 00:33:48.275 --> 00:33:52.699 After that, I'll put the manual 545 00:33:52.700 --> 00:33:53.819 up here 546 00:33:53.820 --> 00:33:56.639 Such as whether to restart or end 547 00:33:56.639 --> 00:34:01.899 Let's work on a UI that displays something on the screen 548 00:34:01.899 --> 00:34:04.795 So, in the animation folder 549 00:34:04.795 --> 00:34:07.315 there will be a montage, a death montage 550 00:34:09.940 --> 00:34:15.555 If you look here, it's not an MM_Death montage 551 00:34:15.555 --> 00:34:18.855 but an animation sequence. Let's double-click on it to open it 552 00:34:20.539 --> 00:34:24.675 It's MM_Death and front01 is written like this 553 00:34:24.676 --> 00:34:26.615 Now, when this animation runs 554 00:34:26.615 --> 00:34:28.695 and reaches this point 555 00:34:28.696 --> 00:34:32.415 I will trigger an event that changes the screen to a gray tone 556 00:34:32.415 --> 00:34:35.035 So, should we create a notification event here? 557 00:34:35.035 --> 00:34:36.675 Click the right mouse button 558 00:34:38.335 --> 00:34:41.760 and on the number 1 that says notify 559 00:34:41.760 --> 00:34:43.460 click the right mouse button 560 00:34:43.460 --> 00:34:45.035 Now, add Notify 561 00:34:45.035 --> 00:34:46.715 Then, new Notify 562 00:34:50.500 --> 00:34:52.440 Should I put DieEnd in it? 563 00:34:54.300 --> 00:34:58.299 When the DieEnd Notify event occurs like this, we try to process it 564 00:34:59.475 --> 00:35:01.515 Now, I will close this window for now 565 00:35:03.035 --> 00:35:05.795 Let's move on to Visual Studio 566 00:35:05.795 --> 00:35:08.500 Now, go to the header file in Visual Studio 567 00:35:08.501 --> 00:35:12.380 Move to the NetTPSCharacter header file 568 00:35:12.380 --> 00:35:16.760 I will add information related to death processing to this part 569 00:35:18.835 --> 00:35:23.095 I will create a function called void DieProcess 570 00:35:23.095 --> 00:35:24.535 and in this function 571 00:35:24.535 --> 00:35:27.459 I will implement what to do when the player dies 572 00:35:27.475 --> 00:35:29.915 So, shall we try adding this function? 573 00:35:30.675 --> 00:35:31.599 Okay? 574 00:35:31.599 --> 00:35:35.740 Now, this is NetTPSCharacter.cpp 575 00:35:35.741 --> 00:35:37.960 Now, what content 576 00:35:37.960 --> 00:35:41.575 are you going to add to the header? 577 00:35:41.575 --> 00:35:43.155 When the animation is played 578 00:35:43.155 --> 00:35:47.115 this notify event called DieEnd occurs 579 00:35:49.766 --> 00:35:53.746 A Notify called DieEnd will be played 580 00:35:53.747 --> 00:35:55.306 and when this event occurs 581 00:35:55.306 --> 00:35:58.000 we will receive the event 582 00:35:58.001 --> 00:35:59.380 and call this DieProcess from there 583 00:35:59.381 --> 00:36:01.020 So here, we'll gray out the screen 584 00:36:01.020 --> 00:36:05.165 pop up the screen with the UI, and do other things like this 585 00:36:05.165 --> 00:36:10.285 So NetTPSAnimation to receive that Notify event 586 00:36:10.286 --> 00:36:12.440 Let's move to the header file 587 00:36:12.440 --> 00:36:16.247 and apply the necessary notify event 588 00:36:16.247 --> 00:36:18.987 Now, if you look here, there is a reload animation notify event 589 00:36:18.987 --> 00:36:22.799 Similarly, I copied and pasted 590 00:36:22.800 --> 00:36:24.779 this below and at the bottom 591 00:36:24.779 --> 00:36:30.988 This time, it goes like this: AnimNotify DieEnd 592 00:36:30.989 --> 00:36:34.668 Then, when the DieEnd animation is in progress 593 00:36:34.669 --> 00:36:37.108 and DieEnd is called 594 00:36:37.108 --> 00:36:38.628 this function is called 595 00:36:38.659 --> 00:36:41.339 when notify is called 596 00:36:44.980 --> 00:36:49.163 Now, what we will do in this AnimNotify DieEnd function is 597 00:36:49.163 --> 00:36:53.103 call the DieProcess function in the player 598 00:36:53.103 --> 00:36:57.403 So, there must be an if player first 599 00:36:57.403 --> 00:37:00.063 After that 600 00:37:00.063 --> 00:37:02.760 the screen should be grayed out only for the main player 601 00:37:02.761 --> 00:37:05.500 which is unnecessary for the opponent 602 00:37:05.501 --> 00:37:07.680 How do I tell 603 00:37:07.681 --> 00:37:10.000 if this character is currently the main character? 604 00:37:10.000 --> 00:37:15.699 if this character is currently the main character? 605 00:37:15.699 --> 00:37:20.439 That means that it is being controlled by the PlayerController, right? 606 00:37:20.440 --> 00:37:23.019 In other words, it is an autonomous character 607 00:37:23.020 --> 00:37:26.599 Once it becomes an autonomous proxy 608 00:37:26.599 --> 00:37:30.699 it becomes locally controlled internally 609 00:37:30.700 --> 00:37:33.299 In the case of a server, it is the authority 610 00:37:33.299 --> 00:37:35.579 What handles these internally? 611 00:37:35.580 --> 00:37:37.319 It's the isLocallyControlled function 612 00:37:37.320 --> 00:37:39.619 In other words, internally 613 00:37:39.619 --> 00:37:43.219 it checks whether it is the player I control 614 00:37:43.219 --> 00:37:49.939 At this time, the message is that DieProcess in the player will be called 615 00:37:49.940 --> 00:37:52.759 At this time, when DieProcess is called 616 00:37:52.759 --> 00:37:57.980 DieProcess in NetTPSCharacter is called 617 00:37:57.980 --> 00:38:05.819 How do I make the screen gray out as if it is disabled 618 00:38:08.094 --> 00:38:09.639 What do I do with this? 619 00:38:09.639 --> 00:38:14.354 What I will change in the Unreal Editor is, internally 620 00:38:14.354 --> 00:38:15.794 in the Blueprint 621 00:38:17.154 --> 00:38:19.174 there is a BP ThirdPerson character 622 00:38:20.099 --> 00:38:25.104 If you go to the following camera, there is a saturation option among the camera options 623 00:38:25.104 --> 00:38:29.664 Should I enable the saturation option with this value? 624 00:38:29.665 --> 00:38:33.044 And if I activate this value 625 00:38:33.044 --> 00:38:36.219 and change it to a black tone 626 00:38:36.219 --> 00:38:37.319 shall we do it randomly? 627 00:38:37.319 --> 00:38:40.839 It means putting it like 0, 0, 0 628 00:38:42.274 --> 00:38:45.939 What will the screen look like if I play it like this? 629 00:38:45.939 --> 00:38:49.380 It comes out in a gray tone like this, everything is hazy 630 00:38:49.381 --> 00:38:52.120 That's right, the whole world becomes gray 631 00:38:52.120 --> 00:38:54.560 What I am saying is that we will make it like this 632 00:38:56.020 --> 00:38:58.339 So, in the code 633 00:39:01.374 --> 00:39:04.034 I am going to set this value to 0 0 0 634 00:39:05.019 --> 00:39:08.999 for this saturation in DieProcess 635 00:39:09.994 --> 00:39:10.994 Right? 636 00:39:12.359 --> 00:39:15.459 If you leave it like this and play again, it will come out as it was 637 00:39:15.459 --> 00:39:21.299 Now, in DieProcess, let's add something here that changes that value to 0, 0, 0 638 00:39:21.299 --> 00:39:25.500 Go to DieProcess in Visual Studio 639 00:39:25.939 --> 00:39:32.740 Now let's first import PlayerController Cast APlayerController 640 00:39:35.179 --> 00:39:38.974 Here, this controller has an unconditional value, why? 641 00:39:38.975 --> 00:39:40.914 How is it done in animation? 642 00:39:40.914 --> 00:39:44.934 When there is a player, right, when there is a player, and local control is in place 643 00:39:44.934 --> 00:39:46.894 we do this to that player 644 00:39:46.894 --> 00:39:49.274 This means that there is a PlayerController 645 00:39:51.654 --> 00:39:55.274 If we want to do something first 646 00:39:55.274 --> 00:39:58.419 since we are done, we want to launch the UI and do this work 647 00:39:58.419 --> 00:40:02.440 So, at this time, to show the mouse on the screen 648 00:40:04.520 --> 00:40:09.080 there is a thing called SetShowMouseCursor in PlayerController 649 00:40:09.081 --> 00:40:10.940 Let's set it to True here 650 00:40:10.941 --> 00:40:13.220 so that the mouse cursor is visible on the screen 651 00:40:13.220 --> 00:40:19.240 then gray out the screen as shown above 652 00:40:19.240 --> 00:40:25.414 Let's put it in the bottom part, and there's GetFollowCamera 653 00:40:25.414 --> 00:40:30.734 This Follow Camera has PostProcessSettings 654 00:40:30.760 --> 00:40:34.859 Let's work on Color Saturation here 655 00:40:37.534 --> 00:40:39.640 In addition, it is FVector 656 00:40:39.640 --> 00:40:44.959 and the value is 0 0 0. At the end, it gives an alpha value of 1 657 00:40:44.960 --> 00:40:49.639 Now, here we have to take over 4 FVectors 658 00:40:49.639 --> 00:40:53.439 Now, let's build it like this and look at the results 659 00:40:54.599 --> 00:40:57.879 So let's play and let the other person play, too 660 00:40:57.880 --> 00:41:01.599 I'll go and grab a gun on the client and shoot the server character 661 00:41:01.599 --> 00:41:05.959 If you shoot three times, how about going to the server window on the left and looking at it? 662 00:41:05.960 --> 00:41:07.999 Can you see that it has now changed to a gray tone? 663 00:41:08.000 --> 00:41:11.119 It looks like this, right? Then there is also a mouse cursor, right? 664 00:41:11.119 --> 00:41:12.840 Do you see it like this? 665 00:41:12.841 --> 00:41:14.080 It worked normally 666 00:41:14.080 --> 00:41:17.179 But on the other hand, why didn't it work when I did it on the client? 667 00:41:18.814 --> 00:41:23.774 Now, let's grab the server and shoot the client Bang, bang, bang 668 00:41:23.775 --> 00:41:27.514 When I shoot the server from the client, it works normally 669 00:41:27.514 --> 00:41:29.980 but what happens when I shoot the client from the server? 670 00:41:29.981 --> 00:41:33.700 The damaged animation is not displayed properly on the screen 671 00:41:33.700 --> 00:41:36.480 and the colors are also not visible 672 00:41:36.481 --> 00:41:38.160 Why is this part like that? 673 00:41:38.160 --> 00:41:41.300 What parts are being processed in our code now? 674 00:41:42.894 --> 00:41:46.534 DieProcess plays in the animation 675 00:41:46.534 --> 00:41:49.960 That is, it is client code that plays in the animation 676 00:41:50.774 --> 00:41:54.054 Right? Since it is client code, if it is sent from the client to the server 677 00:41:54.054 --> 00:41:56.204 all of these details will be applied to the server 678 00:41:56.204 --> 00:41:58.599 so it will be processed properly 679 00:41:58.600 --> 00:42:00.799 However, this content will appear 680 00:42:00.799 --> 00:42:04.759 because the server and client are not properly distinguished 681 00:42:06.354 --> 00:42:08.339 Shall we check it through the code? 682 00:42:08.339 --> 00:42:12.799 Let's move the DamageProcess function 683 00:42:12.800 --> 00:42:16.299 In DamageProcess, the HP value changes 684 00:42:16.300 --> 00:42:17.739 when the user is shot 685 00:42:17.739 --> 00:42:20.520 Where does this part run? The part that converts to data is 686 00:42:20.521 --> 00:42:22.440 currently being executed on the server 687 00:42:22.440 --> 00:42:27.039 What is happening on the server when the current HP value is 0? 688 00:42:27.039 --> 00:42:29.089 They are treating it like this when they die 689 00:42:29.089 --> 00:42:31.180 But what happens to IsDead now? 690 00:42:32.674 --> 00:42:37.633 Is it being replicated? It's not 691 00:42:37.634 --> 00:42:42.519 So, when changing from client to server, the server is the client 692 00:42:42.519 --> 00:42:45.780 showing properly in the server character 693 00:42:45.781 --> 00:42:48.700 However, the server attacked the client 694 00:42:48.700 --> 00:42:52.279 The one in the server window is now in a separate window 695 00:42:52.280 --> 00:42:54.379 from the one in the client window 696 00:42:54.379 --> 00:42:58.360 It was in a separate place, but it attacked 697 00:42:58.360 --> 00:43:02.573 It attacked this person, and in this window, this should be applied and grayed out 698 00:43:02.574 --> 00:43:04.373 but this is set to true only on the server 699 00:43:04.373 --> 00:43:07.253 and there is no way for the client to receive this data 700 00:43:07.253 --> 00:43:09.713 So, this means that the screens are out of sync 701 00:43:09.713 --> 00:43:11.293 Because the fact that it's dead does not come in 702 00:43:12.479 --> 00:43:17.293 Right, it has to be IsDead What do we do with IsDead? 703 00:43:17.293 --> 00:43:19.813 I'm doing animation processing and stuff like that right now 704 00:43:19.814 --> 00:43:23.693 Yes? Where is IsDead handled? 705 00:43:23.693 --> 00:43:29.720 Coming to Unreal Editor, there is ABP Manny in animation 706 00:43:29.721 --> 00:43:33.580 Yes? If you look here, you will see an IsDead option 707 00:43:33.580 --> 00:43:38.020 If you look at NetPlayerAnimInstance 708 00:43:38.021 --> 00:43:40.480 there is code that synchronizes 709 00:43:40.480 --> 00:43:42.230 the IsDead value and the player's IsDead value like this 710 00:43:42.230 --> 00:43:44.053 In this update animation 711 00:43:44.054 --> 00:43:47.553 when this value becomes true, it becomes true 712 00:43:47.553 --> 00:43:50.693 a death animation appears, and this should be processed 713 00:43:50.694 --> 00:43:52.713 What is the problem now? 714 00:43:52.713 --> 00:43:56.100 It works on the server, but does it work on the client? 715 00:43:56.101 --> 00:43:57.160 It doesn't now 716 00:43:57.161 --> 00:43:59.620 I changed it on the server, but the client 717 00:43:59.621 --> 00:44:02.233 hasn't yet synchronized and received this data 718 00:44:03.000 --> 00:44:05.179 So we need to take care of this part 719 00:44:05.180 --> 00:44:06.793 For this purpose 720 00:44:06.793 --> 00:44:10.333 will you synchronize the IsDead property in NetTPSCharacter? 721 00:44:10.339 --> 00:44:11.880 You don't have to do that 722 00:44:13.993 --> 00:44:19.493 How? This part doesn't have to be here, then where? 723 00:44:19.494 --> 00:44:21.253 When the client code is executed 724 00:44:21.253 --> 00:44:24.060 IsDead on the client becomes true 725 00:44:24.061 --> 00:44:26.400 So, instead of putting this part here 726 00:44:26.400 --> 00:44:28.833 this HP value is 727 00:44:28.833 --> 00:44:31.499 synchronized anyway 728 00:44:31.500 --> 00:44:34.059 so I'm setting the HP value here like this 729 00:44:34.059 --> 00:44:37.813 so this HP is currently being replicated 730 00:44:37.813 --> 00:44:43.933 With this HP value alone, we can save packets in the network state 731 00:44:43.933 --> 00:44:46.383 and not synchronize it 732 00:44:46.383 --> 00:44:49.480 Instead, we can just take this value and set it to true here 733 00:44:49.480 --> 00:44:52.280 Where will we take this part? 734 00:44:52.280 --> 00:44:55.553 In DamageProcess, if HP is less than 0 735 00:44:55.553 --> 00:44:59.933 Press Ctrl+x to cut the IsDead true part 736 00:44:59.933 --> 00:45:04.053 Then, you enter the OnRep HP function 737 00:45:04.053 --> 00:45:10.399 What should we do now so that the OnRep HP function is entered 738 00:45:10.400 --> 00:45:14.159 and the relevant content is attached here? At this time, is HP less than 0? 739 00:45:14.159 --> 00:45:17.020 Then, how did he die? Let's deal with it like this 740 00:45:17.813 --> 00:45:19.663 Where does OnRep HP run? 741 00:45:19.663 --> 00:45:21.293 It runs on the client 742 00:45:21.293 --> 00:45:25.920 This means that when executed on the client, it gets the HP value and processes it as if it is dead 743 00:45:25.920 --> 00:45:27.620 Let's build it 744 00:45:29.040 --> 00:45:32.119 then go to Unreal Editor and play again 745 00:45:34.519 --> 00:45:37.159 There was no problem when switching from client to server, right? 746 00:45:37.160 --> 00:45:39.519 Now, let's use the client again on the server 747 00:45:39.520 --> 00:45:44.539 Bang, bang, bang, you can see 748 00:45:44.539 --> 00:45:48.739 which parts of the animation and screen are displayed normally, even the blurry parts 749 00:45:51.993 --> 00:45:55.513 So, first of all, it was about handling death 750 00:45:55.513 --> 00:45:57.940 and there may be questions about what other problems could arise at this time 751 00:45:59.073 --> 00:46:01.433 I'll go and shoot the character 752 00:46:01.440 --> 00:46:04.590 Bang, bang, bang, I got rid of it 753 00:46:04.590 --> 00:46:06.190 He's dead, right? 754 00:46:06.190 --> 00:46:07.839 He's dead, but I'll go and shoot him again 755 00:46:07.839 --> 00:46:12.533 When you shoot, what happens? The screen keeps shaking Why? Because it's keep shot 756 00:46:12.533 --> 00:46:16.113 I think we need to do something to prevent it from getting hit when it dies 757 00:46:16.119 --> 00:46:20.769 So, at this time, when IsDead is true in OnRep HP 758 00:46:20.769 --> 00:46:24.320 if you are still holding the first gun 759 00:46:24.320 --> 00:46:28.320 drop the gun you are holding 760 00:46:29.599 --> 00:46:36.239 and disable the collider to prevent further collisions 761 00:46:36.239 --> 00:46:38.739 Do it like this, right? 762 00:46:38.739 --> 00:46:42.799 After that, can the character keep moving or not? It won't work, right? 763 00:46:42.799 --> 00:46:45.659 Let's prevent the character 764 00:46:48.033 --> 00:46:49.593 from moving 765 00:46:51.600 --> 00:46:55.200 Now, let's check again what's going on right now 766 00:46:56.573 --> 00:47:00.233 I grabbed the gun and shot the other person 767 00:47:00.240 --> 00:47:04.400 First, there is a problem with the damage dealt from repeated hits 768 00:47:04.420 --> 00:47:07.260 And then I'll move it around on the client screen here 769 00:47:07.261 --> 00:47:09.200 Can you see that it keeps moving even though it's dead? 770 00:47:09.200 --> 00:47:11.100 The movement continues 771 00:47:11.100 --> 00:47:18.079 There's this part that prevents him from moving, and even though he's dead 772 00:47:18.080 --> 00:47:20.679 let's say he goes and grabs the gun 773 00:47:20.679 --> 00:47:22.979 The other person is holding a gun now 774 00:47:22.979 --> 00:47:26.799 Do all these things work or not? That's not possible 775 00:47:26.800 --> 00:47:30.840 Should the client even go and grab the gun first? 776 00:47:30.840 --> 00:47:32.040 Got it 777 00:47:32.040 --> 00:47:36.279 Now let's go to the server this time, grab a gun and shoot the opponent 778 00:47:36.280 --> 00:47:41.259 I think there's a problem with this because he keeps holding the gun in his hand 779 00:47:41.259 --> 00:47:42.909 even though he's dead 780 00:47:42.909 --> 00:47:44.920 Drop the gun when you're dead 781 00:47:44.920 --> 00:47:48.953 I will process this like this, so I have included these three contents 782 00:47:48.953 --> 00:47:51.293 So that made us drop the gun we were holding 783 00:47:52.200 --> 00:48:00.860 What was our ReleasePistol? It was the input to release the gun, ReleasePistol 784 00:48:00.860 --> 00:48:06.133 If you go and look, you will see the information about releasing the gun in this ReleasePistol 785 00:48:06.133 --> 00:48:09.893 So what we're saying is that if you simply input ReleasePistol 786 00:48:09.894 --> 00:48:14.053 releasing the gun internally will happen automatically through server communication 787 00:48:14.053 --> 00:48:17.880 You can do this to drop the gun you are holding in OnRep HP 788 00:48:17.880 --> 00:48:24.600 Now, all you have to do is use ReleasePistol and add that FInputActionValue value here 789 00:48:24.600 --> 00:48:29.760 For FInputActionValue, we will only add an empty constructor function 790 00:48:29.760 --> 00:48:30.910 Why? 791 00:48:30.910 --> 00:48:34.660 ReleasePistol does not process any input values 792 00:48:34.660 --> 00:48:36.799 but processes the input as it comes in 793 00:48:39.019 --> 00:48:42.039 so you only need to enter this part here 794 00:48:42.039 --> 00:48:51.640 Next, set SetCollisionEnabled that disables the collider 795 00:48:51.640 --> 00:48:55.740 to No Collision on the CapsuleComponent 796 00:48:55.740 --> 00:48:59.119 Then there will be no more crashes 797 00:48:59.119 --> 00:49:03.819 and if you look, there's also mesh 798 00:49:03.819 --> 00:49:06.720 In addition to CapsuleComponent, there is also mesh here 799 00:49:06.721 --> 00:49:09.840 Even in mesh, colliders are attached separately 800 00:49:09.840 --> 00:49:14.719 So, let's also change CollisionEnabled in the mesh 801 00:49:14.719 --> 00:49:18.540 Press Ctrl+D to process NoCollision 802 00:49:20.252 --> 00:49:24.000 in Getmesh this time 803 00:49:24.000 --> 00:49:28.159 And since we wanted to prevent the character from moving 804 00:49:28.160 --> 00:49:33.579 we will import the GetCharacterMovement component 805 00:49:33.579 --> 00:49:37.880 and handle it like this: DisableMovement 806 00:49:37.881 --> 00:49:41.920 Then, the user will not be able to move 807 00:49:41.920 --> 00:49:45.760 Now, there is one thing you need to know here 808 00:49:45.760 --> 00:49:49.399 I told you that this runs on the client 809 00:49:49.400 --> 00:49:52.119 This is the structure that is currently being executed on the client 810 00:49:52.119 --> 00:49:56.579 This is my main character in onlap right now 811 00:49:56.580 --> 00:49:59.919 There is a user character with a different sub-character over there 812 00:49:59.920 --> 00:50:02.639 He currently has a gun like this 813 00:50:02.639 --> 00:50:06.799 If I bang like this, then this function will be called internally 814 00:50:06.800 --> 00:50:10.179 Since this is a client, it is his own 815 00:50:10.179 --> 00:50:14.159 so things like being deactivated when he is this guy or this guy will also be expressed 816 00:50:14.160 --> 00:50:19.039 Why? When there is a main UI But if it's the other person 817 00:50:19.039 --> 00:50:21.832 you must do these things so they can't keep guessing 818 00:50:21.832 --> 00:50:24.892 That's what dropping the gun is all about 819 00:50:24.892 --> 00:50:27.342 Okay, I'm going to drop the gun just like this 820 00:50:27.342 --> 00:50:28.442 I dropped it 821 00:50:28.442 --> 00:50:31.780 Now, this is what happened with ReleasePistol 822 00:50:31.780 --> 00:50:36.172 Right, but what happens when you use ReleasePistol? 823 00:50:36.172 --> 00:50:38.522 I should leave mine 824 00:50:38.522 --> 00:50:41.712 but for the ones on the main character 825 00:50:41.719 --> 00:50:46.792 I need to properly receive input from ReleasePistol, but this one doesn't work 826 00:50:46.792 --> 00:50:49.492 What I'm saying is that we only need content about dropping the gun 827 00:50:49.492 --> 00:50:51.612 In other words, let's go inside ReleasePistol 828 00:50:53.732 --> 00:51:00.032 Now, if you look here, when you use ReleasePistol, what are the opponent's like now? 829 00:51:00.032 --> 00:51:05.479 Using serverRPC, ReleasePistol is automatically fired when the user dies, which comes in 830 00:51:05.479 --> 00:51:08.359 This condition is required 831 00:51:11.679 --> 00:51:17.880 If it is not locally controlled, it should not be processed 832 00:51:17.880 --> 00:51:23.280 This means that only the one currently controlled by the main can request server RPC now 833 00:51:23.280 --> 00:51:28.530 I will modify the content to do this only when autonomous 834 00:51:28.530 --> 00:51:30.640 Now, let's process the build like this 835 00:51:32.479 --> 00:51:34.720 Now, if you go and play 836 00:51:37.159 --> 00:51:44.359 you grab a gun and shoot, and now you won't take any damage to your opponent even if you keep shooting 837 00:51:44.359 --> 00:51:50.200 Right, so either he can move, or he can do something, or he can't 838 00:51:50.201 --> 00:51:53.160 Up to this point, when dealing with death 839 00:51:53.160 --> 00:51:58.960 I worked on various things like animation, UI, and dropping the gun 840 00:51:58.960 --> 00:51:59.860 Well, it ended up like this 841 00:51:59.860 --> 00:52:04.132 Now, let's try to restart or end the game so that the Game Over UI 842 00:52:04.132 --> 00:52:08.572 can appear on the screen when it is in a dead state 843 00:52:08.572 --> 00:52:14.180 Now, open WBP MainUI from the UI folder We already opened it 844 00:52:14.180 --> 00:52:18.559 In addition, we will take care of this so that the Game Over UI can be displayed 845 00:52:19.619 --> 00:52:27.760 Here, we search for a horizontal box in the palette and add it to the canvas 846 00:52:27.760 --> 00:52:30.510 Then, here comes the horizontal box 847 00:52:30.510 --> 00:52:35.280 I'll name it GameOverUI 848 00:52:35.281 --> 00:52:38.580 Let's put it as GameOverUI 849 00:52:38.581 --> 00:52:41.060 Now, shall we add a button? 850 00:52:41.060 --> 00:52:45.320 Let's add a button and register it with GameOverUI 851 00:52:45.321 --> 00:52:49.060 Because it is a horizontal box, it will be attached to the side like this 852 00:52:49.060 --> 00:52:52.200 And one more text 853 00:52:52.280 --> 00:52:58.079 Make the widget common, take the text widget, and add it to the button 854 00:53:03.159 --> 00:53:06.479 Okay, let's make it like this 855 00:53:06.479 --> 00:53:13.039 Press Ctrl+D to press the button and Ctrl+D to copy two things 856 00:53:13.040 --> 00:53:16.559 I'm going to put a spacer between these two 857 00:53:16.559 --> 00:53:22.960 Let's search for a spacer widget in the palette 858 00:53:22.960 --> 00:53:25.192 and add it between this button and the button like this 859 00:53:25.192 --> 00:53:29.712 If you highlight the spacer button like this, it will look like this 860 00:53:29.719 --> 00:53:35.239 I named the button at the top btn_retry 861 00:53:37.119 --> 00:53:37.960 Below 862 00:53:40.000 --> 00:53:43.000 I will enter btn_exit 863 00:53:43.000 --> 00:53:46.999 For the text value here 864 00:53:49.239 --> 00:53:51.800 enter retry as the value 865 00:53:53.479 --> 00:53:55.420 Enter retry like this 866 00:53:57.679 --> 00:54:00.899 Next, we will put exit as an exit 867 00:54:02.280 --> 00:54:07.130 Now, I'm going to select this Game Over UI 868 00:54:07.130 --> 00:54:09.380 and I'm going to align this to the exact center 869 00:54:11.000 --> 00:54:16.759 Let's align it to the center and add 0 to Position X 870 00:54:18.359 --> 00:54:21.499 Next, we will set the alignment to 0.5 871 00:54:23.200 --> 00:54:24.950 Should I make it a little bigger? 872 00:54:24.950 --> 00:54:28.959 I will set the Size X to about 600 873 00:54:31.739 --> 00:54:34.819 Let's set the Size Y to 50 874 00:54:36.320 --> 00:54:40.580 and I'll also lower the Y value of game Over 875 00:54:42.080 --> 00:54:47.339 Let's put it like this? I'll put it like this 876 00:54:48.919 --> 00:54:54.469 I'll put it in like this: about 155 877 00:54:54.469 --> 00:54:58.039 Next, select btn_retry 878 00:54:58.039 --> 00:55:01.679 and set the size part, fill 879 00:55:03.012 --> 00:55:04.792 Then it will be full 880 00:55:04.792 --> 00:55:11.039 I will set the background color to a slightly distinguishable blue color 881 00:55:11.039 --> 00:55:12.919 Then select space 882 00:55:15.320 --> 00:55:18.780 Select fill again, and there will be a space in the middle 883 00:55:20.559 --> 00:55:25.440 Lastly, select btn_exit and similarly select fill 884 00:55:25.440 --> 00:55:31.280 Then, I will set the background color of this exit to red to distinguish it 885 00:55:31.280 --> 00:55:35.960 Then, compile it so that it appears on the screen like this 886 00:55:35.960 --> 00:55:40.279 Now, with the content, 'I will make this UI appear like this,' let's implement it with this content 887 00:55:42.511 --> 00:55:45.571 Now, should this be shown on the screen at first or not? 888 00:55:45.571 --> 00:55:50.599 It shouldn't be visible, so GameoverUI will first 889 00:55:50.599 --> 00:55:54.460 set the Visibility property to hidden 890 00:55:55.731 --> 00:55:59.900 At first, this UI will not be visible on the screen 891 00:55:59.900 --> 00:56:04.119 Now, I set the Visibility property to hidden 892 00:56:04.120 --> 00:56:08.299 And in the code state, when the game is over, and you die 893 00:56:08.299 --> 00:56:11.960 I will transform it like this so that this screen appears 894 00:56:11.961 --> 00:56:14.140 Go to Visual Studio 895 00:56:14.140 --> 00:56:18.290 and navigate to the MainUI.h file in Visual Studio 896 00:56:18.290 --> 00:56:20.359 At the bottom 897 00:56:20.359 --> 00:56:21.400 Public 898 00:56:24.111 --> 00:56:28.019 I will add information related to GameoverUI 899 00:56:28.019 --> 00:56:32.840 So, set UPROPERTY to BlueprintReadWrite 900 00:56:32.840 --> 00:56:37.799 Now, let's connect the two in meta and bind them to connect them 901 00:56:37.799 --> 00:56:46.239 Connect it with the BindWidget class U horizontal box 902 00:56:46.799 --> 00:56:52.919 The name was GameoverUI, and if you look here, the name is exactly like this on capital letters 903 00:56:52.919 --> 00:56:59.039 Let's insert the GameoverUI value as it is like this 904 00:56:59.039 --> 00:57:00.259 Like this 905 00:57:02.239 --> 00:57:05.989 Just duplicate the one above 906 00:57:05.989 --> 00:57:10.539 This time, it was class UButton 907 00:57:10.539 --> 00:57:14.359 The button said btn_retry 908 00:57:17.280 --> 00:57:21.639 Press Ctrl+D to get one more class UButton 909 00:57:23.479 --> 00:57:25.540 This time it was btn_exit 910 00:57:29.640 --> 00:57:32.919 You can do this in DieProcess so that they appear on the screen 911 00:57:32.999 --> 00:57:40.399 I do build processing here, which can be seen on the screen in DieProcess 912 00:57:45.071 --> 00:57:47.511 Now, the compile was done normally without any errors 913 00:57:47.511 --> 00:57:53.599 Now, let's move to NetTPSCharacter's DieProcess 914 00:57:53.600 --> 00:57:57.359 At this time, it is grayed out like this, so it is not visible on the screen, right? 915 00:57:57.359 --> 00:58:00.359 You made the whole world turn gray 916 00:58:00.359 --> 00:58:03.779 Here, we will finally display the Die UI 917 00:58:05.599 --> 00:58:10.339 I have GameoverUI in MainUI 918 00:58:12.280 --> 00:58:20.640 There will be a SetVisibility property in GameoverUI in MainUI 919 00:58:20.640 --> 00:58:26.800 In addition, we will add the visible property like this 920 00:58:30.520 --> 00:58:33.520 At the top 921 00:58:34.760 --> 00:58:41.239 let's write #include to use the horizontal box 922 00:58:41.239 --> 00:58:43.960 To the component 923 00:58:47.199 --> 00:58:51.599 we will add the HorizontalBox h file 924 00:58:51.600 --> 00:58:56.749 Now, include the HorizontalBox h file in the component 925 00:58:56.749 --> 00:58:59.099 and you can use it 926 00:58:59.099 --> 00:59:02.599 So, let's try building again 927 00:59:02.599 --> 00:59:09.091 Then, when it dies, the screen is treated as if it is deactivated 928 00:59:09.091 --> 00:59:12.871 and GameoverUI is displayed on the screen 929 00:59:13.160 --> 00:59:16.559 Let's go and take a look, play 930 00:59:18.460 --> 00:59:21.060 Should I grab a gun and fight my opponent? 931 00:59:21.060 --> 00:59:26.340 When you shoot, what happens when it dies? 932 00:59:26.340 --> 00:59:30.291 A retry button and an exit button appear on the screen 933 00:59:30.291 --> 00:59:34.591 Then the screen becomes blurry and gray-toned 934 00:59:34.591 --> 00:59:38.180 and nothing has been connected yet, so it's like this 935 00:59:41.359 --> 00:59:46.791 So, we've done processing when it's died 936 00:59:46.791 --> 00:59:49.331 I even completed handling player deaths 937 00:59:51.439 --> 00:59:54.100 Let's summarize what we learned in this lecture 938 00:59:54.851 --> 00:59:56.332 Health Property Synchronization 939 00:59:56.332 --> 00:59:58.031 Health member variables are synchronized through replication and UI update logic is implemented 940 00:59:58.032 --> 00:59:59.831 Handle it in the Tick function to continue processing attribute replication, and switch it to the OnRep event function to reduce CPU processing operations 941 00:59:59.832 --> 01:00:01.503 Learn how to process billboarding so the HP bar remains visible to users 942 01:00:01.503 --> 01:00:02.823 Shooting and Death Effect 943 01:00:02.823 --> 01:00:05.351 Created UI and animations to handle hit effects By applying camera shake, a highly immersive shooting effect is expressed 944 01:00:05.351 --> 01:00:06.611 Insert a notify event into the animation that handles the death state, and write logic that can process it using a callback function at the desired timing 945 01:00:06.611 --> 01:00:07.851 By activating the Saturation option in the camera's post process, the screen turns gray when in a dead state 946 01:00:07.851 --> 01:00:09.391 Display UI in death state to allow choice between restart and end 947 01:00:09.391 --> 01:00:10.391 The End