WEBVTT

00:06.910 --> 00:08.260
Welcome back.

00:08.440 --> 00:12.130
Now we're adding our widget to the viewport from the HUD.

00:12.130 --> 00:16.810
But we need to give this widget a widget controller.

00:16.990 --> 00:24.160
And as we've seen our widget controller which we called or a widget controller has four key variables

00:24.160 --> 00:29.530
player controller, player, state ability, system component, and attribute set.

00:29.530 --> 00:35.950
Which means if we're going to create a widget controller, we should be setting these variables.

00:35.950 --> 00:40.150
So I'd like an easy way to set these four key variables.

00:40.150 --> 00:45.130
I'd like to create a struct that has these four key variables in it.

00:45.130 --> 00:50.770
And that will make it easy to initialize any given widget controller.

00:50.770 --> 00:57.070
So I'm going to make that struct here in the widget controller class, or a widget controller right

00:57.070 --> 01:01.210
here up at the top just under our forward declarations.

01:01.330 --> 01:09.700
So I'll make a new struct and I'm going to call this F widget controller params f widget controller

01:09.700 --> 01:12.490
params can be a u struct.

01:12.490 --> 01:14.950
So we'll give it a use struct macro.

01:15.490 --> 01:18.340
And I'm going to make it blueprint type just in case.

01:18.340 --> 01:22.210
We need to create one of these and use this type in blueprint.

01:22.210 --> 01:31.660
And I'll give it a generated body as u structs need that, and I'll go ahead and make a default constructor

01:31.660 --> 01:35.680
for it, an empty one with an empty body.

01:35.680 --> 01:41.890
And I'll make one that can receive the four key variables these four here.

01:41.890 --> 01:47.710
So I'm going to make another constructor that takes these parameters.

01:47.710 --> 01:52.390
So I'm going to make the constructor receive an A player controller pointer.

01:52.390 --> 01:54.250
I'm just going to call this PC.

01:54.520 --> 02:02.800
I know that's a very non-descriptive name for a parameter, but for these four key variables I'm going

02:02.800 --> 02:04.210
to use abbreviations.

02:04.210 --> 02:10.030
And whenever I use those abbreviations, you know that I'm talking about these key variables.

02:10.030 --> 02:15.220
So after player controller I'm going to add an a player state input.

02:15.460 --> 02:16.300
That's a pointer.

02:16.300 --> 02:18.820
We're going to call this PS for player state.

02:18.820 --> 02:27.010
And we're also going to have a U ability system component called ask for ability system component.

02:27.010 --> 02:28.870
And a U attribute set.

02:28.870 --> 02:31.060
Looks like we need a forward declaration.

02:31.060 --> 02:32.920
I'll add that as well here.

02:32.920 --> 02:38.200
And this is going to be called a S for attribute set.

02:38.380 --> 02:42.610
And I'm going to go ahead and define the constructor right here.

02:42.610 --> 02:47.110
So I'm going to use an initializer list that involves a colon.

02:47.110 --> 02:54.130
And between the colon and the curly brackets we initialize the variables right here.

02:54.130 --> 02:55.960
Well this struct doesn't have any.

02:55.960 --> 02:58.930
So I'm going to add a few pointers here.

02:58.930 --> 03:00.850
I'm going to use t object pointer.

03:00.850 --> 03:03.310
And the first one will be the player controller.

03:03.310 --> 03:05.260
That's an A player controller.

03:05.560 --> 03:07.330
We'll call it player controller.

03:07.330 --> 03:08.530
We'll keep things simple.

03:08.530 --> 03:12.190
And this will be initialized to a null pointer.

03:13.420 --> 03:20.260
We tend to get compiler warnings when creating structs when they're member variables are not initialized.

03:20.260 --> 03:23.230
So I'm going to initialize it to null pointer.

03:23.230 --> 03:25.660
And this gets a u property.

03:27.010 --> 03:31.360
And I'm going to make it edit anywhere and blueprint rewrite.

03:31.360 --> 03:37.540
We'll give full blueprint access for all of these variables.

03:37.540 --> 03:40.090
So that's going to be the player controller.

03:40.090 --> 03:41.530
We're going to need the player state.

03:41.530 --> 03:45.550
So we'll make a t object pointer a player state.

03:46.990 --> 03:49.510
This variable will be player state.

03:49.630 --> 03:55.540
It'll be initialized to null pointer and gets the same u property access.

03:55.780 --> 03:59.050
And next we have ability system component.

03:59.050 --> 04:07.510
That will be a t object pointer u ability system component called ability system component initialized

