WEBVTT

00:06.960 --> 00:07.980
Welcome back.

00:07.980 --> 00:10.250
Now we have an aura player controller.

00:10.260 --> 00:11.820
It has an aura context.

00:11.820 --> 00:15.270
That's the input mapping context that we're going to set.

00:15.300 --> 00:21.420
Once we make a blueprint based on this and then begin play, we access the enhanced input local player

00:21.420 --> 00:24.900
subsystem to call add mapping context.

00:24.930 --> 00:30.360
That's how we add that mapping context so that our player controller can retrieve data.

00:30.360 --> 00:32.640
Now, how do we actually retrieve that data?

00:32.640 --> 00:37.080
Well, in characters it's usually done in setup player input component.

00:37.080 --> 00:42.330
And if you'll recall, that used to be in our or a character base, but we deleted that function as

00:42.330 --> 00:47.910
we plan on doing things here in the player controller and the player controller can handle input.

00:47.910 --> 00:51.210
It has a function called setup input component.

00:51.210 --> 00:54.780
So contrast that with setup player input component.

00:54.810 --> 00:57.450
It's just called setup input component.

00:57.480 --> 01:02.490
Now this is a protected function much like Beginplay and we're going to override this.

01:02.490 --> 01:10.390
So we'll say virtual void setup input component override ID and we can go ahead and generate the definition.

01:10.390 --> 01:13.480
And in this function, of course, we need to call super.

01:13.480 --> 01:17.380
We'll let that happen, but we need to access the input component.

01:17.410 --> 01:21.760
You see, the player controller has an input component variable.

01:21.760 --> 01:26.770
If we simply type input component, we'll see that we can access that variable.

01:26.770 --> 01:32.260
And if we hover over it, we see that it's a T object pointer of type U input component.

01:32.410 --> 01:39.400
Now we created an enhanced input input action and to bind a function to that input action so it can

01:39.400 --> 01:46.420
be called to handle input data, we need to cast our input component to an enhanced input component

01:46.420 --> 01:53.260
as this input component is a pointer of type U input component, but it actually stores the address

01:53.260 --> 01:57.600
of an object of type U enhanced input component.

01:57.610 --> 02:05.710
So if we say U enhanced input component and create a pointer to that and we can call it enhanced input

02:05.710 --> 02:13.000
component, for instance, we can cast the input component to this type now rather than casting and

02:13.000 --> 02:19.150
then checking the pointer or using an assert like we did up here with subsystem, we can do both in

02:19.150 --> 02:25.000
one go using cast checked cast checked needs to know what type we're casting to.

02:25.000 --> 02:27.760
That's this type enhanced input component.

02:27.760 --> 02:31.960
And what we're casting is our input component member variable.

02:31.960 --> 02:37.150
And if the cast fails, then it's the same as hitting an assert here.

02:37.150 --> 02:40.480
In other words, we can crash the program if this cast fails.

02:40.480 --> 02:46.840
Now this is an incomplete type, which means we're going to need an include for this so we can include

02:46.840 --> 02:47.620
that.

02:47.650 --> 02:56.110
And that's going to simply be the include for enhanced input component dot H.

02:56.110 --> 03:00.220
And now this is no longer an incomplete type and we don't need to check the pointer.

03:00.220 --> 03:02.350
We don't need to use an assert.

03:02.380 --> 03:08.140
We'll get a crash if this cast fails, which is what we want because that will really get our attention

03:08.140 --> 03:10.630
and make sure that this is not broken.

03:10.630 --> 03:17.170
So once we have our enhanced input component, we want to bind our move input action to it, which means

03:17.170 --> 03:24.460
just like our input mapping context called aura context, we also need a variable for our input action.

03:24.460 --> 03:29.440
Now the C plus plus type for input actions is U input action, and I'm going to go ahead and forward

03:29.440 --> 03:33.040
declare it right up here along with our input mapping context.

03:33.040 --> 03:40.060
So we'll say class U input action and we'll add a variable down here of that type.

03:40.060 --> 03:41.410
It can be a private variable.

03:41.410 --> 03:48.700
So we'll say T object pointer u input action and we'll call this move action.

03:48.700 --> 03:53.050
We'll make it edit anywhere and stick it in the same category category input.

03:53.050 --> 03:54.940
So we'll give it that u property.

03:55.030 --> 04:00.940
Now we're going to want to set that on the blueprint and we're going to want to bind a function that

04:00.940 --> 04:03.940
we can use to move our character in response to input.

04:03.940 --> 04:07.150
So we need a function for moving the character.

04:07.180 --> 04:12.940
This is going to only be called internally here in the player controller, so it can also be private.

