WEBVTT 1 00:00:27.520 --> 00:00:29.400 Hello, this is Youngho Lee 2 00:00:29.400 --> 00:00:35.360 Today we will cover Crosshair and bullet UI, as well as reloading 3 00:00:35.360 --> 00:00:40.360 We will create Crosshair UI that stands for the aiming point 4 00:00:40.360 --> 00:00:43.460 This lets the user know where the collision happened 5 00:00:43.460 --> 00:00:46.040 Using LineTrace 6 00:00:46.040 --> 00:00:49.320 Second, we will create bullet UI 7 00:00:49.320 --> 00:00:53.440 This will show the user how many bullets are left 8 00:00:53.440 --> 00:00:55.840 And using Uniform Grid Panel widget 9 00:00:55.840 --> 00:00:58.920 We will learn about how to polish UI layout 10 00:00:58.920 --> 00:01:02.560 Finally we will implement reload 11 00:01:02.560 --> 00:01:05.860 We will learn how to process by syncing 12 00:01:05.860 --> 00:01:08.599 UI intialization work with reloading animation 13 00:01:08.599 --> 00:01:12.960 Here, we will use Notify Event of animation to process 14 00:01:13.780 --> 00:01:17.330 Crosshair and Bullet UI 15 00:01:19.920 --> 00:01:22.760 Let's create Crosshair UI 16 00:01:25.480 --> 00:01:29.420 Crosshair UI requires UMG at Unreal Engine 17 00:01:29.421 --> 00:01:32.040 Or Unreal Motion Graphics 18 00:01:32.040 --> 00:01:36.220 For that, let's first create a C++ class 19 00:01:36.220 --> 00:01:38.800 To control this UI 20 00:01:40.720 --> 00:01:45.240 Content Browser, at C++ Class folder 21 00:01:45.240 --> 00:01:49.379 Right click and New C++ Class 22 00:01:51.200 --> 00:01:55.260 Select All Classes 23 00:01:55.261 --> 00:01:57.900 And search for User Widget 24 00:01:57.900 --> 00:02:01.300 And as its parent class 25 00:02:01.300 --> 00:02:03.980 Select User Widget Class 26 00:02:06.080 --> 00:02:07.179 Next 27 00:02:09.119 --> 00:02:14.040 This class name is MainUI 28 00:02:15.360 --> 00:02:16.900 And Create Class 29 00:02:19.320 --> 00:02:22.279 And load everything again 30 00:02:22.279 --> 00:02:24.679 With this here 31 00:02:24.679 --> 00:02:28.400 This C++ class is now in the project 32 00:02:29.400 --> 00:02:30.480 MainUI 33 00:02:31.380 --> 00:02:34.640 And let's create a class that takes MainUI as its parent 34 00:02:35.480 --> 00:02:37.880 Let's create Widget Blueprint class 35 00:02:42.140 --> 00:02:48.400 NetTPS Content Browser, there's the UI folder below 36 00:02:48.400 --> 00:02:52.900 Let's make it here 37 00:02:52.900 --> 00:02:54.840 Right click 38 00:02:56.239 --> 00:03:00.699 User Widget, below User Interface 39 00:03:00.700 --> 00:03:04.699 We have Widget Blueprint, click 40 00:03:04.699 --> 00:03:08.599 As its parent class, at All Classes 41 00:03:08.599 --> 00:03:11.140 Search for MainUI 42 00:03:11.140 --> 00:03:14.620 Here, we have the freshly made MainUI class 43 00:03:16.560 --> 00:03:19.980 Select, rename as 44 00:03:19.980 --> 00:03:25.120 WBP that stands for Widget Blueprint, so WBP_MainUI 45 00:03:29.660 --> 00:03:34.339 And double click on MainUI Widget to open 46 00:03:41.639 --> 00:03:45.559 At MainUI Widget, we will be working on Crosshair 47 00:03:45.559 --> 00:03:47.580 So at the center 48 00:03:48.540 --> 00:03:51.460 We will add a crosshair 49 00:03:51.460 --> 00:03:57.880 So if this is the game screen, the crosshair will be here 50 00:03:57.881 --> 00:04:01.140 With the two lines on top of each other, thus crosshair 51 00:04:01.140 --> 00:04:05.400 We will create this crosshair here so that 52 00:04:05.400 --> 00:04:06.850 Whenever we shoot 53 00:04:06.850 --> 00:04:09.479 We can aim for the target 54 00:04:09.480 --> 00:04:12.639 That's the UI work we will do 55 00:04:12.639 --> 00:04:15.139 For that, first 56 00:04:15.139 --> 00:04:18.279 Let's add a Canvas Panel 57 00:04:18.279 --> 00:04:20.079 See the palette at the left 58 00:04:20.079 --> 00:04:23.679 At Palette, serach for Canvas 59 00:04:23.680 --> 00:04:26.279 Then we get Canvas Panel 60 00:04:26.279 --> 00:04:28.179 Drag and rop this Canvas Panel 61 00:04:28.179 --> 00:04:31.600 Into Hierarchy 62 00:04:31.600 --> 00:04:35.139 Then based on the resolution 63 00:04:35.140 --> 00:04:39.479 We get the outline for it 64 00:04:39.479 --> 00:04:41.579 It automatically resizes based on screen size 65 00:04:43.399 --> 00:04:47.679 And for Crosshair, we will have an image at the center 66 00:04:47.679 --> 00:04:50.739 We will add an Imadge Widget here 67 00:04:52.119 --> 00:04:55.880 Palette, Common, down there we see Image 68 00:04:55.880 --> 00:04:58.130 Image Widget, drag and drop 69 00:04:58.130 --> 00:05:01.040 Let's add it as the child of Canvas Panel 70 00:05:04.040 --> 00:05:08.960 See how Image Widget is here now 71 00:05:08.961 --> 00:05:12.020 Let's rename it 72 00:05:12.020 --> 00:05:17.480 Name it as img_Crosshair 73 00:05:23.639 --> 00:05:27.140 And since this crosshair will be at the center 74 00:05:27.141 --> 00:05:31.240 To the right at Details, we have Anchor 75 00:05:31.240 --> 00:05:35.800 Open the dropdown menu and we get anchor presets 76 00:05:35.800 --> 00:05:38.360 Let's align it to the center 77 00:05:42.079 --> 00:05:46.920 Then the anchor value goes in the center 78 00:05:46.920 --> 00:05:49.959 But this widget is at the top here 79 00:05:49.959 --> 00:05:53.359 So in order to position it at the center 80 00:05:53.359 --> 00:05:55.200 We need a few steps for that 81 00:05:55.200 --> 00:06:00.679 Let's add 0,0 for position X and Y 82 00:06:00.679 --> 00:06:01.420 Like so 83 00:06:04.359 --> 00:06:06.390 Center alignment for the anchor 84 00:06:06.390 --> 00:06:09.940 And 0,0 for position X and Y 85 00:06:11.340 --> 00:06:13.860 For size 86 00:06:13.860 --> 00:06:17.519 For both size X and Y, let's add 150, 150 87 00:06:20.279 --> 00:06:21.359 Which is huge 88 00:06:26.440 --> 00:06:31.490 And Alignment, 0.5, 0.5 89 00:06:31.490 --> 00:06:33.480 So 0.5 for each 90 00:06:33.480 --> 00:06:37.300 Then we see an image at the center 91 00:06:39.399 --> 00:06:43.999 And at Appearance, we need an image at this brush area 92 00:06:43.999 --> 00:06:48.980 So we can add the crosshair image right here 93 00:06:49.000 --> 00:06:52.100 Use a png image here 94 00:06:52.100 --> 00:06:56.400 So let's go to the class assets 95 00:06:58.600 --> 00:07:00.150 We have one in blue and one in red 96 00:07:00.150 --> 00:07:02.260 You can use whichever you like 97 00:07:03.960 --> 00:07:06.960 Let me start with the red one here 98 00:07:06.960 --> 00:07:10.839 For you, you can choose whichever 99 00:07:10.839 --> 00:07:14.839 Let me bring in this red Crosshair.png image 100 00:07:14.839 --> 00:07:16.989 Since png has the background 101 00:07:16.989 --> 00:07:20.320 As transparent, we can use it here 102 00:07:20.321 --> 00:07:23.320 So here at Contents Drawer 103 00:07:23.321 --> 00:07:24.571 We have UI folder 104 00:07:24.571 --> 00:07:26.920 Over here 105 00:07:26.920 --> 00:07:29.859 Drag and drop the image 106 00:07:32.280 --> 00:07:34.320 Then it is now here 107 00:07:34.320 --> 00:07:38.670 So this Crosshair image 108 00:07:38.670 --> 00:07:43.040 Drag and drp at the brush area like so 109 00:07:44.959 --> 00:07:48.640 Then now we get that Crosshair image here 110 00:07:52.279 --> 00:07:55.629 So now let's make sure this crosshair 111 00:07:55.629 --> 00:07:57.000 Is visible on screen 112 00:07:57.001 --> 00:07:58.501 It's not that when we play the game 113 00:07:58.501 --> 00:08:00.760 This crosshair widget will appear on the screen 114 00:08:00.780 --> 00:08:02.080 When we create this widget 115 00:08:02.080 --> 00:08:05.180 We need to add this widget to Viewport 116 00:08:06.140 --> 00:08:08.919 So go back to Visual Studio 117 00:08:10.640 --> 00:08:15.780 And at Visual Studio, go to NetTPSCharacter.h file 118 00:08:17.959 --> 00:08:22.660 At NetTPSCharacter header file 119 00:08:22.660 --> 00:08:25.500 Let's add some content regarding the widgets 120 00:08:26.960 --> 00:08:27.960 Public 121 00:08:30.920 --> 00:08:35.079 Let's add the widget classes for use 122 00:08:35.079 --> 00:08:39.740 U PROPERTY EditDefaultOnly 123 00:08:39.741 --> 00:08:41.741 At editor mode, at Blueprint 124 00:08:41.741 --> 00:08:44.640 We will allow for a drag and drop 125 00:08:44.640 --> 00:08:47.820 So category is UI 126 00:08:50.679 --> 00:08:57.760 TSubClassof class UMainUI type is the class we will accept here 127 00:08:57.760 --> 00:08:59.860 Our widget Blueprint 128 00:08:59.860 --> 00:09:02.559 It is also made out of inheriting MainUI class 129 00:09:02.559 --> 00:09:05.409 So through TSubClassof 130 00:09:05.409 --> 00:09:09.839 We can accept children of MainUI 131 00:09:09.839 --> 00:09:12.739 Let's add MainUI widget 132 00:09:15.119 --> 00:09:17.169 This widget that is made 133 00:09:17.169 --> 00:09:21.399 It will be on screen but it can also disappear if needed 134 00:09:21.399 --> 00:09:25.160 So we need to remember this widget that we created 135 00:09:25.161 --> 00:09:28.820 So in order to remember this widget instance 136 00:09:28.820 --> 00:09:35.279 Let's add a variable so that it remembers 137 00:09:37.519 --> 00:09:40.000 This instance made out of MainUI widget 138 00:09:40.000 --> 00:09:46.480 U PROPERTY class UMainUI 139 00:09:46.480 --> 00:09:48.619 Let's add that MainUI here 140 00:09:52.000 --> 00:09:55.560 And let's add a function that creates and initializes 141 00:09:55.560 --> 00:09:58.000 This widget right here 142 00:10:01.060 --> 00:10:03.760 So this is the initialization function 143 00:10:03.760 --> 00:10:07.160 void InitUIWidget 144 00:10:12.559 --> 00:10:16.159 InitUIWidget, at C++ 145 00:10:16.159 --> 00:10:19.300 Let's add it to NetTPSCharacter.cpp file 146 00:10:23.460 --> 00:10:27.680 So this is autofilled 147 00:10:28.880 --> 00:10:30.330 Alt Enter 148 00:10:30.330 --> 00:10:34.030 Or if you're using Visual Assist, Alt Shift Q 149 00:10:34.030 --> 00:10:35.300 That's how you can make it 150 00:10:37.080 --> 00:10:44.000 Add Init Widget function at ANetTPSCharacter 151 00:10:44.000 --> 00:10:48.300 And let's now add a code to create the widget 152 00:10:49.440 --> 00:10:51.290 First, when the user 153 00:10:52.240 --> 00:10:56.040 Adds MainUI Widget 154 00:10:56.040 --> 00:10:57.039 They should be able to create this 155 00:10:57.039 --> 00:10:59.960 If this is trying to create it even without the user assigning it 156 00:10:59.961 --> 00:11:02.880 This will be an attempt out of data that does not exist, which is an error 157 00:11:02.880 --> 00:11:07.500 So let's first check if MainUI widget is Null or not 158 00:11:07.500 --> 00:11:09.820 Or whether it has value or not 159 00:11:12.039 --> 00:11:15.159 Let's add this code that checks for that 160 00:11:15.160 --> 00:11:17.819 And then for MainUI 161 00:11:17.819 --> 00:11:19.979 Let's create it from this MainUI widget 162 00:11:22.419 --> 00:11:26.840 Use create-widget 163 00:11:26.840 --> 00:11:32.440 And GetWorld, and add MainUI widget 164 00:11:32.440 --> 00:11:35.740 So since widget just creates User widget 165 00:11:35.740 --> 00:11:43.219 Let's just cast it here and wrap it 166 00:11:44.719 --> 00:11:49.239 Now we will be using UMainUI 167 00:11:52.660 --> 00:11:56.870 And in order to print MainUI on screen 168 00:11:56.870 --> 00:12:02.459 AddToViewport is needed 169 00:12:08.939 --> 00:12:12.980 In order to use MainUI widget 170 00:12:12.980 --> 00:12:16.000 We need a header file at the top 171 00:12:17.880 --> 00:12:20.130 # include 172 00:12:20.130 --> 00:12:23.530 And add that MainUI header file 173 00:12:23.530 --> 00:12:24.459 That's how 174 00:12:27.559 --> 00:12:29.320 We can use this 175 00:12:30.840 --> 00:12:34.140 So this InitUIWidget 176 00:12:34.140 --> 00:12:37.960 Let's call it so that it appears on screen 177 00:12:37.960 --> 00:12:39.460 Where do we work on it? 178 00:12:39.460 --> 00:12:41.719 Let's do it at BeginPlay 179 00:12:41.719 --> 00:12:45.269 Over here, below fire, we can add it here 180 00:12:45.269 --> 00:12:49.479 Notice how this initialization function 181 00:12:49.480 --> 00:12:51.580 Is right next to the user input function 182 00:12:51.580 --> 00:12:55.129 So let's place this along with BeginPlay 183 00:12:55.129 --> 00:12:57.719 That take care of init function 184 00:12:57.719 --> 00:13:00.169 I will cut this part 185 00:13:00.169 --> 00:13:03.440 Ctrl+X to cut 186 00:13:03.440 --> 00:13:05.640 And over at BeginPlay function 187 00:13:05.640 --> 00:13:09.540 At the bottom of BeginPlay function 188 00:13:09.540 --> 00:13:11.920 Let's paste it like so 189 00:13:13.599 --> 00:13:18.359 Then, this lifecycle function that is called when BeginPlay starts 190 00:13:18.359 --> 00:13:22.940 Below this BeginPlay, I have added 191 00:13:22.940 --> 00:13:25.900 That InitUIWidget function is declared 192 00:13:27.500 --> 00:13:30.280 And at the bottom of BeginPlay 193 00:13:30.280 --> 00:13:35.400 Let's have InitUIWidget called like so 194 00:13:35.400 --> 00:13:38.780 Then, when it is born 195 00:13:38.780 --> 00:13:41.100 BeginPlay assigns the input 196 00:13:41.100 --> 00:13:44.850 And the actors needed for the gun search 197 00:13:44.850 --> 00:13:46.700 Searching for gun actors 198 00:13:46.700 --> 00:13:50.860 And the code for the UI goes here 199 00:13:52.640 --> 00:13:55.619 So let's process this build 200 00:14:03.179 --> 00:14:05.160 When the build is successful 201 00:14:05.160 --> 00:14:06.900 Go to Unreal Editor 202 00:14:08.199 --> 00:14:12.320 Go to Blueprint folder, below NetTPS 203 00:14:12.320 --> 00:14:16.280 And open BPThirdPerson Blueprint 204 00:14:17.639 --> 00:14:20.679 At Details, let's search by UI 205 00:14:20.679 --> 00:14:22.129 As MainUI 206 00:14:22.129 --> 00:14:25.800 Then we get that MainUI widget that we created 207 00:14:27.919 --> 00:14:30.069 Like so 208 00:14:30.069 --> 00:14:31.179 Over here 209 00:14:33.400 --> 00:14:37.680 Let's choose WBP_MainUI 210 00:14:42.419 --> 00:14:43.559 And compile 211 00:14:46.419 --> 00:14:49.080 Let's run this 212 00:14:49.080 --> 00:14:52.400 Now we see the crosshair 213 00:14:52.400 --> 00:14:55.400 Let's go grab the gun 214 00:14:55.400 --> 00:14:56.750 And aim and shoot 215 00:14:56.750 --> 00:15:01.839 We see how it shoots right at the center of our crosshair 216 00:15:04.239 --> 00:15:06.679 But there seems to be a problem 217 00:15:06.680 --> 00:15:08.530 When we run it 218 00:15:08.530 --> 00:15:11.259 It's good that our crosshair is at the center 219 00:15:11.259 --> 00:15:14.039 But it appears even when we don't have the gun yet 220 00:15:14.039 --> 00:15:15.839 So let's process it so that 221 00:15:15.839 --> 00:15:18.960 We only get Crosshair when we hold onto a gun 222 00:15:18.960 --> 00:15:23.051 So in order to hide and then show the crosshair 223 00:15:23.051 --> 00:15:26.371 We need a function to process that 224 00:15:26.371 --> 00:15:30.140 And then we need a logic that tests conditions 225 00:15:30.140 --> 00:15:34.239 So that Crosshair UI is not visible on screen 226 00:15:34.239 --> 00:15:36.580 Based on whether Player is holding onto a gun or not 227 00:15:39.000 --> 00:15:43.139 For that, let's go back to Visual Studio 228 00:15:44.739 --> 00:15:48.640 Go to MainUI header file 229 00:15:49.100 --> 00:15:51.600 MainUI literally is 230 00:15:51.600 --> 00:15:57.240 The C++ class file that shows Crosshair now 231 00:15:57.240 --> 00:16:00.660 Here, the one in use now 232 00:16:01.600 --> 00:16:03.700 This Crosshair, this 233 00:16:03.700 --> 00:16:07.000 Let's make it visible and invisible on screen 234 00:16:09.440 --> 00:16:11.740 For that, first 235 00:16:14.239 --> 00:16:17.559 Public to declare 236 00:16:17.559 --> 00:16:19.640 MainUI.header file 237 00:16:19.640 --> 00:16:21.590 And what of this are we 238 00:16:21.590 --> 00:16:23.840 Trying to show and hide? 239 00:16:23.841 --> 00:16:27.680 It's this file, img_Crosshair 240 00:16:27.680 --> 00:16:32.359 This UI or widget is what we want to show and hide 241 00:16:32.359 --> 00:16:34.820 Here we have options for Visibility 242 00:16:39.760 --> 00:16:41.860 Here's that Visibility option 243 00:16:41.860 --> 00:16:44.119 It is at 'visible' now 244 00:16:44.120 --> 00:16:46.520 Let's try changing it 245 00:16:46.520 --> 00:16:48.119 We have other things like 'Hidden' 246 00:16:48.119 --> 00:16:52.359 Let's set it as Hidden, and when we compile it 247 00:16:52.359 --> 00:16:53.959 When we go back and play 248 00:16:53.959 --> 00:16:56.359 It is now hidden on the screen 249 00:16:56.359 --> 00:16:57.980 When we work on it 250 00:17:00.280 --> 00:17:04.800 We don't see it when we run it 251 00:17:04.801 --> 00:17:08.200 So right now Visibility is set as Visible 252 00:17:08.200 --> 00:17:11.160 For us to control this option 253 00:17:11.160 --> 00:17:13.810 Between Hidden and Visible 254 00:17:13.810 --> 00:17:15.200 We need some set of works 255 00:17:20.799 --> 00:17:26.080 First let's allow for control for img_Crosshair 256 00:17:26.080 --> 00:17:34.280 So here, class U imae img_Crosshair 257 00:17:34.281 --> 00:17:36.720 Let's declare to control 258 00:17:36.720 --> 00:17:42.880 So this img_Crosshair corresponds to who? 259 00:17:42.881 --> 00:17:47.481 It corresponds to WBP MainUI's img_Crosshair 260 00:17:47.481 --> 00:17:49.060 With that same name 261 00:17:49.060 --> 00:17:51.679 So this corresponding 262 00:17:51.680 --> 00:17:53.819 Also means that they are bound 263 00:17:53.819 --> 00:17:59.369 So let's bind this variable with this widget variable 264 00:17:59.369 --> 00:18:00.600 Using the binding 265 00:18:02.280 --> 00:18:07.080 Therefore, we need to declare a property that binds the two widgets 266 00:18:07.080 --> 00:18:09.880 For which we use UPROPRETY 267 00:18:09.880 --> 00:18:11.680 Here, Blueprint 268 00:18:14.980 --> 00:18:17.300 I will add ReadWrite 269 00:18:18.340 --> 00:18:22.599 So for category, let's just say UI 270 00:18:22.599 --> 00:18:25.199 And using the meta keyword 271 00:18:25.199 --> 00:18:28.639 We process it by using bind widget 272 00:18:30.000 --> 00:18:34.580 And let's build it 273 00:18:34.580 --> 00:18:38.460 So this that is declared with bind widget 274 00:18:38.461 --> 00:18:41.560 This binds all widgets with the same name as img_Crosshair 275 00:18:41.561 --> 00:18:44.060 Meaning, the two becomes one 276 00:18:44.060 --> 00:18:47.439 So what value goes in here? 277 00:18:47.440 --> 00:18:51.199 This img_Crosshair over here 278 00:18:51.199 --> 00:18:53.099 And where do we check for this? 279 00:18:53.099 --> 00:18:55.599 BindWidget, we have another tab here 280 00:18:55.600 --> 00:18:57.419 So click on that tab 281 00:18:57.420 --> 00:19:01.419 And we see the BindWidget being processed 282 00:19:01.419 --> 00:19:05.680 So here, img_Crosshair is added to BindWidget 283 00:19:05.680 --> 00:19:06.799 It has the tick mark 284 00:19:09.040 --> 00:19:11.480 So we can see that the work is done 285 00:19:11.499 --> 00:19:15.739 So at C++, when we run the Blueprint 286 00:19:15.739 --> 00:19:19.719 At img_Crosshair, this widget is to be added automatically 287 00:19:21.560 --> 00:19:25.210 Next, let's add a variable that will 288 00:19:25.210 --> 00:19:27.240 Make this widget visible and invisible 289 00:19:27.240 --> 00:19:31.399 So this variable processes 290 00:19:33.080 --> 00:19:36.039 Whether to show this Crosshair 291 00:19:36.039 --> 00:19:42.639 So void show Crosshair, and isShow 292 00:19:44.079 --> 00:19:47.200 Let's add this parameter 293 00:19:51.439 --> 00:19:55.819 So let's add implementation to our cpp file 294 00:19:58.840 --> 00:20:02.840 Here, we will be processing 295 00:20:02.841 --> 00:20:07.080 To show and now show img_Crosshair, so isShow option 296 00:20:07.080 --> 00:20:10.839 It will change based on its variable value 297 00:20:10.839 --> 00:20:14.660 If isShow value is True 298 00:20:14.660 --> 00:20:17.860 It shows, so at img_Crosshair 299 00:20:19.520 --> 00:20:21.280 Set Visibility 300 00:20:26.760 --> 00:20:28.860 So this Set Visibility option 301 00:20:30.800 --> 00:20:33.720 Is set as Visible 302 00:20:33.720 --> 00:20:35.640 And if not 303 00:20:40.120 --> 00:20:42.059 We will keep it hidden 304 00:20:49.320 --> 00:20:53.800 And over at the top, to use that image widget 305 00:20:53.800 --> 00:20:55.300 With the Include option 306 00:20:56.860 --> 00:20:58.580 At Component 307 00:21:00.500 --> 00:21:04.260 Let's add Image.h 308 00:21:07.240 --> 00:21:12.640 And this ShowCrosshair function should be called somewhere 309 00:21:12.641 --> 00:21:14.641 So call when Player has the gun 310 00:21:14.641 --> 00:21:16.240 And if now 311 00:21:16.240 --> 00:21:18.340 Call False, and with the gun 312 00:21:18.340 --> 00:21:20.639 Call True, that's how it works 313 00:21:20.639 --> 00:21:24.920 Let's now build where it calls ShowCrosshair 314 00:21:25.520 --> 00:21:26.520 Which happens at 315 00:21:27.140 --> 00:21:30.240 NetTPSCharacter at cpp file 316 00:21:30.241 --> 00:21:33.891 InitUIWidget, when UI is first built 317 00:21:33.891 --> 00:21:35.720 Player won't hold the gun when it's first born 318 00:21:35.720 --> 00:21:38.420 We need to go pick up the gun 319 00:21:38.420 --> 00:21:39.700 So what happens then? 320 00:21:41.420 --> 00:21:43.820 Crosshair is invisible 321 00:21:43.820 --> 00:21:45.140 So at MainUI 322 00:21:47.960 --> 00:21:52.160 At MainUI, go to ShowCrosshair and add False 323 00:21:52.161 --> 00:21:57.280 Then it becomes invisible 324 00:21:57.280 --> 00:22:02.459 And when it picks up the gun, then Crosshair should be visible 325 00:22:02.459 --> 00:22:06.599 This is attachPistol, so here 326 00:22:09.139 --> 00:22:12.240 ShowCrosshair should be True 327 00:22:14.660 --> 00:22:16.960 Meaning Crosshair is visible 328 00:22:16.960 --> 00:22:19.580 And with Detach 329 00:22:19.580 --> 00:22:21.279 With Detach 330 00:22:23.920 --> 00:22:29.140 LIke so, since the gun is away, it should be invisible 331 00:22:29.140 --> 00:22:31.980 So the Crosshair should be gone 332 00:22:31.980 --> 00:22:33.980 That's how we process it 333 00:22:33.980 --> 00:22:35.480 Let's build it 334 00:22:42.399 --> 00:22:42.940 Done 335 00:22:44.260 --> 00:22:47.439 Let's go to Unreal Editor and play 336 00:22:49.520 --> 00:22:51.399 At first, we don't see Crosshair 337 00:22:51.400 --> 00:22:54.679 Let's go hold onto that gun 338 00:22:54.679 --> 00:22:58.099 Then we get Crosshair, try shooting with z 339 00:22:58.099 --> 00:23:01.440 And let's let the gun to, and Crosshair disappears 340 00:23:01.440 --> 00:23:04.960 Press f again, and it appears, and drop 341 00:23:05.980 --> 00:23:10.280 And it is gone, so this works 342 00:23:10.280 --> 00:23:12.900 We worked on displaying Crosshair on screen 343 00:23:14.180 --> 00:23:18.459 Next, let's create our Bullet UI 344 00:23:18.459 --> 00:23:22.860 Bullet UI means, when we play here 345 00:23:22.861 --> 00:23:26.260 When we hold the gun, we get our Crosshair 346 00:23:26.260 --> 00:23:31.940 But it does not have any limitation as to how many bullets I can shoot 347 00:23:31.940 --> 00:23:35.280 So it doesn't have infinite bullets 348 00:23:35.281 --> 00:23:38.920 It should stop shooting when it runs out of bullets 349 00:23:38.920 --> 00:23:41.680 So let's work on that part 350 00:23:42.580 --> 00:23:47.660 So this is about adding to this screen 351 00:23:47.660 --> 00:23:50.060 The Bullet UI at the bottom 352 00:23:50.060 --> 00:23:52.939 Like as I'm outlining here 353 00:23:52.940 --> 00:23:56.979 It will show remaining bullets 354 00:23:56.980 --> 00:24:01.879 So that whenever I shoot, this number of bullets 355 00:24:01.879 --> 00:24:04.639 Get updated based on how many is left 356 00:24:06.059 --> 00:24:12.740 For that, go to WEB MainUI at UI folder 357 00:24:12.741 --> 00:24:17.240 Same thing, since it is a widget that shows UI on screen 358 00:24:17.240 --> 00:24:20.040 We will be adding here at the bottom 359 00:24:20.040 --> 00:24:21.619 Let's add that UI 360 00:24:21.620 --> 00:24:24.959 Like so, at the bottom 361 00:24:24.959 --> 00:24:28.139 But we won't set up all the bullets in advance 362 00:24:28.140 --> 00:24:29.090 Instead 363 00:24:29.090 --> 00:24:32.579 It only displays the remaining number of bullets 364 00:24:32.579 --> 00:24:36.059 So we need that automatic increase 365 00:24:36.059 --> 00:24:39.921 So the panel for that is 366 00:24:39.921 --> 00:24:43.821 Let's use Uniform Grid Panel 367 00:24:45.739 --> 00:24:47.689 Grid, literally 368 00:24:47.689 --> 00:24:50.419 It is in shape of a grid 369 00:24:50.420 --> 00:24:54.399 So we can add that grid and add each like so 370 00:24:54.400 --> 00:24:57.339 It's like a matrix, or a tile 371 00:24:57.339 --> 00:24:59.289 Like so, we can add 372 00:24:59.289 --> 00:25:01.660 Each of the widgets we want 373 00:25:01.661 --> 00:25:05.080 Search for Uniform Grid Panel at Palette 374 00:25:05.080 --> 00:25:07.130 And it is the child of Canvas 375 00:25:07.130 --> 00:25:09.259 Let's drag and drop to add so 376 00:25:09.259 --> 00:25:13.120 Then we get that panel here 377 00:25:16.100 --> 00:25:19.850 Let's set its location value 378 00:25:19.850 --> 00:25:23.899 Let's align it at the bottom left 379 00:25:23.899 --> 00:25:27.099 So its anchor value at Details 380 00:25:27.099 --> 00:25:30.459 Let's add it to the bottom left 381 00:25:32.660 --> 00:25:38.979 Then it pivots to the bottom left, the anchor value 382 00:25:38.979 --> 00:25:43.841 Its position X and Y values, 10 383 00:25:43.841 --> 00:25:47.521 And let's bring it up a bit, so -10 384 00:25:52.459 --> 00:25:54.609 And alignment 385 00:25:54.609 --> 00:25:58.031 X value stays, and Y is 1 386 00:25:58.031 --> 00:26:01.801 So this is what we see over here 387 00:26:02.739 --> 00:26:04.039 So here 388 00:26:05.579 --> 00:26:09.541 So this is the X value for this spacing, by 10 389 00:26:09.541 --> 00:26:12.161 And by Y value, this spacing by 10 390 00:26:14.980 --> 00:26:17.580 That's how it is made 391 00:26:17.580 --> 00:26:20.899 And we will be adding the widgets here 392 00:26:20.899 --> 00:26:25.341 And in order for this to resize itself based on the attached size 393 00:26:25.341 --> 00:26:28.091 Let's go to Details and go to Size to Content 394 00:26:28.091 --> 00:26:30.740 Let's tick this box 395 00:26:30.740 --> 00:26:32.540 Then now it is tiny 396 00:26:32.540 --> 00:26:34.179 It's because we don't have anything 397 00:26:34.180 --> 00:26:37.299 And the moment we add that bullet widget we need 398 00:26:37.299 --> 00:26:40.540 It will resize itself based on that 399 00:26:40.541 --> 00:26:41.441 Done 400 00:26:41.441 --> 00:26:45.320 Now let's add the widget here 401 00:26:45.320 --> 00:26:46.979 First compile 402 00:26:50.161 --> 00:26:55.101 Go to UI folder, right click 403 00:26:55.101 --> 00:27:00.079 At User Widget, select Widget Blueprint 404 00:27:02.601 --> 00:27:04.561 Select User Widget 405 00:27:05.600 --> 00:27:06.300 Select 406 00:27:06.300 --> 00:27:07.600 There is User Widget on top as well 407 00:27:07.600 --> 00:27:10.399 It's the same thing, so you can choose whichever 408 00:27:10.399 --> 00:27:15.219 Let's say WBP_Bullet 409 00:27:17.220 --> 00:27:19.719 Its name is WBP_Bullet 410 00:27:21.341 --> 00:27:23.921 Double click to open 411 00:27:23.921 --> 00:27:27.660 Let's add an image here 412 00:27:27.660 --> 00:27:31.940 At Image Palette, we have Image Widget 413 00:27:31.941 --> 00:27:33.980 Add it like so 414 00:27:33.981 --> 00:27:36.380 Drag and drop at Hierarchy 415 00:27:36.380 --> 00:27:38.080 Do we not need a canvas? 416 00:27:38.080 --> 00:27:39.119 It's not necessary 417 00:27:39.119 --> 00:27:42.579 Since we are only using a widget, this is fine 418 00:27:44.581 --> 00:27:49.521 So select this, and we have a few tings at Details 419 00:27:49.521 --> 00:27:51.940 We need an image for that brush 420 00:27:51.941 --> 00:27:54.141 And we don't have that image yet 421 00:27:54.141 --> 00:27:55.740 We will be importing an image 422 00:27:55.741 --> 00:27:57.580 And we have Image Size 423 00:27:57.580 --> 00:28:01.480 For this size, let's add 50 and 50 424 00:28:01.480 --> 00:28:05.940 And this widget will be at the bottom left with this size 425 00:28:08.221 --> 00:28:11.921 And then we need an image to add at this Widget 426 00:28:11.921 --> 00:28:15.934 Go to our Assets 427 00:28:15.934 --> 00:28:17.694 And we have our bullet asset 428 00:28:18.401 --> 00:28:21.961 See this BulletSprite.png? 429 00:28:21.961 --> 00:28:24.111 Let's bring it to our project 430 00:28:24.111 --> 00:28:26.660 And put it in our UI folder 431 00:28:26.660 --> 00:28:28.140 Drag and drop 432 00:28:30.220 --> 00:28:31.819 So it drops like so 433 00:28:34.399 --> 00:28:37.649 So to this image 434 00:28:37.649 --> 00:28:41.940 Add our Sprite image 435 00:28:41.940 --> 00:28:44.479 Then we see this bullet 436 00:28:48.619 --> 00:28:50.581 Compile 437 00:28:50.581 --> 00:28:54.181 You can close WBP_Bullet now 438 00:28:55.820 --> 00:28:59.070 So let's check if this is working well 439 00:28:59.070 --> 00:29:01.459 We have WBP_MainUI 440 00:29:01.460 --> 00:29:05.219 And we have Uniform Grid Panel here, right? 441 00:29:05.219 --> 00:29:10.100 Let's rename this Uniform Grid Panel 442 00:29:10.100 --> 00:29:15.779 Let's rename it as BulletPanel 443 00:29:15.780 --> 00:29:18.039 So with this BulletPanel 444 00:29:18.040 --> 00:29:20.779 Let's add one by one at BulletPanel 445 00:29:20.779 --> 00:29:25.540 So at Palette, we just made our WBP_Bullet 446 00:29:25.540 --> 00:29:27.490 We can search for it 447 00:29:27.490 --> 00:29:29.100 And drag and drop 448 00:29:29.101 --> 00:29:32.940 To add it as the child of BulletPanel, and ta-da 449 00:29:32.940 --> 00:29:38.100 It is on the screen, it shows like so 450 00:29:39.360 --> 00:29:41.220 See how it is at the bottom left? 451 00:29:43.281 --> 00:29:47.979 And now, Ctrl+D to add another WBP_Bullet 452 00:29:47.979 --> 00:29:49.929 It does add, but 453 00:29:49.929 --> 00:29:52.619 Under Hierarchy, it says that it has been added 454 00:29:52.619 --> 00:29:54.119 But that's not what we see here 455 00:29:54.119 --> 00:29:54.669 The reason it 456 00:29:54.669 --> 00:29:55.640 Its position is overlapping 457 00:29:57.261 --> 00:30:01.361 Thoes added as children of BulletPanel 458 00:30:01.361 --> 00:30:06.419 At Details, we have options for row and column 459 00:30:06.420 --> 00:30:09.879 The options for row and column 460 00:30:09.880 --> 00:30:11.780 For row and column 461 00:30:11.780 --> 00:30:14.579 Let's skip row and add to column 462 00:30:14.579 --> 00:30:18.279 So that it adds to different columns, like next to each other 463 00:30:18.279 --> 00:30:20.179 So for this first one 464 00:30:20.179 --> 00:30:24.659 If I add 1 to its column, this is what happens 465 00:30:24.659 --> 00:30:28.439 For the second, I can say 2 to its column 466 00:30:30.179 --> 00:30:31.229 See? 467 00:30:31.229 --> 00:30:36.359 So their row, let's try 0 and then 1 468 00:30:38.419 --> 00:30:41.099 Then we see how it moves starting with 0 469 00:30:41.100 --> 00:30:43.999 Thoes that are 1 right now 470 00:30:44.000 --> 00:30:46.779 These are 1, so they are at the bottom, and these 0's are at the top 471 00:30:46.779 --> 00:30:51.219 This is how we can work with different row and column 472 00:30:51.220 --> 00:30:56.559 So these are up just for the sake of testing 473 00:30:56.559 --> 00:31:00.979 We will only use one row 474 00:31:00.979 --> 00:31:06.029 And we will have as many columns as there are bullets 475 00:31:06.029 --> 00:31:13.321 To control this, let's go to MainUIWidget C++ Class 476 00:31:13.321 --> 00:31:15.981 And add a code for that 477 00:31:18.500 --> 00:31:22.160 Let's go to Visual Studio and to the MainUI Header file 478 00:31:24.261 --> 00:31:25.501 Over here 479 00:31:27.340 --> 00:31:32.139 Let's add the members to show Bullet UI 480 00:31:33.401 --> 00:31:36.501 MainUI.h file 481 00:31:36.501 --> 00:31:40.501 And the panel to add Bullet Widget 482 00:31:40.501 --> 00:31:43.519 It's our Uniform Grid Panel 483 00:31:43.539 --> 00:31:50.939 And then we had Bullet Widget Class, WBP_Bullet 484 00:31:52.659 --> 00:31:55.209 Let's bring them in and add to the Bullet Widget 485 00:31:55.209 --> 00:31:57.419 That's the code we will write 486 00:31:57.420 --> 00:32:01.319 And we will create a function where 487 00:32:01.319 --> 00:32:05.060 This Bullet Widget keeps getting added to BulletPanel 488 00:32:07.121 --> 00:32:11.981 So the function to add Bullet Widget 489 00:32:11.981 --> 00:32:15.700 So, first the panel to add Bullet Widget 490 00:32:15.701 --> 00:32:18.180 Let's create using U PROPERTY 491 00:32:18.180 --> 00:32:21.580 And at Blueprint ReadWrite 492 00:32:21.580 --> 00:32:23.380 Shall we bring it from the top? 493 00:32:27.641 --> 00:32:28.501 Done 494 00:32:28.501 --> 00:32:35.181 And class UUniformGridPanel 495 00:32:35.181 --> 00:32:36.881 Declare the class 496 00:32:36.881 --> 00:32:39.980 The name is BulletPanel 497 00:32:41.940 --> 00:32:44.040 And then Bullet Widget Class 498 00:32:44.040 --> 00:32:46.940 Same thing, UPROPERTY 499 00:32:46.940 --> 00:32:49.940 DefaultOnly 500 00:32:49.940 --> 00:32:53.739 And Blueprint ReadWrite 501 00:32:53.739 --> 00:32:59.659 Category, let's say Bullet to distinguish 502 00:32:59.659 --> 00:33:04.620 TSubClassof, class UUserWidget 503 00:33:07.820 --> 00:33:11.520 Let's say Bullet UI Factory 504 00:33:11.520 --> 00:33:12.940 I said Factory for a reason 505 00:33:12.940 --> 00:33:17.319 Because this is different from instance, it's a file 506 00:33:18.721 --> 00:33:21.761 And the function that adds Bullet Widget 507 00:33:21.761 --> 00:33:25.260 Let's add it in the name of void add bullet 508 00:33:25.820 --> 00:33:28.970 Let's implement add bullet 509 00:33:28.970 --> 00:33:32.920 Let's add the implementation at the cpp file 510 00:33:35.001 --> 00:33:41.221 Let's create a WBP bullet here 511 00:33:41.221 --> 00:33:44.979 Its instance, so auto 512 00:33:44.979 --> 00:33:48.079 BulletWidget 513 00:33:48.079 --> 00:33:53.159 CreateWidget, GetWorld 514 00:33:53.159 --> 00:33:56.309 BulletUIFactory 515 00:33:56.309 --> 00:33:58.740 With that, WBP_Bullet 516 00:34:00.580 --> 00:34:04.220 We just wrote a cote to create a widget 517 00:34:06.381 --> 00:34:08.701 So we created a widget like so 518 00:34:08.701 --> 00:34:12.500 And we need to add it to BulletPanel 519 00:34:12.539 --> 00:34:16.139 So at BulletPanel 520 00:34:16.139 --> 00:34:23.700 Add it to the function AddChildtoUniformGrid 521 00:34:23.700 --> 00:34:25.899 Add BulletWidget here 522 00:34:32.221 --> 00:34:35.781 And at the back we have the row value 523 00:34:35.781 --> 00:34:39.739 Keep the row value as 0 524 00:34:39.780 --> 00:34:44.430 And following that we need the column value 525 00:34:44.430 --> 00:34:45.500 Whose default is 0 526 00:34:45.501 --> 00:34:49.920 But for us we need different values based on how many are in there 527 00:34:49.920 --> 00:34:54.700 And we need the increasing value by one 528 00:34:54.701 --> 00:34:59.980 So for example if we have three bullets now 529 00:34:59.980 --> 00:35:04.579 Then the next one should have the column of 4 530 00:35:04.580 --> 00:35:08.439 And then next one 5, like so 531 00:35:08.439 --> 00:35:13.459 We need to increase the size by its max + 1 532 00:35:13.459 --> 00:35:18.099 So this is the adding index for this 533 00:35:18.100 --> 00:35:23.699 At BulletPanel we can import the number of child it has 534 00:35:23.699 --> 00:35:26.719 By using getChildCount 535 00:35:28.121 --> 00:35:31.501 So we need as this number, why? 536 00:35:31.501 --> 00:35:36.019 When the child is added 537 00:35:37.641 --> 00:35:41.721 It adds starting with 0, 1, 2, 3, 4 538 00:35:41.722 --> 00:35:44.961 So all the added things are here 539 00:35:44.961 --> 00:35:47.659 And the first one is added at 0 540 00:35:47.660 --> 00:35:51.999 So getChildCount becomes 0 541 00:35:51.999 --> 00:35:53.699 And with one new, it's 1 542 00:35:53.699 --> 00:35:55.700 And the count is 1 543 00:35:55.701 --> 00:35:59.900 Meaning, the second one has its index at 1 544 00:35:59.900 --> 00:36:03.179 Because 0 contains the one before 545 00:36:03.201 --> 00:36:06.081 The second one goes into 1 546 00:36:06.559 --> 00:36:09.920 So it should go into the index 1 547 00:36:09.921 --> 00:36:13.140 So by using getChildCount 548 00:36:13.140 --> 00:36:15.839 We can keep adding to the desired index 549 00:36:17.940 --> 00:36:21.090 So here BulletPanel 550 00:36:21.090 --> 00:36:24.259 Let's add by including Uniform Grid Panel 551 00:36:27.261 --> 00:36:32.001 Inside the component, add Uniform Grid Panel header file like so 552 00:36:32.001 --> 00:36:35.451 And now call AddBullet 553 00:36:35.451 --> 00:36:37.619 The bullet number we want 554 00:36:37.619 --> 00:36:40.719 It calls AddBullet for the remaining bullet number 555 00:36:40.719 --> 00:36:42.879 Then it will show on the screen 556 00:36:42.880 --> 00:36:45.059 And this part is worked at 557 00:36:45.059 --> 00:36:47.359 NetTPSCharacter Header file 558 00:36:47.359 --> 00:36:49.399 Let's add that content 559 00:36:53.021 --> 00:36:58.281 Below the bottom of the file, add public 560 00:36:58.281 --> 00:37:02.580 I will add Bullet UI 561 00:37:02.580 --> 00:37:06.280 And Bullet Member 562 00:37:08.621 --> 00:37:12.121 And we don't know how many is left 563 00:37:13.461 --> 00:37:15.261 But it starts with the maximum bullet number 564 00:37:15.261 --> 00:37:19.059 Whether it loads 10 or 20 bullets 565 00:37:19.060 --> 00:37:23.979 So after Player shoots it all, 10 or 20 bullets should be reloaded 566 00:37:23.979 --> 00:37:27.859 So we need that maximum number first 567 00:37:27.860 --> 00:37:32.700 So let's declare that max bullet number here 568 00:37:32.700 --> 00:37:35.500 In order for designer to edit later 569 00:37:35.500 --> 00:37:38.700 Let's use UPROPERTY to expose it on Editor 570 00:37:38.700 --> 00:37:43.359 Edit Anywhere, and category 571 00:37:45.141 --> 00:37:46.661 It's Bullet 572 00:37:47.819 --> 00:37:52.659 int32 MaxBulletCount 573 00:37:52.659 --> 00:37:56.920 I will only allow for 10 bullets 574 00:37:58.380 --> 00:38:01.999 And then the remaining bullet number 575 00:38:05.761 --> 00:38:06.482 How many 576 00:38:06.482 --> 00:38:09.601 How many have I shot and how many do I have left? 577 00:38:09.601 --> 00:38:13.740 So let's add BulletCount 578 00:38:15.580 --> 00:38:19.839 And initialize the remaining bullet number with MaxBulletCount 579 00:38:26.161 --> 00:38:30.281 It's in capital letters because this is to be used as a constant 580 00:38:30.281 --> 00:38:34.060 So we could use const for constant 581 00:38:34.061 --> 00:38:37.260 But then this won't be exposed to Editor 582 00:38:37.261 --> 00:38:39.240 So I didn't use const 583 00:38:39.240 --> 00:38:43.340 So in order for this to be used as a contstant 584 00:38:43.340 --> 00:38:45.939 I wrote the variable name in capital letters 585 00:38:45.940 --> 00:38:47.779 Since its value keeps changing 586 00:38:47.779 --> 00:38:52.060 I wanted to keep editng it as a variable, so this is in small letters 587 00:38:52.061 --> 00:38:55.560 So this initializes BulletCount 588 00:38:55.560 --> 00:38:57.560 And one by one, bullet goes away 589 00:38:57.560 --> 00:38:59.219 This part should be added 590 00:38:59.219 --> 00:39:01.969 So based on BulletCount 591 00:39:01.969 --> 00:39:04.240 Let's allow for adding Bullet UI 592 00:39:04.241 --> 00:39:05.291 And that is done at 593 00:39:05.291 --> 00:39:09.699 The beginning at InitUIWidget 594 00:39:10.819 --> 00:39:15.780 So at cpp, let's get into InitUIWidget 595 00:39:15.781 --> 00:39:18.760 Under Crosshair 596 00:39:18.761 --> 00:39:22.140 It's about Bullet UI 597 00:39:22.140 --> 00:39:25.599 So let's add that initialization part 598 00:39:25.619 --> 00:39:31.979 So first for BulletCount we need MaxBulletCount 599 00:39:31.979 --> 00:39:33.779 Did we not do it here? 600 00:39:33.779 --> 00:39:36.579 Did we not do it at the header file? 601 00:39:36.580 --> 00:39:37.680 We did, but 602 00:39:37.680 --> 00:39:40.519 In order to process many things such as reload 603 00:39:40.519 --> 00:39:43.739 We need to call it again 604 00:39:43.740 --> 00:39:45.190 So how? 605 00:39:45.190 --> 00:39:48.390 In order to initialize this part 606 00:39:48.390 --> 00:39:50.220 Let's add that code 607 00:39:51.801 --> 00:39:55.439 In order to initialize the bullets 608 00:39:55.439 --> 00:40:00.260 Let's add the widget one by one to the UI with this code 609 00:40:00.260 --> 00:40:07.061 SO for int I starting with 0, I gets as big as BulletCount 610 00:40:07.061 --> 00:40:10.181 And it repeats 611 00:40:11.701 --> 00:40:13.841 And at MainUI 612 00:40:15.541 --> 00:40:19.121 Call AddBullet and 613 00:40:19.121 --> 00:40:20.971 It adds UI Widget 614 00:40:20.971 --> 00:40:23.639 Or Bullet Widget one by one 615 00:40:26.900 --> 00:40:28.659 So build 616 00:40:31.260 --> 00:40:33.540 Build and open Editor 617 00:40:38.459 --> 00:40:39.399 That's it 618 00:40:41.660 --> 00:40:47.019 Now go to WBP_MainUI 619 00:40:49.140 --> 00:40:52.520 And then to Graph 620 00:40:54.739 --> 00:41:00.619 At Details, let's serach for Bullet 621 00:41:00.620 --> 00:41:02.539 And it shows here 622 00:41:02.539 --> 00:41:06.089 We need the Widget for BulletUIFactory 623 00:41:06.089 --> 00:41:07.780 It's set as none here 624 00:41:07.780 --> 00:41:09.439 This, let's 625 00:41:11.981 --> 00:41:14.981 Select WBP_Bullet 626 00:41:16.039 --> 00:41:19.719 Let's add WBP_Bullet to BulletUIFactory 627 00:41:21.739 --> 00:41:22.899 Compile 628 00:41:25.541 --> 00:41:28.781 And play now 629 00:41:28.781 --> 00:41:33.498 And it shows the bullet UI at the bottom left 630 00:41:33.498 --> 00:41:34.179 Like so 631 00:41:38.501 --> 00:41:43.241 Then, grab the gun, and shoot 632 00:41:43.241 --> 00:41:44.391 But what happens? 633 00:41:44.391 --> 00:41:48.660 We haven't added the reduction part with the gunshoot 634 00:41:48.660 --> 00:41:54.579 It only shows the UI that we want 635 00:41:54.580 --> 00:41:57.830 So in order for this UI to reduce 636 00:41:57.830 --> 00:41:59.399 And remove the bullet 637 00:41:59.399 --> 00:42:01.699 Let's work on that part 638 00:42:01.699 --> 00:42:07.079 Visual Studio, now at MainUI.h file 639 00:42:08.581 --> 00:42:11.501 Let's add a function to remove bullets 640 00:42:11.519 --> 00:42:16.420 void, and to mean remove bullet, let's say 'pop' 641 00:42:16.420 --> 00:42:22.220 PopBullet int 32, and which of the index to be removed? 642 00:42:22.220 --> 00:42:23.380 Let's work on this 643 00:42:23.381 --> 00:42:26.200 It could start with the last one, or select a particular 644 00:42:26.200 --> 00:42:29.700 For me, I will bring in that index value 645 00:42:29.700 --> 00:42:32.739 And reduce it in this code 646 00:42:32.739 --> 00:42:37.580 So PopBullet, let's add it to MainUI.h cpp 647 00:42:40.959 --> 00:42:46.760 And here, at BulletPanel, we have 648 00:42:48.161 --> 00:42:50.481 Simple 'remove child at' 649 00:42:50.500 --> 00:42:52.350 And add the index value 650 00:42:52.350 --> 00:42:56.120 Then it removes UI of that index 651 00:42:59.121 --> 00:43:02.581 So when should this happen? 652 00:43:02.581 --> 00:43:05.031 When Player shoots 653 00:43:05.031 --> 00:43:08.819 At NetTPSCharacter.cpp, we have fire function 654 00:43:08.819 --> 00:43:13.819 So whenever Player shoots 655 00:43:13.819 --> 00:43:14.319 What happens? 656 00:43:14.319 --> 00:43:16.739 Bullet UI should decrease by one 657 00:43:16.740 --> 00:43:19.590 When Player does not hold the gun 658 00:43:19.590 --> 00:43:21.699 It can't shot, so leave it be 659 00:43:21.699 --> 00:43:24.849 When animation plays, right before that 660 00:43:24.849 --> 00:43:27.699 Let's add the logic to 661 00:43:27.700 --> 00:43:29.859 Remove the bullet here 662 00:43:29.860 --> 00:43:33.810 To remove bullet, we need one less BulletCount 663 00:43:33.810 --> 00:43:34.719 With the gunshoot 664 00:43:34.719 --> 00:43:38.579 The remaining bullets should decrease by one 665 00:43:38.580 --> 00:43:43.879 So we remove one UI from MainUI 666 00:43:43.879 --> 00:43:48.939 popBullet, and add to BulletCount 667 00:43:48.939 --> 00:43:53.260 Then it removes the last one, right? 668 00:43:55.819 --> 00:43:57.719 And then build 669 00:44:04.639 --> 00:44:10.140 If it succeeds, go to Editor and play again 670 00:44:10.141 --> 00:44:13.400 So get the gun, shoot, shoot 671 00:44:13.400 --> 00:44:16.899 And the UI gest reduced 672 00:44:19.221 --> 00:44:23.121 So that happened, but there could be a problem 673 00:44:23.121 --> 00:44:26.171 Player moves, get the gun, shoots 674 00:44:26.171 --> 00:44:28.380 And the UI is removed well 675 00:44:28.380 --> 00:44:30.530 So it is out of bullets 676 00:44:30.530 --> 00:44:32.330 Now there are no more bullets 677 00:44:32.330 --> 00:44:34.819 But somehow it can still shoot 678 00:44:34.819 --> 00:44:36.069 Which shouldn't happen 679 00:44:36.069 --> 00:44:39.580 So we need to add that it can't shoot if without bullets 680 00:44:40.681 --> 00:44:42.441 So at Visual Studio 681 00:44:43.380 --> 00:44:45.430 At our fire function 682 00:44:45.430 --> 00:44:48.380 At NetTPSCharacter.cpp, at 'fire' 683 00:44:48.381 --> 00:44:51.500 We need to add a code 684 00:44:51.501 --> 00:44:52.851 If without bullet 685 00:44:52.851 --> 00:44:56.001 Meaning, if Bulletcount is equal to or less than 0 686 00:44:56.001 --> 00:44:57.820 That means there is none 687 00:44:57.820 --> 00:45:01.020 Then this does not proceed 688 00:45:01.021 --> 00:45:03.321 Can't it just be equal to 0? 689 00:45:03.321 --> 00:45:05.800 That's right, it will be reduced here as well 690 00:45:05.800 --> 00:45:07.619 So if it is 0, it won't enter here anyways 691 00:45:07.620 --> 00:45:11.899 But then, somehow, with programming 692 00:45:11.899 --> 00:45:13.649 Somehow 693 00:45:13.649 --> 00:45:16.540 There could be a random bug for things like this 694 00:45:16.541 --> 00:45:21.720 So when this should be 0, it may overlap and ignore 695 00:45:21.720 --> 00:45:25.260 And proceed with something strange 696 00:45:25.260 --> 00:45:26.810 So just to be safe 697 00:45:26.810 --> 00:45:31.459 Let's just say less than or equal to 0 698 00:45:31.459 --> 00:45:34.940 So that was on creating the Bullet UI 699 00:45:35.627 --> 00:45:38.027 Reload 700 00:45:39.740 --> 00:45:42.979 So let's now work on the reload 701 00:45:42.979 --> 00:45:49.500 We built it well, and let's get the gun 702 00:45:49.501 --> 00:45:53.280 So after using all the bullets, it can't shoot anymore 703 00:45:53.280 --> 00:45:55.941 And since it can't proceed here 704 00:45:55.941 --> 00:45:58.861 We now need to work on the reload part 705 00:45:58.861 --> 00:46:03.060 To reload, let's add an input for that 706 00:46:03.060 --> 00:46:06.060 NetTPS, go to Input folder 707 00:46:06.060 --> 00:46:11.380 At action, choose TaskePistol, Ctrl D 708 00:46:11.380 --> 00:46:15.319 And add IA_Reload 709 00:46:17.021 --> 00:46:22.021 It uses bool value to determine whether pressed or not 710 00:46:22.021 --> 00:46:26.279 So I just simply made Reload like others 711 00:46:26.280 --> 00:46:30.319 To check if there is or is not an input 712 00:46:30.319 --> 00:46:33.369 And then the Reload value 713 00:46:33.369 --> 00:46:37.420 Let's set to assign it to a key 714 00:46:37.420 --> 00:46:39.870 Open IMC default 715 00:46:39.870 --> 00:46:41.430 Add a Mappings 716 00:46:41.488 --> 00:46:47.089 At the bottom we see IA Reload 717 00:46:47.089 --> 00:46:49.019 So add IA Reload 718 00:46:52.719 --> 00:46:54.769 Once IA Reload is added 719 00:46:54.769 --> 00:46:57.069 There is a keyboard here 720 00:46:57.069 --> 00:46:58.620 Click on that keyboard button 721 00:47:01.721 --> 00:47:03.521 And add 'r' for the key value 722 00:47:04.741 --> 00:47:06.421 The 'r' key 723 00:47:06.421 --> 00:47:09.140 Then we added that input 724 00:47:09.140 --> 00:47:12.340 Now close IMC default window 725 00:47:12.341 --> 00:47:17.180 At Visual Studio, let's declare to process this input 726 00:47:17.180 --> 00:47:20.439 Go to NetTPSCharacter.h 727 00:47:22.180 --> 00:47:25.780 And at the bottom, public 728 00:47:25.780 --> 00:47:28.880 I will say 'reload' here 729 00:47:30.540 --> 00:47:34.300 so for reload, at the top for input we have one for shoot 730 00:47:34.301 --> 00:47:37.500 Let's bring it down and use it 731 00:47:38.900 --> 00:47:39.619 Like so 732 00:47:41.859 --> 00:47:46.060 Let's just change the name to Reload 733 00:47:47.339 --> 00:47:50.939 So it becomes ReloadAction 734 00:47:50.939 --> 00:47:53.780 And to process this in a function 735 00:47:53.780 --> 00:47:57.930 Let's bring in the structure of our fire function 736 00:47:57.930 --> 00:48:00.660 And change its name to Reload 737 00:48:00.660 --> 00:48:04.200 Let's say ReloadPistol 738 00:48:07.460 --> 00:48:08.419 Done 739 00:48:10.180 --> 00:48:12.820 Now let's work on ReloadPistol 740 00:48:15.859 --> 00:48:17.980 For ReloadPistol, let's bring it down 741 00:48:21.339 --> 00:48:24.439 And paste on top of SetupPlayerInputComponent 742 00:48:24.439 --> 00:48:26.040 Let's move it over here 743 00:48:27.281 --> 00:48:29.441 Just to make it easier to work 744 00:48:29.441 --> 00:48:32.291 So at the function SetupPlayerInputComponent 745 00:48:32.291 --> 00:48:36.479 We need to bind ReloadPistol and ReloadAction 746 00:48:36.479 --> 00:48:39.829 So at the bottom of SetupPlayerInputComponent 747 00:48:39.829 --> 00:48:40.779 We have 'fire' 748 00:48:40.779 --> 00:48:41.900 At the bottom, Ctrl D 749 00:48:41.900 --> 00:48:44.150 So this time, it's not FireAction 750 00:48:44.150 --> 00:48:46.741 But ReloadAction added 751 00:48:46.741 --> 00:48:49.761 And not fire but ReloadPistol 752 00:48:50.660 --> 00:48:53.110 Let's add it like so 753 00:48:53.110 --> 00:48:55.500 So this part has been added 754 00:48:55.500 --> 00:48:56.600 That's it 755 00:48:56.600 --> 00:49:00.750 So we added that function for reload 756 00:49:00.750 --> 00:49:02.040 Though it is empty for now 757 00:49:02.041 --> 00:49:06.060 And we have bound the inputs 758 00:49:06.061 --> 00:49:10.640 So what does ReloadPistol process? 759 00:49:10.641 --> 00:49:16.140 Let's make it initialize Bullet UI and set the current bullet 760 00:49:16.140 --> 00:49:20.259 To our max bullet value 761 00:49:20.259 --> 00:49:21.609 For that 762 00:49:21.609 --> 00:49:23.059 Over here 763 00:49:23.059 --> 00:49:29.260 Let's say that here we have a few UI Widget left 764 00:49:29.261 --> 00:49:33.880 Let's say we have around 3 bullets here 765 00:49:33.881 --> 00:49:36.700 Then if we use add bullet here 766 00:49:36.700 --> 00:49:40.150 Meaning, we add 10 more bullets on top 767 00:49:40.150 --> 00:49:42.459 There could be 13 in total 768 00:49:42.460 --> 00:49:46.059 So before working on this 769 00:49:46.059 --> 00:49:48.259 We need to remove these 770 00:49:48.259 --> 00:49:51.119 And then set the 10 bullets again 771 00:49:51.120 --> 00:49:52.739 That's the clean way 772 00:49:52.740 --> 00:49:55.440 So all Bullet UI, however many is left 773 00:49:55.440 --> 00:49:58.199 For example, even if 3 bullets are left 774 00:49:58.199 --> 00:50:03.159 It removes all Widgets, and since the max is 10 775 00:50:03.160 --> 00:50:05.010 It sets 10 bullets again 776 00:50:05.010 --> 00:50:06.659 That's the clean way 777 00:50:06.659 --> 00:50:11.300 So let's add a function to remove all Bullet UI 778 00:50:11.301 --> 00:50:14.461 To our MainUI.h 779 00:50:15.740 --> 00:50:21.939 popup, below this pop bullet function 780 00:50:21.939 --> 00:50:28.461 Let's add a function to remove all Bullet UI 781 00:50:28.461 --> 00:50:33.121 void RemoveAllAmmo 782 00:50:35.241 --> 00:50:36.241 Let's do that 783 00:50:37.880 --> 00:50:41.839 And let's work on RemoveAllAmmo 784 00:50:49.180 --> 00:50:51.420 So let's add this implementation part 785 00:50:55.339 --> 00:50:56.999 So here 786 00:50:59.021 --> 00:51:02.021 We remove all children at BulletPanel 787 00:51:02.021 --> 00:51:08.680 So at BulletPanel we have ClearChildren 788 00:51:10.280 --> 00:51:11.480 See? 789 00:51:11.480 --> 00:51:15.660 This will remove all child widgets 790 00:51:15.661 --> 00:51:20.320 Here is says 'remove all child widget' 791 00:51:20.320 --> 00:51:22.270 So it removes everything at once 792 00:51:22.270 --> 00:51:24.339 So we can call this 793 00:51:24.340 --> 00:51:28.059 Or we could call every pop and remove it 794 00:51:28.059 --> 00:51:29.259 That's a way, but 795 00:51:29.259 --> 00:51:32.440 Let's rather use ClearChildren that does it at once 796 00:51:34.260 --> 00:51:35.460 And then 797 00:51:37.241 --> 00:51:40.681 At NetTPSCharacter, let's implement ReloadPistol 798 00:51:40.681 --> 00:51:42.981 Remove all widgets 799 00:51:42.981 --> 00:51:46.060 And we will be setting the structure again 800 00:51:46.060 --> 00:51:49.820 So let's work on this part where 801 00:51:51.300 --> 00:51:56.059 The user presses 'reload' to initialize bullet count 802 00:51:57.939 --> 00:52:02.480 And then for Bullet UI 803 00:52:04.339 --> 00:52:09.589 Remove all Bullet UI Widgets 804 00:52:09.589 --> 00:52:11.040 And then 805 00:52:12.180 --> 00:52:15.030 Set the Bullet UI back again 806 00:52:15.030 --> 00:52:16.580 That's the structure here 807 00:52:16.580 --> 00:52:18.380 But there needs a condition 808 00:52:18.380 --> 00:52:20.780 A condition of 809 00:52:20.780 --> 00:52:25.941 Only when Player holds the gun 810 00:52:27.780 --> 00:52:29.680 Are all these possible, right? 811 00:52:29.680 --> 00:52:31.340 If Player does not have a gun 812 00:52:35.699 --> 00:52:40.549 The content below won't be processed 813 00:52:40.549 --> 00:52:43.819 So this part, if 814 00:52:46.001 --> 00:52:50.041 If bHasPistol is False 815 00:52:50.041 --> 00:52:54.059 Then this part does not go through 816 00:52:56.300 --> 00:52:58.180 So return 817 00:53:00.781 --> 00:53:02.331 If this is False 818 00:53:02.331 --> 00:53:05.821 This doesn't work since Player has no gun 819 00:53:05.821 --> 00:53:08.559 And if True, since Player has the gun, reload is possible 820 00:53:10.061 --> 00:53:12.781 So let's initialize bullet count here 821 00:53:12.781 --> 00:53:17.679 BulletCount, initialize with maxBulletCount 822 00:53:21.100 --> 00:53:23.650 And remove all existing Bullet UI Widgets 823 00:53:23.650 --> 00:53:25.059 At MainUI 824 00:53:30.401 --> 00:53:33.381 We just made RemoveAllAmmo 825 00:53:34.941 --> 00:53:37.820 This will remove all UI first 826 00:53:40.819 --> 00:53:46.001 And for in I that re-sets the Bullet UI 827 00:53:46.001 --> 00:53:48.741 At 0, I repeats as much as BulletCount 828 00:53:51.020 --> 00:53:53.520 And at MainUI 829 00:53:55.380 --> 00:53:59.099 We do AddBullet as before 830 00:54:02.180 --> 00:54:05.479 So let's see how this builds 831 00:54:11.421 --> 00:54:13.971 So when user presses 'reload' 832 00:54:13.971 --> 00:54:17.751 Then this bound function ReloadPistol is called 833 00:54:17.751 --> 00:54:21.619 If Player has the gun, bullet is initialized 834 00:54:21.619 --> 00:54:24.169 UI is removed and set up again 835 00:54:24.169 --> 00:54:26.399 This part of the code works out 836 00:54:26.421 --> 00:54:27.821 And Blueprint 837 00:54:31.899 --> 00:54:36.619 At this folder, open BPThirdPerson 838 00:54:36.619 --> 00:54:42.459 Search for Reload and at Input we are to add ReloadAction 839 00:54:42.459 --> 00:54:47.200 Here we can add IA Reload that we made before 840 00:54:49.181 --> 00:54:50.181 Compile 841 00:54:51.319 --> 00:54:54.140 Let's run 842 00:54:54.141 --> 00:54:58.500 Press f, and shoot 843 00:54:58.500 --> 00:55:00.200 We shot everything 844 00:55:00.200 --> 00:55:04.259 And press 'r' to reload 845 00:55:04.259 --> 00:55:07.359 And we shoot again, and we still have a few left 846 00:55:07.359 --> 00:55:10.020 And press 'r' and now 847 00:55:10.020 --> 00:55:14.299 We have 10 bullets, the maximum number, reloaded 848 00:55:15.979 --> 00:55:19.820 And next, when reloading 849 00:55:22.180 --> 00:55:23.580 This works now 850 00:55:23.580 --> 00:55:24.880 The UI refills again 851 00:55:24.880 --> 00:55:27.180 And let's add an animation here 852 00:55:27.181 --> 00:55:30.620 So in our list of animations, we have 853 00:55:30.620 --> 00:55:33.699 One regarding reloading, so search for 854 00:55:33.699 --> 00:55:40.300 'Reload' and we get MM_PistolReload 855 00:55:40.300 --> 00:55:41.150 See? 856 00:55:41.150 --> 00:55:44.350 So right click on MM_PistolReload 857 00:55:44.350 --> 00:55:47.179 And make it into a Montage file 858 00:55:47.179 --> 00:55:51.339 Create AnimMontage 859 00:55:53.739 --> 00:55:55.189 Don't change the file name 860 00:55:55.189 --> 00:56:00.340 We have MM_PistolRealod AnimMontage file 861 00:56:00.340 --> 00:56:01.640 Here it is 862 00:56:01.640 --> 00:56:04.419 Let's save all to save everything 863 00:56:07.459 --> 00:56:11.060 And let's open this animation file 864 00:56:13.559 --> 00:56:15.020 So this is the animation 865 00:56:17.699 --> 00:56:21.340 Good, but here 866 00:56:22.860 --> 00:56:26.860 When the bullet is being reloaded 867 00:56:26.860 --> 00:56:31.179 I want the UI to fill it at this last moment 868 00:56:31.180 --> 00:56:35.079 So it can't fill up the bullets at the beginning 869 00:56:35.079 --> 00:56:38.179 Let's sync it to the animation so that 870 00:56:38.179 --> 00:56:40.820 When this actions is all done 871 00:56:40.820 --> 00:56:43.219 Around here 872 00:56:43.220 --> 00:56:47.020 The bullets should fill in, so here 873 00:56:47.020 --> 00:56:52.340 Let's wait until the bullets are reloaded 874 00:56:52.341 --> 00:56:55.460 And then let's make the UI fill up here 875 00:56:55.460 --> 00:56:58.619 So we should add a Notify event for this 876 00:56:59.981 --> 00:57:02.631 Here, let's right click 877 00:57:02.631 --> 00:57:04.141 On this Notify part 878 00:57:04.141 --> 00:57:06.441 Click on Add Notify 879 00:57:06.441 --> 00:57:08.359 And add New Notify 880 00:57:10.379 --> 00:57:13.740 Let's name it 881 00:57:15.681 --> 00:57:16.801 OnReloadFinish 882 00:57:18.861 --> 00:57:20.901 OnReloadFinish 883 00:57:22.400 --> 00:57:25.400 Here, this Notify Event of OnReloadFinish 884 00:57:25.400 --> 00:57:26.979 It's added here 885 00:57:26.979 --> 00:57:29.579 So now that we have this Notify Event 886 00:57:29.579 --> 00:57:30.719 Let's close this 887 00:57:33.501 --> 00:57:37.001 And at Montage, when the event is called 888 00:57:37.001 --> 00:57:39.801 When OnReloadFinish is called 889 00:57:39.801 --> 00:57:43.419 Let's make a logic to process that 890 00:57:43.420 --> 00:57:46.659 So at Visual Studio that controls the animation 891 00:57:46.659 --> 00:57:50.009 We have the class NetPlayerAnimInstance 892 00:57:50.009 --> 00:57:54.540 This is the calss that controls animation on Player 893 00:57:54.540 --> 00:57:59.259 Here, at the bottom, let's say public 894 00:57:59.260 --> 00:58:03.899 And add content regarding the reload 895 00:58:03.899 --> 00:58:10.060 Let's add Reload Montage Instance 896 00:58:10.060 --> 00:58:15.510 UPROPERTY EditDefaultOnly 897 00:58:15.510 --> 00:58:18.839 And Category, Anim 898 00:58:18.840 --> 00:58:21.899 Same as above, add Anim 899 00:58:21.899 --> 00:58:26.240 And calss UAminMontae 900 00:58:28.659 --> 00:58:34.240 And for reload, let's say Reload Montage 901 00:58:36.001 --> 00:58:39.441 And in order to play that reload animation 902 00:58:39.441 --> 00:58:42.591 Just as the shoting animation, we should be able to play reload 903 00:58:42.591 --> 00:58:43.939 For that, we need a function 904 00:58:43.939 --> 00:58:49.719 Let's make a function to play the reload animation 905 00:58:49.720 --> 00:58:52.179 void Play 906 00:58:52.179 --> 00:58:56.500 Reload animation, let's say that 907 00:58:58.100 --> 00:59:01.850 And at Montage, at our reload animation 908 00:59:01.850 --> 00:59:03.659 We added Notify Event 909 00:59:03.659 --> 00:59:06.709 The function to get that event 910 00:59:06.709 --> 00:59:08.340 Let's add it here 911 00:59:08.340 --> 00:59:13.420 Reload Animation Notify Event 912 00:59:13.420 --> 00:59:16.480 And the function to process it, UFUNCTION 913 00:59:20.401 --> 00:59:23.401 We need UFUNCTION here 914 00:59:23.401 --> 00:59:29.300 In order to sync Unreal Editor and C++ to process further 915 00:59:29.300 --> 00:59:35.020 UFUNCTION void AnimNotify, add prefix for the name 916 00:59:35.020 --> 00:59:39.340 And underbar, until here is what processes Notify Event 917 00:59:39.340 --> 00:59:43.100 Following that, add the name of the Notify Event 918 00:59:43.100 --> 00:59:48.260 OnReloadFinish, like so 919 00:59:48.260 --> 00:59:54.340 Then since we have OnReloadFinish for the Notify Event 920 00:59:54.340 --> 00:59:57.740 The function to process it is AnimNotify_ 921 00:59:57.740 --> 00:59:59.939 And this function is to be called 922 00:59:59.939 --> 01:00:03.139 Here, when OnReloadFinish Notify occurs 923 01:00:03.139 --> 01:00:05.860 This function is synced to run 924 01:00:05.860 --> 01:00:08.500 So let's finish the two functions 925 01:00:08.500 --> 01:00:13.179 First, add PlayReloadAnimation 926 01:00:13.179 --> 01:00:16.659 And then let's add again AnimNotify ReloadFinish 927 01:00:16.659 --> 01:00:23.300 We added two classes at NetPlayerANimInstance.cpp 928 01:00:23.300 --> 01:00:29.460 First, PlayReloadAnimation function needs the gun 929 01:00:31.900 --> 01:00:34.739 Only when Player has it, right? 930 01:00:36.739 --> 01:00:39.599 And when with reload montage 931 01:00:42.139 --> 01:00:43.389 That's when to process it 932 01:00:43.389 --> 01:00:46.439 So if bHasPistol 933 01:00:46.439 --> 01:00:47.500 So Player has the gun 934 01:00:47.500 --> 01:00:53.100 And with and reload montage 935 01:00:53.100 --> 01:00:57.619 At MontagePlay, reload montage 936 01:00:59.780 --> 01:01:02.660 Its default is 1, so let's add that 937 01:01:05.661 --> 01:01:08.861 Then reload montage is now play 938 01:01:08.861 --> 01:01:12.511 So here, when it is now OnReloadFinish 939 01:01:12.511 --> 01:01:14.020 Then what do we want? 940 01:01:15.979 --> 01:01:16.959 We need to 941 01:01:19.419 --> 01:01:25.020 Update the Plyaer UI 942 01:01:25.060 --> 01:01:29.661 Here, at reloadPIstol, notice this part 943 01:01:29.661 --> 01:01:31.411 This is what gets updated 944 01:01:31.411 --> 01:01:33.320 So we need to call that in 945 01:01:33.320 --> 01:01:35.470 But when the animation is playing 946 01:01:35.470 --> 01:01:37.739 This is only processed with the input 947 01:01:37.740 --> 01:01:41.479 Which is good to do it then, but 948 01:01:41.479 --> 01:01:43.179 What we want is 949 01:01:43.179 --> 01:01:47.160 Play the animation here, and when it does that 950 01:01:47.161 --> 01:01:49.611 At a certain point, after some time passes 951 01:01:49.611 --> 01:01:51.361 When AnimNotifyEvent occurs 952 01:01:51.361 --> 01:01:53.950 That's when we want to do this 953 01:01:53.950 --> 01:01:56.350 So since the poitn of time is a little different 954 01:01:56.350 --> 01:01:59.189 We need to add another function 955 01:01:59.189 --> 01:02:01.259 That can process this part 956 01:02:02.739 --> 01:02:07.089 So let's move to the header file of NetTPSCharacter 957 01:02:07.089 --> 01:02:09.060 Here 958 01:02:09.060 --> 01:02:15.459 Let's create a function to initialize Bullet UI 959 01:02:15.459 --> 01:02:20.659 void initAmmoUI 960 01:02:21.060 --> 01:02:23.439 Create one InitAmmoUI 961 01:02:27.580 --> 01:02:33.979 And let's add the code to initialize this UI 962 01:02:33.979 --> 01:02:38.379 So at reloadPistol, add it up until here 963 01:02:38.379 --> 01:02:40.619 So that this code to call this is included 964 01:02:42.969 --> 01:02:45.019 And then here 965 01:02:45.019 --> 01:02:48.899 All initialization part should go down here 966 01:02:48.899 --> 01:02:54.339 So that this part moves to down here 967 01:02:55.921 --> 01:02:59.821 Then, at initAmmoUI, it initializes the bullet 968 01:02:59.821 --> 01:03:01.181 Initializes Bullet UI 969 01:03:01.181 --> 01:03:03.231 Here, the bullet count is initialized 970 01:03:03.231 --> 01:03:04.780 And the setup part goes here 971 01:03:06.540 --> 01:03:07.239 Right? 972 01:03:09.179 --> 01:03:11.729 And at reload, the animation 973 01:03:11.729 --> 01:03:16.860 It should play the reload animation 974 01:03:16.861 --> 01:03:20.740 Then when is InitAmmoUI called? 975 01:03:20.740 --> 01:03:22.390 When the animation plays 976 01:03:22.390 --> 01:03:24.540 During that reload animation 977 01:03:24.540 --> 01:03:26.340 When Notify Event enters 978 01:03:26.340 --> 01:03:28.990 Then what do we do? 979 01:03:28.990 --> 01:03:32.219 This processes to update Bullet UI 980 01:03:32.219 --> 01:03:35.400 Right, so here at Player 981 01:03:38.260 --> 01:03:42.081 InitAmmoUI is now 982 01:03:42.081 --> 01:03:44.301 Being called in here 983 01:03:47.860 --> 01:03:49.660 That's when the bullets are set up 984 01:03:49.660 --> 01:03:52.419 So that this code updates the UI 985 01:03:52.420 --> 01:03:54.760 So let's add the code that 986 01:03:54.760 --> 01:03:58.499 Plays the animation right here 987 01:03:58.499 --> 01:04:01.249 At reloadPistol, with the user input 988 01:04:01.249 --> 01:04:03.020 It only plays the animation 989 01:04:03.020 --> 01:04:06.540 And from the animation it gets the event to update UI 990 01:04:07.820 --> 01:04:10.820 Let's add 'auto anim' here 991 01:04:10.820 --> 01:04:14.870 Add Cast UNextPlayerAnimInstance 992 01:04:14.870 --> 01:04:21.270 At GetMesh, bring in GetAnimInstance class 993 01:04:21.270 --> 01:04:23.039 And we've done the casting 994 01:04:23.040 --> 01:04:25.139 Next, at anim 995 01:04:25.139 --> 01:04:28.939 Add PlayReloadAnimation 996 01:04:28.939 --> 01:04:30.789 Then it plays ReloadAnimation 997 01:04:30.789 --> 01:04:32.339 So build 998 01:04:34.699 --> 01:04:36.999 And let's check 999 01:04:39.281 --> 01:04:42.201 At animation, we have ABP_Manny 1000 01:04:42.201 --> 01:04:45.301 At ABP_Manny, which is in NetTPS animation folder 1001 01:04:45.301 --> 01:04:47.360 Double click on ABP_Manny to open 1002 01:04:50.880 --> 01:04:52.618 Done, and then 1003 01:04:53.798 --> 01:04:55.458 At Details 1004 01:04:57.540 --> 01:04:59.640 Search for 'reload' 1005 01:04:59.640 --> 01:05:01.560 And we are to add reload Montage 1006 01:05:03.821 --> 01:05:07.021 NetTPS, here at the header file of Player animation 1007 01:05:07.021 --> 01:05:10.300 We implemented to get this reload Montage 1008 01:05:10.300 --> 01:05:14.539 This is the exposed result, so 1009 01:05:16.459 --> 01:05:20.699 Let's choose MM_Pistol_Reload_Montage here 1010 01:05:20.699 --> 01:05:21.999 Then it adds like so 1011 01:05:22.787 --> 01:05:24.007 Now, compile 1012 01:05:26.540 --> 01:05:29.260 And let's play here 1013 01:05:30.381 --> 01:05:31.741 Play 1014 01:05:32.561 --> 01:05:35.281 So we have the gun, bang bang 1015 01:05:35.281 --> 01:05:37.531 And let's reload by pressing r 1016 01:05:37.531 --> 01:05:39.459 Then we get the animation 1017 01:05:39.459 --> 01:05:41.079 Ta-da 1018 01:05:42.201 --> 01:05:44.341 And ta-da again 1019 01:05:44.379 --> 01:05:46.779 So the animation plays 1020 01:05:46.779 --> 01:05:50.360 And when it puts it in, then the UI is updated 1021 01:05:52.341 --> 01:05:53.341 See? 1022 01:05:54.000 --> 01:05:55.750 But the problem is, let's shoot and press reload 1023 01:05:55.750 --> 01:05:58.620 So let's shoot and press reload 1024 01:05:58.620 --> 01:06:00.481 And then here, press reload again 1025 01:06:00.481 --> 01:06:03.011 Then the reload animation repeats itself 1026 01:06:05.139 --> 01:06:06.289 See? 1027 01:06:06.289 --> 01:06:10.060 This is what we need to work with 1028 01:06:10.061 --> 01:06:12.800 So that it cannot reload again when it is reloading 1029 01:06:12.800 --> 01:06:17.020 When it is reloading, it shouldn't reload again 1030 01:06:17.020 --> 01:06:20.470 So we need a variable that remembers 1031 01:06:20.470 --> 01:06:21.620 If it is reloading right now 1032 01:06:22.620 --> 01:06:26.120 At NetTPSCharacter, at the very bottom 1033 01:06:28.139 --> 01:06:30.080 Let's add a variable 1034 01:06:31.699 --> 01:06:33.799 That remembers if it's reloading 1035 01:06:33.799 --> 01:06:37.459 So bool, isReloading 1036 01:06:37.460 --> 01:06:40.360 At first it is False 1037 01:06:40.360 --> 01:06:43.000 When isReloading 1038 01:06:43.000 --> 01:06:45.940 Let's make it impossible to reload again 1039 01:06:47.361 --> 01:06:49.821 So at NetTPSCharacter 1040 01:06:51.041 --> 01:06:52.701 ReloadPistol 1041 01:06:52.701 --> 01:06:57.340 If Player does not have the gun, what else do we need? 1042 01:06:57.341 --> 01:07:01.541 And if Player is not reloading 1043 01:07:01.541 --> 01:07:06.659 Or, in order for this to process nothing, if it is reloading 1044 01:07:06.660 --> 01:07:09.559 It should not process it 1045 01:07:09.559 --> 01:07:15.780 So let's add 'or' so that it doesn't process if isReloading 1046 01:07:15.780 --> 01:07:16.520 That's how it works 1047 01:07:22.241 --> 01:07:26.381 So how do we set that it is reloading? 1048 01:07:27.700 --> 01:07:31.060 So, when reload is successfull, when isReloading is False 1049 01:07:31.061 --> 01:07:34.640 Then this will be running, but 1050 01:07:34.640 --> 01:07:38.590 If it is reloading, playing the animation 1051 01:07:38.590 --> 01:07:41.340 Then it is True 1052 01:07:41.340 --> 01:07:42.660 So when does reloading end? 1053 01:07:44.201 --> 01:07:45.381 When InitAmmo 1054 01:07:46.761 --> 01:07:51.181 Is called and when the animation ends 1055 01:07:51.181 --> 01:07:56.419 Then if it is IsReloading as False 1056 01:07:56.419 --> 01:08:01.979 Then it is processed as reloading has been complete 1057 01:08:01.979 --> 01:08:07.120 If this becomes False then we can reload again 1058 01:08:10.699 --> 01:08:11.999 It's not only this 1059 01:08:11.999 --> 01:08:15.659 We can shoot like bang, bang 1060 01:08:15.660 --> 01:08:17.459 And we reload 1061 01:08:17.459 --> 01:08:21.340 And we cannot shoot during the reload animation 1062 01:08:21.341 --> 01:08:23.780 This will halt the reload 1063 01:08:23.780 --> 01:08:25.680 So only when the reload animation ends 1064 01:08:25.680 --> 01:08:27.860 Can Player shoot, let's make it so 1065 01:08:27.860 --> 01:08:31.080 So it's not just about here, we need to go to 'fire' 1066 01:08:31.081 --> 01:08:37.020 We need to make it do nothing when reloading at 'fire' too 1067 01:08:37.020 --> 01:08:40.220 So don't process if IsReloading 1068 01:08:41.820 --> 01:08:48.100 And when Pleyer lets go of the gun, it can't be reloading 1069 01:08:48.101 --> 01:08:50.960 So even when it drops the gun 1070 01:08:50.960 --> 01:08:53.410 When isReloading, this does not process 1071 01:08:53.410 --> 01:08:55.620 Let's add that part 1072 01:08:55.620 --> 01:08:56.359 So here 1073 01:08:58.219 --> 01:08:59.280 Even at Release 1074 01:09:03.060 --> 01:09:06.260 Let's make it not process 1075 01:09:09.480 --> 01:09:14.100 So when reloading, all these should not be possible 1076 01:09:14.100 --> 01:09:16.300 At releasePistol, when reloading 1077 01:09:16.300 --> 01:09:18.979 This should not occur 1078 01:09:18.979 --> 01:09:20.779 So when reload animation is playing 1079 01:09:20.779 --> 01:09:23.580 When Player drops the gun, it halts the animation 1080 01:09:23.580 --> 01:09:25.980 So we should only allow for the drop 1081 01:09:25.980 --> 01:09:28.159 Only after the animation is complete 1082 01:09:29.381 --> 01:09:32.401 So let's finish the build here and play 1083 01:09:32.401 --> 01:09:36.820 Press F, shot, and press R 1084 01:09:36.821 --> 01:09:38.440 Then you can't shot 1085 01:09:38.440 --> 01:09:40.640 Press R, and keep pressing R 1086 01:09:40.640 --> 01:09:42.780 But it doesn't overlap 1087 01:09:42.780 --> 01:09:47.339 It only reloads again when this is over 1088 01:09:48.379 --> 01:09:49.620 That's when we can shoot as well 1089 01:09:51.580 --> 01:09:53.420 So that concludes 1090 01:09:53.421 --> 01:09:56.580 The reload part 1091 01:09:56.580 --> 01:09:58.760 Let's summarize what we've learned today 1092 01:10:00.410 --> 01:10:03.602 Crosshair and Bullet UI Crosshair How to use Unreal Motion Graphics (UMG) to display UI How to create a MainUI C++ class of UserWidget type 1093 01:10:03.602 --> 01:10:05.382 Building Bullet UI UI is only visible when Player holds the gun 1094 01:10:05.382 --> 01:10:06.866 At UMG widget, use Univorm Grid Panel to add and remove Bullet UI Use MainUI C++ Class to control data of Widget Blueprint 1095 01:10:06.866 --> 01:10:09.481 Reload Reload Implementing input action creation and mapping for reload 1096 01:10:09.481 --> 01:10:10.817 To implement reloading, first remove all remaining bullet widgets and add new widgets 1097 01:10:10.818 --> 01:10:13.577 Implement logic to process animation when reloading using animation montage Use Notify event to update bullet UI according to animation timing 1098 01:10:13.577 --> 01:10:14.577 The End