04:07.510 --> 04:11.710
to null and given the u property.

04:11.710 --> 04:19.330
And finally our last t object pointer of type u attribute set called attribute set.

04:20.430 --> 04:24.540
Initialized to null with our U property.

04:24.810 --> 04:28.170
And now in our constructor we can initialize these.

04:28.170 --> 04:37.380
We can say player controller and with parentheses we can initialize it with our PC input parameter PC.

04:37.800 --> 04:39.600
And these are going to run off the screen.

04:39.600 --> 04:44.490
So I'm going to go ahead and starting at the colon start these on the next line here.

04:44.490 --> 04:46.500
And this will be a comma separated list.

04:46.500 --> 04:49.890
This is known as the member initializer list.

04:49.890 --> 04:57.750
We're going to initialize player state with PS ability system component with ASC and attribute set with

04:57.750 --> 04:58.680
a s.

04:58.920 --> 05:06.150
And I get red squiggles because it looks like I allowed autocomplete to put aura attributes set here.

05:06.150 --> 05:13.710
I actually just want u attribute set, so I don't need to forward declare u or attribute set either.

05:13.860 --> 05:18.990
It's just going to be a u attribute set here in the or widget controller class.

05:18.990 --> 05:25.380
So now we have a struct that can receive these four key variables when we create one.

05:25.680 --> 05:30.360
And that's going to make it easy to initialize a widget controller.

05:30.600 --> 05:37.740
And in order to do that I'd like to have a function here in or a widget controller that can initialize

05:37.740 --> 05:39.270
those values for us.

05:39.270 --> 05:43.470
So I'd like a public section and a function for that.

05:43.470 --> 05:48.900
Now I'm just going to call it set widget controller params.

05:48.900 --> 05:54.060
And it's going to take a const f widget controller params.

05:54.180 --> 05:59.370
We'll pass in a const reference and I'll call this w c params.

05:59.370 --> 06:06.780
For widget controller params, I'll generate the definition and all that's going to do is set those

06:06.780 --> 06:08.070
key variables.

06:08.070 --> 06:17.100
We'll set player controller equal to and we have our w c param struct w c params dot player controller.

06:17.100 --> 06:20.970
We also have player state.

06:20.970 --> 06:25.980
We'll set that to w c params dot player state.

06:25.980 --> 06:35.130
We have ability system component set that to w c params dot ability, system component and finally attribute

06:35.130 --> 06:40.770
set will be set to w c params dot attribute set.

06:41.130 --> 06:48.720
So now we can simply call this function and pass in the structure f widget controller params and the

06:48.720 --> 06:52.260
widget controller will set its member variables.

06:52.260 --> 06:58.800
And I'll go ahead and make this a u function with blueprint callable so we can set it if we need to

06:58.800 --> 06:59.760
from blueprint.

06:59.970 --> 07:04.920
And now we have a way to set those variables okay.

07:04.920 --> 07:09.660
So now our widget controller has a way to set those variables.

07:09.660 --> 07:14.490
We're going to want to actually create an object of this widget controller.

07:14.490 --> 07:19.050
But I'd like to use a widget controller as a sort of base class.

07:19.050 --> 07:22.980
So all of our widget controllers will inherit these properties.

07:22.980 --> 07:28.350
And for our overlay I'd like to create a specific overlay widget controller.

07:28.770 --> 07:32.520
So I'm going to make a child class based on aura widget controller.

07:32.520 --> 07:38.010
So I'm going to go ahead and compile and launch the editor so I can make that child class.

07:38.460 --> 07:43.470
So opening all the assets that I had open looks like I still have AVP aura.

07:43.470 --> 07:44.880
I can close that.

07:44.880 --> 07:48.750
I can close Aura Game mode and Aura HUD.

07:48.750 --> 07:53.040
And I'm going to make the new C plus plus class that I want.

07:53.040 --> 07:56.190
So C plus plus classes, Aura Public.

07:56.190 --> 08:00.360
And here in UI we have the widget controller.

08:00.360 --> 08:03.750
I'm going to make a widget controller based on Aura widget controller.

08:03.750 --> 08:06.840
So I'm going to right click create a C plus plus class.

08:06.840 --> 08:10.200
And I can let this live in the widget controller folder.

08:10.200 --> 08:14.280
And this is going to be called Overlay Widget Controller.

08:14.280 --> 08:18.210
So we'll go ahead and create this class and close the editor.

08:18.210 --> 08:24.030
And now that I have an overlay widget controller, this is the one I want to create.

08:24.030 --> 08:28.770
So here in the UI folder we have widget controller.