04:12.970 --> 04:20.110
We'll make a void function called Move Now in order to bind move to an input action that provides data,

04:20.110 --> 04:28.570
we have to provide an input parameter for move and that's going to be of type const F input action value.

04:28.840 --> 04:33.640
That will be a const reference and we'll call this input action value.

04:33.940 --> 04:38.290
Now F input action value is not defined here.

04:38.290 --> 04:45.040
We would have to include the header file for it or forward declare it because it's a reference here

04:45.040 --> 04:48.010
we can forward declare it and it's a struct.

04:48.010 --> 04:54.910
So rather than forward declaring with the class keyword we can say struct f input action value and forward

04:54.910 --> 04:56.080
declare it that way.

04:56.080 --> 05:01.960
We could also alternatively forward declare up here with our other forward declarations so we can say

05:01.960 --> 05:05.350
struct f input action value up there.

05:05.350 --> 05:06.700
And then this.

05:06.720 --> 05:12.810
Struct keyword down here now becomes redundant as Ryder has graded out, telling me that I no longer

05:12.810 --> 05:15.940
need it there as we've already forward declared.

05:15.960 --> 05:19.170
Now we can generate a function definition for move.

05:19.170 --> 05:22.440
I'll go ahead and let Ryder generate that for me.

05:22.440 --> 05:29.010
And now we have a callback function and we also have our move action input action variable.

05:29.010 --> 05:31.170
Now we need to link these two together.

05:31.170 --> 05:39.390
Whenever we press Wasd keys, our Move action will be filled in with data according to how we've configured

05:39.390 --> 05:40.770
our input mapping context.

05:40.770 --> 05:41.070
Right.

05:41.070 --> 05:46.710
So Move needs to accept that data in the form of an input action value.

05:46.710 --> 05:52.950
So we'll configure this here in setup input component since we have access to our input component and

05:52.950 --> 06:00.150
the input component has the function bind action designed to do just that, bind a function to one of

06:00.150 --> 06:01.140
our input actions.

06:01.140 --> 06:08.010
So we're going to take enhanced input component and we're going to call bind action, which takes the

06:08.010 --> 06:08.820
input action.

06:08.820 --> 06:13.590
We're going to use our move action and takes an E trigger event.

06:13.590 --> 06:19.200
In other words, do we want move called when our input action starts?

06:19.230 --> 06:22.770
Do we want it when our input action is triggered?

06:22.770 --> 06:29.070
In other words, do we want to continue calling this as long as our input is triggered or held down?

06:29.070 --> 06:32.310
In our case, I do want that, so I'm going to choose triggered.

06:32.340 --> 06:36.780
Next is the user object that's going to be this player controller object.

06:36.780 --> 06:39.030
And finally, the callback function.

06:39.030 --> 06:44.550
That's going to be the address of operator, followed by the fully qualified function name.

06:44.550 --> 06:50.190
We'd like to bind to this input action A or a player controller move.

06:50.190 --> 06:58.560
So after this line move will be bound to move, action and then move can contain the movement functionality

06:58.590 --> 06:59.820
for moving the character.

06:59.820 --> 07:01.770
And that's going to be relatively simple.

07:01.770 --> 07:08.460
First, we have to get our input action value and we need that in a form that we can retrieve the X

07:08.460 --> 07:10.880
and Y axis data from it.

07:10.890 --> 07:18.870
Remember, our move input action is an axis 2D type input action so we can make a const local F vector

07:18.870 --> 07:25.320
2d called input axis vector.

07:26.430 --> 07:32.880
And what we'll do is we'll take our input action value, we'll call get on it, which is a template

07:32.880 --> 07:38.130
function that allows us to get the value in the form that we need it in.

07:38.160 --> 07:40.980
We need it in an F vector 2d form.

07:42.970 --> 07:47.500
So now we have our input action value in the form of a vector 2D.

07:47.530 --> 07:51.080
We can access the X and Y axes of that.

07:51.100 --> 07:52.930
So how do we want to use it?

07:52.960 --> 08:00.160
Well, we'd like to use add movement input to add movement to our controlled pawn in the forward direction

08:00.160 --> 08:05.770
and the right direction based on the X and Y values of our input axis vector.

08:05.800 --> 08:13.060
So the way we do that is first we figure out which direction is forward for us and we want to find out

08:13.060 --> 08:15.620
which direction is forward based on our controller.

08:15.640 --> 08:23.290
As our controller will be pointed basically in the direction from the camera to the character and controllers

08:23.290 --> 08:27.190
have a rotation accessible with get control rotation.

08:27.610 --> 08:33.850
So if we get this control rotation and we zero out its pitch and roll, then we have the yaw value for