08:28.770 --> 08:30.540
There's aura widget controller.

08:30.540 --> 08:32.310
That'll be our sort of base class.

08:32.310 --> 08:34.830
And we have overlay widget controller.

08:34.890 --> 08:37.440
And that's the one I want to construct.

08:37.440 --> 08:40.500
Now I'm going to construct this in the HUD class.

08:40.500 --> 08:47.730
I think the HUD is a good class to create both the overlay widget and the widget controller itself.

08:47.730 --> 08:52.590
So I'm going to make a function to create the widget controller.

08:52.590 --> 08:58.320
Now I'd like this function to create the widget controller if it hasn't been created yet.

08:58.530 --> 09:01.650
And if it has, just return that widget controller.

09:01.650 --> 09:06.180
In other words, we'll only ever have one overlay widget controller.

09:06.300 --> 09:12.930
It's kind of treated like a singleton in a sense that will only be able to get it through a getter that

09:12.930 --> 09:15.150
will create it if it doesn't exist yet.

09:15.390 --> 09:18.960
So I'm going to make that get'er it's going to be public and it's.

09:19.110 --> 09:23.820
Going to return a U overlay widget controller.

09:23.820 --> 09:29.670
That's the class we just created, and we're going to add a forward declaration for that.

09:29.670 --> 09:36.270
And this function will be called get Overlay Widget Controller.

09:36.420 --> 09:44.370
And it can take a const reference to some f widget controller params.

09:44.790 --> 09:46.890
So that'll be a const reference.

09:46.890 --> 09:51.360
And we're going to call it wc params.

09:51.360 --> 09:56.100
And we can even forward declare f widget controller params.

09:56.100 --> 10:00.450
So up here with our forward declarations I'm going to say struct.

10:02.270 --> 10:07.070
F widget controller params and let's generate this get'er.

10:07.750 --> 10:13.480
And the Get'er is going to check to see if one of these has already been created.

10:13.480 --> 10:16.660
So if one has been created, we should store it in a pointer.

10:16.660 --> 10:22.450
So or a HUD is also going to get a pointer to store that overlay widget controller.

10:22.540 --> 10:28.180
So here in the private section we're going to have a you overlay widget controller.

10:28.360 --> 10:29.500
That's a pointer.

10:29.500 --> 10:31.660
We'll make it a t object pointer.

10:35.100 --> 10:38.880
And we'll call this overlay widget controller.

10:39.510 --> 10:43.620
And for now we'll give it a U property with no specifiers.

10:43.620 --> 10:49.740
And here in our HUD we're going to check to see if it's a null pointer or not.

10:49.740 --> 10:54.420
So we'll say if overlay widget controller.

10:56.140 --> 10:57.730
Is a null pointer.

10:57.910 --> 11:00.820
If it is a null pointer, we'll create one.

11:00.820 --> 11:07.240
And if it's not a null pointer, well then we'll just return the non null widget controller.

11:07.240 --> 11:10.810
So we'll return right here overlay widget controller.

11:10.990 --> 11:13.240
But if it's null we need to create one first.

11:13.240 --> 11:14.620
So we'll create one.

11:14.620 --> 11:20.380
We'll say overlay widget controller equals and we'll use new object.

11:20.380 --> 11:23.680
So new object is how we can create a new object.

11:23.680 --> 11:26.590
We're going to create a you overlay widget controller.

11:27.190 --> 11:31.720
Notice that writer just included that header for us.

11:31.720 --> 11:37.150
And for new object we need to pass in the outer which is going to be the HUD itself.

11:37.270 --> 11:39.460
And we also need the you class.

11:39.460 --> 11:42.670
So our HUD needs to have a new class.

11:42.670 --> 11:49.300
In other words, we should make a subclass of for the overlay widget controller class itself.

11:49.300 --> 11:55.570
So just like we have the overlay widget class, we need an overlay widget controller class.

11:55.570 --> 12:01.450
That'll be a subclass of you Overlay widget controller.

12:01.450 --> 12:06.010
And this will be overlay Widget controller class.

12:06.400 --> 12:07.810
And this gets a new property.

12:07.810 --> 12:11.200
But we also have to be able to set this from the blueprint.

12:11.200 --> 12:13.210
So we'll make it edit anywhere.

12:13.210 --> 12:17.860
And back in the cpp file we'll pass that class into new object.

12:17.860 --> 12:21.460
So overlay widget controller class.

12:21.880 --> 12:25.240
So here we're setting our member variable overlay widget controller.

12:25.240 --> 12:27.160
We've just created a new one.

12:27.160 --> 12:30.970
And we should set its widget controller params.

12:30.970 --> 12:34.780
So this get'er takes WC params.

12:34.780 --> 12:37.810
So we can take our overlay widget controller.

12:39.910 --> 12:48.970
And call that public function that we created called set widget controller params and pass in WC params.

12:50.920 --> 12:53.830
And that way those key variables will be set.

12:53.830 --> 12:59.170
And once we've created one of these we can return overlay widget controller.

12:59.170 --> 13:06.100
So now we have this Get'er that will construct it for the first time if it hasn't been constructed yet,

13:06.100 --> 13:12.280
but if it already has, it won't be null and we'll just return it without constructing anything.

13:12.280 --> 13:19.090
So in order to get it, we have to pass in those WC params for it to have its key variables set.

13:19.360 --> 13:24.340
So now that we have that get'er, we now need to construct our widget controller.

13:24.340 --> 13:32.290
But we see that in order to construct it we need widget controller params and to initialize widget controller

13:32.290 --> 13:38.200
params, we need those four key variables which we don't really have access to in begin play.

13:38.200 --> 13:38.920
Here.

13:38.920 --> 13:44.200
So essentially we need to do this somewhere where we have access to those four key variables.

13:44.200 --> 13:50.800
So what I like is for the HUD to have a function, we can call and pass in those four key variables.

13:50.800 --> 13:55.810
That way we can create that widget controller and assign it to our widget.

13:55.810 --> 14:02.110
So rather than doing all this and begin play, I'd rather do it in a function that can take those key

14:02.110 --> 14:02.860
variables.

14:02.860 --> 14:07.330
So we're going to make a function here in our HUD.

14:07.360 --> 14:08.800
It's going to be a void function.

14:08.800 --> 14:11.170
We'll call it init overlay.

14:11.680 --> 14:15.820
And it's going to take the four key variables in a player controller.

14:15.820 --> 14:19.390
We'll call it PC and a player state.

14:20.170 --> 14:21.190
We'll call it PS.

14:21.190 --> 14:25.540
These are pointers a new ability system component.

14:26.170 --> 14:33.010
I'll add the forward declaration and call this as C and a U attribute set.

14:33.010 --> 14:37.420
We'll add a forward declaration and we'll call this as.

14:37.960 --> 14:40.840
And we'll make the definition for init overlay.

14:40.840 --> 14:48.670
And init overlay is going to construct the widget controller, construct the widget, set the widgets

14:48.670 --> 14:50.620
widget controller and add it to the viewport.

14:50.620 --> 14:54.250
We'll take all those things and tie them all together here.

14:54.250 --> 14:57.160
So we're not going to do it in begin play anymore.

14:57.310 --> 14:59.890
I'm going to go ahead and just remove begin play.

14:59.890 --> 15:05.320
But these two lines, we can go ahead and cut and paste them into init overlay first.

15:05.320 --> 15:08.920
And then we're done with begin play I'm going to delete begin play.

15:08.950 --> 15:12.700
I'm going to delete it from our HUD as well.

15:13.000 --> 15:19.180
And here in init overlay is where we're going to actually do everything.

15:19.360 --> 15:24.160
Now first of all init overlay needs to create two things.

15:24.160 --> 15:27.580
Now we need to create a widget and a widget controller.

15:27.580 --> 15:30.970
So what I'd like to do is perform a check.

15:30.970 --> 15:38.200
But if that check fails and we crash the engine, I'd like to provide a more descriptive crash message.

15:38.200 --> 15:40.600
So for that I'm going to use check f.

15:40.600 --> 15:50.890
Check F will check a condition and then print a formatted string to the crash log if the check fails.

15:50.890 --> 15:54.430
So I'm going to check first of all overlay widget class.

15:54.430 --> 15:55.990
We need that to be set.

15:55.990 --> 16:00.460
And if we fail then we'll use the following message.

16:00.460 --> 16:06.310
We'll say overlay widget class uninitialized.

16:06.820 --> 16:15.970
Please fill out BP or HUD and we'll do the same thing for the widget controller as well.

16:15.970 --> 16:20.920
So we'll say check F overlay widget controller class.

16:20.920 --> 16:33.670
And we'll say for the text overlay widget controller class uninitialized please fill out BP or HUD.

16:34.750 --> 16:37.720
So that way we definitely won't forget.

16:37.720 --> 16:40.450
So first we need to create the widget.

16:40.450 --> 16:42.010
We'll call it widget.