08:33.850 --> 08:35.470
our controller's rotation.

08:35.470 --> 08:42.910
And if we convert that to a vector, then that will be what we consider forward As far as w asd keys

08:42.940 --> 08:44.030
are concerned.

08:44.050 --> 08:45.520
So here's what I'll do.

08:45.550 --> 08:52.630
I'll make a const f rotator called rotation and initialize it with get control rotation.

08:53.020 --> 08:57.850
So we have our controllers rotation but I'd like its pitch and roll zeroed out.

08:57.850 --> 08:59.080
So we just have your.

08:59.260 --> 09:06.640
So I'll make another const F rotator called your rotation and I'll initialize it with a zero for the

09:06.640 --> 09:09.310
pitch and I'll use the yaw from rotation.

09:09.310 --> 09:13.900
So rotation yaw for the yaw and zero for the roll.

09:13.930 --> 09:18.670
Now you could be clever and condense these into the same line if you like.

09:18.760 --> 09:23.680
I'm going to leave it like this so it's a bit more obvious what I'm doing.

09:23.860 --> 09:29.320
And now I have a rotation that I can use to get a forward vector from.

09:29.320 --> 09:31.660
The way to do that is to create an f vector.

09:31.660 --> 09:39.100
I'm going to make this const and I'll call this forward direction and we can use an F rotation matrix

09:39.100 --> 09:43.220
to get a forward vector from this rotator value.

09:43.250 --> 09:45.920
We do that with F rotation matrix.

09:47.090 --> 09:54.320
We initialize an F rotation matrix with our rotation, and from that F rotation matrix we call the function

09:54.320 --> 09:59.180
get unit axis, not axes but axis.

09:59.180 --> 10:01.910
And this requires the enum e axis.

10:04.170 --> 10:06.240
And we need to specify the axis.

10:06.270 --> 10:08.640
X will give us the forward axis.

10:08.640 --> 10:14.160
So this gives us the forward vector that corresponds to this, your rotation vector.

10:14.160 --> 10:19.020
And if our controller's rotation is that rotation, as I mentioned, from the camera to the character,

10:19.020 --> 10:24.690
and if your rotation has zeroed out the pitch and roll for that, then forward direction is the vector

10:24.690 --> 10:28.770
pointing from the camera to the character only it's leveled out.

10:28.770 --> 10:30.450
It's parallel to the ground.

10:30.540 --> 10:32.280
That's how we get forward direction.

10:32.280 --> 10:34.380
But we also want the right direction.

10:34.380 --> 10:41.880
So we're going to make a const f vector called right Direction and we'll use this same exact function

10:41.880 --> 10:44.790
call creating an F rotation matrix.

10:44.790 --> 10:51.090
The only difference is for each axis we're going to use Y as that will give us the right axis vector.

10:51.090 --> 10:58.080
And these are normalized because get unit axis returns a unit vector, which is a vector with a length

10:58.080 --> 10:58.680
of one.

10:58.680 --> 11:04.260
Now that we have those directions, we can add movement input to the controlled pawn.

11:04.270 --> 11:11.200
Now, to get the pawn controlled by our player controller, we can call, get pawn and get pawn is a

11:11.200 --> 11:11.620
template.

11:11.620 --> 11:13.870
Function requires a type.

11:13.870 --> 11:15.310
We just want a pawn.

11:15.340 --> 11:16.150
That's fine.

11:16.150 --> 11:22.060
And what we can do is create a local pointer variable of type a pawn.

11:22.210 --> 11:28.000
We'll call this controlled pawn and we'll wrap this in an if statement.

11:29.710 --> 11:34.810
So that way, if controlled pawn is null, well then we won't do anything.

11:34.810 --> 11:40.780
And because Move is potentially called every frame, it might be called a little too early before this

11:40.780 --> 11:42.040
controlled pawn is valid.

11:42.040 --> 11:47.950
So in this case, rather than doing an assert, we're just going to check the pointer and we have forward

11:47.950 --> 11:49.180
and right directions.

11:49.180 --> 11:51.760
All we need to do is take that controlled pawn.

11:53.720 --> 12:00.070
And we can call add movement input on that pawn and add movement input takes a world direction.

12:00.080 --> 12:06.380
We'll add movement input in the forward direction, but we also have a scale value to pass in and our

12:06.380 --> 12:08.030
input axis vector.

12:08.060 --> 12:13.100
This 2D vector from our input action value has an X and a Y component.

12:13.100 --> 12:19.040
And as we already said, as we're pressing W and S to go forward and back, the Y component of this

12:19.040 --> 12:24.950
vector will be positive 1 or -1 depending on whether we're pressing W or S.