16:42.010 --> 16:45.970
And we're going to want to create the widget controller as well.

16:45.970 --> 16:49.780
So I'm going to wait to add this widget to the viewport till the very end.

16:49.780 --> 16:55.000
And I'm going to cast Widget to Aura User widget.

16:55.000 --> 16:57.430
That way we can set its widget controller.

16:57.430 --> 17:00.700
So that way I can set my overlay widget.

17:00.700 --> 17:04.810
Remember we have this overlay widget which is an aura user widget.

17:04.810 --> 17:12.700
So I'm going to say overlay widget equals we're going to cast to you aura user widget.

17:12.700 --> 17:14.440
And we're casting widget.

17:15.160 --> 17:22.090
Now we have access to overlay widgets or a user widget stuff like set widget controller and so on.

17:22.090 --> 17:25.120
But we have to create that widget controller first.

17:25.120 --> 17:27.790
So next we create the widget controller.

17:27.790 --> 17:32.950
And I'm going to make a f widget controller params struct.

17:33.220 --> 17:36.010
I'm going to call it widget controller params.

17:36.010 --> 17:38.680
And remember this has a constructor.

17:39.180 --> 17:41.550
That takes the four key variables.

17:41.550 --> 17:45.540
We'll just briefly go back to our widget controller to remind ourselves.

17:45.540 --> 17:47.730
We'll scroll up and see that constructor.

17:47.730 --> 17:51.180
It takes player controller, player state AC.

17:51.180 --> 17:56.040
And as let's initialize the widget controller params.

17:56.040 --> 18:04.350
Because init overlay takes those key variables, we can initialize it with pc, PS, AC and as and.

18:04.350 --> 18:06.270
Now this struct contains those.

18:06.270 --> 18:09.270
And really we could make this a const struct.

18:09.270 --> 18:11.220
There's no need to make it mutable.

18:11.430 --> 18:15.930
And now that we have those params, we can now construct the widget controller.

18:15.930 --> 18:21.300
Because our HUD has get overlay widget controller, it requires the params.

18:21.300 --> 18:24.870
It's going to be null the first time our overlay widget controller.

18:24.870 --> 18:30.420
So it's going to construct the widget controller, set it's widget controller params and return one.

18:30.420 --> 18:38.100
So what we'll do here is we'll call that function and store its result in a you overlay widget controller.

18:38.100 --> 18:39.540
So we'll make that pointer.

18:39.540 --> 18:47.970
We'll call it overlay widget controller and we'll initialize it with get overlay widget controller.

18:47.970 --> 18:52.170
And as we can see it requires the f widget controller params.

18:52.170 --> 18:54.960
We have one here called widget controller params.

18:54.960 --> 18:57.420
We'll pass that in just like that.

18:57.420 --> 19:00.450
And now we have the overlay widget controller.

19:00.720 --> 19:05.760
So now that we've constructed the overlay widget we've constructed the overlay widget controller.

19:05.760 --> 19:13.020
We need to tie the two together by taking overlay widget and calling set widget controller passing in

19:13.020 --> 19:15.090
overlay widget controller.

19:15.450 --> 19:21.090
And after that we can add it to the viewport and in our HUD line 30.

19:21.120 --> 19:26.640
Looks like I'm hiding a class member overlay widget controller here.

19:26.640 --> 19:34.140
Looks like we made this a member variable, so I'm going to actually call this simply Widget Controller

19:34.230 --> 19:36.540
and pass that in to set Widget Controller.

19:36.540 --> 19:41.070
That way I'm not actually hiding a member variable.

19:41.070 --> 19:44.790
So now we have this function in the HUD called init overlay.

19:44.790 --> 19:50.430
And as long as we can pass in the player controller, the player state the ability system component

19:50.430 --> 19:52.020
and the attribute set.

19:52.020 --> 19:59.760
Then init overlay can construct both the overlay and its widget controller and set the overlay widgets

19:59.760 --> 20:02.580
widget controller before adding it to the viewport.

20:02.580 --> 20:06.030
So this init overlay sort of does everything for us.

20:06.030 --> 20:09.150
We just need to be able to pass in all that information.

20:09.150 --> 20:13.320
So the question is when and where do we call init overlay.

20:13.320 --> 20:16.260
When do we have access to all of these.

20:16.260 --> 20:20.460
When do we know that they're all initialized with valid data already.

20:20.940 --> 20:23.670
And that's going to be your quest.

20:23.700 --> 20:27.630
Now this quest requires you to do a little bit of thinking.

20:27.630 --> 20:33.000
Your objective here is to call init overlay, but decide where to call it.

20:33.000 --> 20:37.440
Where should we call it, when and where are we going to know?

20:37.440 --> 20:40.260
All the key variables are initialized?

20:40.260 --> 20:46.920
This is going to make us think back to where we had to make sure our player controller was already set

20:46.920 --> 20:53.940
for the character, and our player state was already set back when we had to init ability actor info.

20:53.940 --> 20:55.200
So there's a hint for you.

20:55.200 --> 20:58.170
So decide where you need to call this.

20:58.170 --> 21:01.890
Make sure you take care of both cases, the server and the client.

21:01.890 --> 21:08.940
And once you're calling that function, you can play test and make sure you get that widget added to

21:08.940 --> 21:09.810
the viewport.

21:09.810 --> 21:13.950
So pause the video and try this quest now.

21:16.990 --> 21:22.120
Okay, so we now have this nice function that ties everything together in the HUD.

21:22.120 --> 21:25.840
And here is where we create the widget.

21:25.840 --> 21:27.550
Create the widget controller.

21:27.550 --> 21:31.420
Set that widget controller on the widget and add it to the viewport.

21:31.420 --> 21:36.910
But this function requires the player controller, the player state, the ability system component,

21:36.910 --> 21:38.800
and the attribute set.

21:38.800 --> 21:43.090
So where do we know that those are initialized already?

21:43.090 --> 21:51.160
Well, you might have thought that we could go into aura character into init ability actor info.

21:51.430 --> 21:52.960
This is a pretty good spot right?

21:52.960 --> 21:59.380
It's called in possessed by and on rep player state taken care of for the server and the client.

21:59.380 --> 22:04.060
And here is where we already know the controller is set.

22:04.060 --> 22:07.600
And we also know that we have a player state.

22:07.600 --> 22:07.990
Right.

22:07.990 --> 22:10.240
We're checking the aura player state here.

22:10.240 --> 22:12.490
So there's two of our key variables.

22:12.490 --> 22:15.280
And also we have the ability system component.

22:15.280 --> 22:16.660
And the attribute set.

22:16.660 --> 22:18.970
We have all four of the key variables here.

22:18.970 --> 22:21.190
This is a great place to do it.

22:21.190 --> 22:22.960
Now we need to access the HUD.

22:22.960 --> 22:26.710
And the HUD is always accessible through the player controller.

22:26.710 --> 22:35.470
So what we can do is we can get our player controller, the character class has get controller.

22:35.680 --> 22:39.580
And of course this returns a a controller.

22:39.580 --> 22:42.490
So we have to cast it to a player controller.

22:42.490 --> 22:47.230
In fact we can cast it directly to our player controller class.

22:47.230 --> 22:48.280
What is that?

22:48.280 --> 22:51.190
That's of course our A player controller.

22:51.190 --> 22:54.490
That's a or a player controller.

22:54.490 --> 22:56.290
We can cast right away.

22:56.710 --> 23:06.190
And we can store this in an A or a player controller pointer called Aura Player controller.

23:07.760 --> 23:12.980
Now the question arises, do we check this pointer, make sure it's not null?

23:12.980 --> 23:16.100
Or are we sure that it'll never be null?

23:16.100 --> 23:18.590
Or should we place a check here?

23:18.590 --> 23:20.150
Should it never be null?

23:20.150 --> 23:22.220
Is there a problem if it's null?

23:22.370 --> 23:31.250
This is a pretty common question, and a lot of newer developers sort of struggle to understand when

23:31.250 --> 23:39.590
to null check and when to perform an assert like check, and it helps to understand the player controller

23:39.590 --> 23:45.200
and whether or not it exists on all machines for all players.

23:45.200 --> 23:52.580
And we can recall back in our multiplayer discussion that only on the server are all player controllers

23:52.580 --> 23:53.390
valid.

23:53.810 --> 24:01.040
The server has all the players player controllers, but each player has only its own player controller.

24:01.040 --> 24:08.750
So on a client's machine who is controlling that specific character, that player controller is valid,

24:08.750 --> 24:16.610
but the other characters on that client's machine who are not locally controlled, those do not have

24:16.610 --> 24:18.050
valid player controllers.

24:18.050 --> 24:24.200
So say in a three player game, for example, if you are a client, your player controller is valid,

24:24.200 --> 24:31.730
but on your machine, the other two characters, those two copies do not have valid player controllers

24:31.730 --> 24:33.830
and innate ability actor info.

24:33.860 --> 24:39.770
This function will be called and or a player controller will be a null pointer in that case.