12:24.980 --> 12:30.260
If we're pressing S, it'll be negative and we'll be calling add movement input, moving our character

12:30.260 --> 12:35.450
in the forward direction, but scaled by negative one, which means we'll have it moving in the backward

12:35.450 --> 12:36.260
direction.

12:36.260 --> 12:40.730
So we need to scale by the y component of this input axis vector.

12:40.730 --> 12:43.100
So we'll say input axis vector.

12:43.710 --> 12:49.380
Dot y here, and we'll handle moving left and right by taking this line.

12:49.380 --> 12:50.490
We'll copy it.

12:50.490 --> 12:54.150
And instead of forward direction, we'll pass in right direction.

12:54.150 --> 13:01.500
And instead of the input axis, vector y component, we'll use the x component as the x is what we associated

13:01.500 --> 13:04.460
with the A and D keys moving left and right.

13:04.470 --> 13:10.140
So now we have a move function that will handle movement based on our input action.

13:10.140 --> 13:14.880
So now that this is all set up, the only thing left to do is tie this all together.

13:14.880 --> 13:18.390
We need to make an aura player controller blueprint.

13:18.420 --> 13:24.630
We need to set these variables, the aura input mapping context and the move action.

13:24.630 --> 13:32.280
And then we need to make sure that our project is configured to use aura player controller and our Aura

13:32.280 --> 13:33.390
character.

13:33.390 --> 13:35.580
So we'll take this one step at a time.

13:35.580 --> 13:41.100
The first thing we need to do is actually make a blueprint based on this C plus plus class.

13:41.100 --> 13:44.680
So your quest will be to make a player controller blueprint.

13:44.680 --> 13:50.170
So create a blueprint based on aura player controller, call it BP or a player controller.

13:50.170 --> 13:54.070
Make sure you keep a good folder structure in your blueprints folder.

13:54.070 --> 14:00.160
Now, in this blueprint, set up the input action and input mapping context variables that we added

14:00.160 --> 14:01.570
in C plus plus.

14:01.660 --> 14:04.480
Pause the video and conquer this quest.

14:07.520 --> 14:10.070
Okay, so we need a blueprint based on this class.

14:10.070 --> 14:15.800
I'm going to go ahead and launch the editor and here in the Blueprints folder, I'm going to make a

14:15.800 --> 14:20.720
new folder called Player and we'll make that blueprint here.

14:20.720 --> 14:26.870
So I'm going to right click, make a Blueprint class and search for Aura Player controller and choose

14:26.870 --> 14:27.590
that.

14:28.640 --> 14:32.960
And this will be BP ora player controller.

14:33.920 --> 14:38.060
And I can open that up and we can set ora context.

14:38.090 --> 14:44.090
We'll use IMC ora context and our move action will be in a move.

14:44.120 --> 14:48.230
So that's set up and we're all set there and that's it.

14:48.230 --> 14:54.260
So in the next video, we need to make sure that our project is set to use this player controller as

14:54.260 --> 14:56.450
well as our Ora character.

14:56.450 --> 14:59.480
We can configure all that with a game mode.

14:59.480 --> 15:01.190
So we'll be making that next.

15:01.190 --> 15:08.360
And before we wrap up the video, recall that in our player controller we cast our input component to

15:08.360 --> 15:09.110
the U.

15:09.110 --> 15:11.270
Enhanced input component class.

15:11.270 --> 15:18.110
And I mentioned that I know that this pointer, which is a pointer of type U input component, points

15:18.110 --> 15:21.470
to an object of type U enhanced input component.

15:21.500 --> 15:22.950
Now how did I know that?

15:22.970 --> 15:27.620
Well, if you go to edit project settings and input.

15:28.480 --> 15:30.790
Then we can scroll down to the bottom.

15:30.790 --> 15:37.360
And down here, under default classes, we have default input component class and it's set to enhanced

15:37.360 --> 15:38.650
input component.

15:38.680 --> 15:44.650
That's how I knew that our input component pointer points to an object of this type because here in

15:44.650 --> 15:47.500
project settings is where we configure that.

15:47.500 --> 15:53.830
And if we wanted a say, custom enhanced input component class and we went and created one in C plus

15:53.830 --> 16:00.880
plus, then here is where we would set that class to make sure our project uses that as the input component.

16:00.880 --> 16:06.190
So I figured I would just point that out so I can go ahead and close project settings.

16:06.190 --> 16:11.830
And in the next video we'll tie all this together so we can actually start moving our character.

16:11.830 --> 16:12.870
So great job.

16:12.880 --> 16:14.140
I'll see you soon.