24:39.770 --> 24:47.000
So in this scenario for this function or, a player controller can and will be null in multiplayer.

24:47.000 --> 24:48.230
And that's okay.

24:48.230 --> 24:51.650
We only want to continue if it's not null.

24:51.650 --> 24:58.430
So we'll place an if check and wrap this in an if check in that way only if our player controller is

24:58.430 --> 25:00.920
not a null pointer do we continue.

25:00.920 --> 25:06.560
So this is the case where we check the null pointer and don't place an assert, because we don't want

25:06.560 --> 25:08.660
to crash in this case.

25:08.660 --> 25:11.720
Now this brings up an interesting point.

25:11.720 --> 25:15.050
Is there anywhere else in our code that's like that?

25:15.050 --> 25:16.490
Well, there is one.

25:16.490 --> 25:23.810
And just as a bit of a tangent, I'm going to show you that if we go to our player controller dot cpp

25:24.080 --> 25:31.370
right here in Beginplay, we're checking the subsystem and we're calling Add mapping context here.

25:31.370 --> 25:38.810
But really in Beginplay for or a player controller, we're not going to get a valid subsystem unless

25:38.810 --> 25:44.360
we're on the locally controlled machine who has a valid local player here.

25:44.360 --> 25:50.510
So this is one of those cases where we should check the subsystem instead of using an assert that says

25:50.510 --> 25:51.020
check.

25:51.020 --> 25:54.710
So really quick we can just say if subsystem here.

25:56.970 --> 26:01.050
And place that subsystem call right there.

26:01.050 --> 26:03.570
And now this will work in multiplayer.

26:03.570 --> 26:08.370
So that's kind of an important detail now that we're thinking about multiplayer.

26:08.370 --> 26:15.480
So we'll make that change and close or a player controller and come back to or a character in init ability

26:15.480 --> 26:21.360
actor info where we're getting or a player controller now from or a player controller, we can get the

26:21.360 --> 26:29.190
HUD so we can take or a player controller, we can call get HUD and this returns a a HUD.

26:29.190 --> 26:29.580
Right.

26:29.580 --> 26:31.500
But we want an A or a HUD.

26:31.500 --> 26:35.610
So we're going to cast this to A or a HUD.

26:38.240 --> 26:40.100
And we have a valid player controller.

26:40.100 --> 26:42.200
We want a valid HUD as well.

26:42.200 --> 26:49.730
So we'll make a local A or a HUD called or a HUD, and we'll place that in an if check to make sure

26:49.730 --> 26:50.660
that it's valid.

26:50.660 --> 26:56.360
Because remember the HUD is only valid for the locally controlled player.

26:56.420 --> 27:01.430
So if our HUD is valid now we have access to our HUD.

27:01.430 --> 27:08.990
And we can finally call that function on our HUD, which we called init overlay which takes the four

27:08.990 --> 27:09.800
key variables.

27:09.800 --> 27:13.940
We need the player controller we can pass in, or a player controller.

27:13.940 --> 27:17.600
We need the player state we can pass in, or a player state.

27:17.960 --> 27:20.210
We need ability system component.

27:20.210 --> 27:22.610
That's going to be ability system component.

27:22.610 --> 27:26.900
And finally an attribute set that's going to be attribute set.

27:26.900 --> 27:30.920
And now init ability actor info is complete.

27:30.920 --> 27:33.770
And we can go ahead and test this out.

27:33.770 --> 27:35.750
And I'm going to run in debug mode.

27:35.780 --> 27:36.440
All right.

27:36.440 --> 27:38.090
So we've opened the editor.

27:38.090 --> 27:45.950
We're running in debug mode I'm going to go to blueprints UI HUD Openbor HUD.

27:45.950 --> 27:49.820
And we have overlay widget class and overlay widget controller class.

27:49.820 --> 27:54.470
Now we don't have a blueprint for overlay widget controller.

27:54.470 --> 27:55.310
That's okay.

27:55.310 --> 28:01.610
We can set it to the C plus plus class for now, but eventually our overlay widget controller may wish

28:01.610 --> 28:06.230
to have some data on it that we can set from blueprints, so we'll keep that in mind.

28:06.230 --> 28:08.720
But let's go ahead and hit play.

28:08.720 --> 28:10.610
And there we have it.

28:10.610 --> 28:14.810
Our health and mana globes are being displayed on the screen.

28:14.810 --> 28:22.340
And that's all being drawn from the aura HUD, thanks to our nice function init overlay.

28:22.340 --> 28:29.900
And we know that our widget controller is being created and it's being set on our overlay widget.

28:29.900 --> 28:37.130
And just before we wrap up, we can prove to ourselves that that widget controller is being set.

28:37.130 --> 28:38.030
How can we do that?

28:38.030 --> 28:46.880
Well, we can go into the Wbbp overlay widget, go into its graph and right click and we have a widget

28:46.880 --> 28:49.160
controller set event.

28:49.160 --> 28:52.310
Remember we added this to Aura User widget.

28:52.310 --> 28:58.370
And if event widget controller set is fired off, that means we've set the widget controller.

28:58.370 --> 29:01.820
And in fact we can search for widget controller.

29:01.820 --> 29:05.540
And here's the get widget controller.

29:05.540 --> 29:08.570
That's the getter for that variable.

29:08.570 --> 29:10.460
That is our widget controller.

29:10.460 --> 29:13.730
Here in blueprints we can use get object name.

29:14.730 --> 29:21.840
To get a string with that object name, and we can use print string to print it to the screen.

29:21.840 --> 29:28.320
And now if we go ahead and hit play we see overlay widget controller underscore zero.

29:28.320 --> 29:31.080
That's the name of the widget controller.

29:31.080 --> 29:34.770
So we know that the widget controller is set as well.

29:34.770 --> 29:36.990
And we're running this in debug mode.

29:37.140 --> 29:43.110
Which means if we want we can place a breakpoint anywhere, such as in init overlay.

29:43.110 --> 29:49.800
If I place a breakpoint at the very last line where we're calling add to viewport, well, now if we

29:49.800 --> 29:52.050
press play, we'll hit that breakpoint.

29:52.050 --> 29:56.340
And here's where we're starting to see the benefit of having symbols.

29:56.340 --> 29:58.050
Because now check this out.

29:58.050 --> 30:02.910
Down here we have a lot of things popping up and showing us values.

30:02.910 --> 30:12.240
So when this function init overlay gets called we see that this is bp or hud underscore c.

30:12.240 --> 30:17.850
So we know inside this function this this holds a blueprint the or HUD blueprint.

30:17.850 --> 30:18.810
That's pretty cool.

30:18.810 --> 30:26.880
And we know that PC this local input parameter local to init overlay has a valid value look it's set

30:26.880 --> 30:28.740
to BP or a player controller.

30:28.740 --> 30:29.430
How about that.

30:29.430 --> 30:35.940
And we can hover over it and see that in fact hovering over it we see its memory address, we see its

30:35.940 --> 30:36.630
name.

30:36.630 --> 30:39.750
And if we click plus we get a dropdown.

30:39.750 --> 30:45.330
This is all writer specific, but Visual Studio also has debug capabilities.

30:45.330 --> 30:49.890
We see that the player controller has last actor and this actor set to null.

30:49.890 --> 30:52.950
Those are those I enemy interface pointers.

30:52.950 --> 30:56.370
And so we have the ability to see all kinds of information.

30:56.370 --> 30:58.440
So that's really really cool.

30:58.440 --> 31:04.770
And by the way I'm just now remembering last actor and this actor where raw pointers right.

31:04.770 --> 31:06.330
We didn't use object pointer.

31:06.330 --> 31:07.710
And we can see that here.

31:07.710 --> 31:14.370
And if we want that to be an object pointer we really could change it to object pointer and keep up

31:14.370 --> 31:15.210
with that standard.

31:15.210 --> 31:18.240
So hey there Steven from the future here.

31:18.240 --> 31:23.220
Coming back to let you know that what I said in this video is incorrect.

31:23.220 --> 31:28.530
We cannot use a t object pointer for an interface such as our eye enemy interface.

31:28.530 --> 31:29.880
That is not correct.

31:29.880 --> 31:33.180
What we need to use instead is a t script interface.

31:33.180 --> 31:41.250
Please refer back to section two in the Highlight Enemies lecture, where we use the T script interface

31:41.250 --> 31:43.800
instead of eye enemy interface.

31:43.800 --> 31:49.950
That was an addition to the course, so please make sure that you're using a T script interface and

31:49.950 --> 31:57.270
not a raw pointer or a t object pointer for your last actor and this actor.

31:57.270 --> 31:58.320
Very important.

31:58.320 --> 32:00.540
Use t script interface.

32:00.540 --> 32:06.960
Now that widget controller can start really controlling the widgets that have their widget controller

32:06.960 --> 32:07.710
set to it.

32:07.710 --> 32:10.560
And we're going to see that power in the videos to come.

32:10.560 --> 32:15.540
So excellent job and I'll see you in the next video.
