WEBVTT

00:06.900 --> 00:08.130
Welcome back.

00:08.400 --> 00:11.550
Now we have our gameplay ability firebolt.

00:11.640 --> 00:14.940
And so far it's pretty simple.

00:15.030 --> 00:23.010
If we're hovering over an enemy and we left click, we spawn a Firebolt, which is great, but obviously

00:23.010 --> 00:25.140
we have some things that we need to do.

00:25.440 --> 00:32.040
Now in this section we're concerned with talking about ability, tasks and ability.

00:32.040 --> 00:41.640
Tasks are sort of like the workers that a gameplay ability employs to do tasks and things that can be

00:41.640 --> 00:47.280
done either instantaneously or they may span across some period of time.

00:47.280 --> 00:52.860
And there are a number of tasks that already exist in the gameplay ability system.

00:52.860 --> 00:56.010
And of course we have the ability to create our own.

00:56.040 --> 01:01.730
Now the easiest way to learn how tasks work is to just use one of the pre-made tasks.

01:01.740 --> 01:05.580
So if we right click, let's type play montage.

01:05.760 --> 01:15.850
Now if we select play montage under animation montage, this is what we refer to as a latent node.

01:15.880 --> 01:21.970
Latent means a synchronous or a node that will be executed.

01:22.060 --> 01:30.340
And then depending on what happens later, we have a number of output execution pins that can be executed.

01:30.370 --> 01:37.690
Notice that it has an input execution pin and it also has a regular output execution pin.

01:37.930 --> 01:45.820
The regular output execution pin at the very top right is executed immediately after we reach the node.

01:45.910 --> 01:52.960
But then that allows us to continue calling other functions and things right after we've reached the

01:52.960 --> 01:53.680
node.

01:53.710 --> 02:01.450
But then we have a number of circumstances that can trigger these other output execution wires to flow

02:01.450 --> 02:03.190
such as completed.

02:03.190 --> 02:07.630
That's when the montage has finished playing on blend out.

02:07.630 --> 02:15.100
This is executed when the montage begins, blending out and is not interrupted and depending on blend

02:15.130 --> 02:22.720
settings, this might be earlier than completed and usually is on interrupted is self-explanatory.

02:22.750 --> 02:24.640
On notify Begin.

02:24.670 --> 02:33.550
This is executed when using a play montage, notify or a play montage notify window in the montage as

02:33.550 --> 02:40.420
we can put notifies in the montage and then of course notify end is for when a montage notify window

02:40.420 --> 02:41.440
has ended.

02:41.440 --> 02:48.550
As you can see, there are a number of things that can cause any of these situations to trigger.

02:48.550 --> 02:55.200
Now this is just a blueprint latent node, also known as an async task.

02:55.210 --> 03:02.830
Now gas has more specialized forms of these latent nodes and these are more ingrained in the ability

03:02.830 --> 03:04.030
system itself.

03:04.210 --> 03:13.590
For example, if we type play montage, notice that there's another blueprint function under ability

03:13.620 --> 03:14.370
tasks.

03:14.370 --> 03:19.980
This is an ability task and if we click on this one, it looks a lot like the other one.

03:19.980 --> 03:22.290
It just has more options, right?

03:22.290 --> 03:28.500
And if you had browsed through the gameplay ability header file, you may have noticed that there were

03:28.500 --> 03:31.650
some things in there related to montages.

03:31.680 --> 03:35.970
A given ability knows which montage is currently playing.

03:35.970 --> 03:44.130
If we're using the gameplay ability system version of play montage and wait now play montage in wait

03:44.160 --> 03:45.990
is going to do what it says.

03:45.990 --> 03:52.890
It's going to play a montage and then it's going to wait for one of these things to happen for the montage

03:52.890 --> 03:57.090
to complete or blend out or be interrupted or cancelled.

03:57.120 --> 04:03.180
And then of course, we have the topmost execution pin that we can execute things immediately after

04:03.180 --> 04:05.070
reaching the node with.

04:05.100 --> 04:06.930
Now let's see how this works.

04:06.930 --> 04:14.650
I'm going to delete that play montage latent node and leave my play montage in wait ability task node.

04:14.650 --> 04:17.800
And what this can do is it can play a montage.

04:17.800 --> 04:23.670
We can hardcode one in by selecting one here, but that means we need a montage to play, don't we?

04:23.680 --> 04:26.410
So why don't we create a montage real quick?

04:26.410 --> 04:34.540
We can go to content assets, characters, aura animations, abilities and we have this cast Firebolt

04:34.540 --> 04:35.620
animation.

04:35.800 --> 04:37.000
I'd like to use this.

04:37.000 --> 04:44.320
I'm going to right click on it, go to create and create anim montage and I'm going to call this a m

04:44.320 --> 04:48.580
underscore cast underscore Firebolt.

04:48.790 --> 04:50.410
I'm going to double click on it.

04:50.410 --> 04:52.360
And now I have a montage.

04:53.760 --> 04:56.790
Now it's set to the default slot.

04:56.820 --> 05:02.040
All montages are set to use the default slot by default.

05:02.050 --> 05:02.580
Right.

05:02.640 --> 05:09.780
But we do need to be using that default slot and it's a good idea to just double check in our animation

05:09.780 --> 05:10.290
blueprint.

05:10.290 --> 05:16.560
So in Blueprints Character Aura, here's our animation blueprint app Aura.

05:16.740 --> 05:22.440
And yes, we created the default slot node here and we're running our pose through it.

05:22.440 --> 05:27.480
So if we play this montage, we'll actually successfully see it played.

05:27.630 --> 05:31.770
So we have a montage called Arm Cast Firebolt.

05:31.770 --> 05:38.460
So if we go back to our gameplay ability and open our dropdown, we now see the montage, we can select

05:38.460 --> 05:45.660
that and play montage and weight is going to play the montage and we can just see that this topmost

05:45.660 --> 05:54.510
execution wire is executed right away by printing a string that says Casting Firebolt.

05:54.510 --> 06:03.000
And if we compile and press play and click on an enemy, we see that we're playing that montage and

06:03.030 --> 06:08.640
of course we're spawning the projectile immediately, which doesn't look right, but we're playing the

06:08.640 --> 06:09.300
montage.

06:09.330 --> 06:15.180
Now let's open that montage back up and make sure that we're okay with our blend options.

06:15.210 --> 06:20.220
Our blend in under blend option is set to 0.25.

06:20.220 --> 06:26.520
I'd like this to be zero so we have no blending and for blend out, I'm okay with a little blending,

06:26.520 --> 06:27.840
but less than that.

06:27.840 --> 06:31.530
I want 0.1 and then we can test this out.

06:32.460 --> 06:33.300
That looks better.

06:33.300 --> 06:40.740
I want to just start playing the montage with no blending at all so it's a lot faster, more responsive.

06:40.770 --> 06:43.230
You can have some blending here if you want.

06:43.440 --> 06:48.860
If you prefer to have it less snappy, you can have a blend in time.

06:48.870 --> 06:53.160
I like them very low, so like 0.05 is a good blend time.

06:53.160 --> 07:00.360
So as we can see, we play the montage and immediately we get that print string node because that print

07:00.360 --> 07:06.060
string node is reached immediately after play montage and wait.

07:06.240 --> 07:08.790
However we can do things later.

07:08.790 --> 07:11.670
That's what async tasks are good for.

07:11.670 --> 07:19.560
We can do something when Oncompleted is executed so we can just drag off of this, use a print string

07:19.560 --> 07:22.200
and say Oncompleted.

07:22.800 --> 07:25.650
We can also do something on blend out.

07:25.650 --> 07:30.570
So we'll do a print string in this case that says on Blend out

07:33.300 --> 07:40.560
and then we'll do a print string for the other two here we're going to say on Interrupted.

07:42.360 --> 07:44.280
And then on cancelled.

07:46.300 --> 07:48.010
We'll say on Canceled.

07:49.790 --> 07:52.490
So that way we can see which of these gets called.

07:52.580 --> 07:55.310
So we'll go ahead and activate our ability.

07:56.090 --> 08:01.730
And then we see that on blend out and on completed happened, right?

08:01.760 --> 08:03.230
They get executed.

08:03.350 --> 08:03.980
Why?

08:04.010 --> 08:13.100
Because we start blending out first and that's why we get that message first and then on completed happens

08:13.100 --> 08:21.290
because shortly after we began blending out, the montage completes and we're not interrupting or canceling

08:21.290 --> 08:21.920
the montage.

08:21.920 --> 08:24.500
So those print strings don't get called.

08:24.500 --> 08:31.250
But we saw that a short period of time elapsed before on Blend out and on completed were executed.

08:31.400 --> 08:39.110
This allows us to do things later in time without needing to go through the trouble of using timers

08:39.110 --> 08:40.070
and things like that.

08:40.070 --> 08:44.510
We can base things on the length of a montage, so this is great.

08:44.540 --> 08:50.160
Now we know how to use the blueprint node, but how does this work under the hood?

08:50.160 --> 08:58.440
How does a blueprint node become async and how does it wait until something happens and then execute

08:58.440 --> 09:02.190
these wires conditionally based on what's going on in the game?

09:02.310 --> 09:08.910
Well, I'm going to close and save all and I'm going to hit double shift so I can search my solution

09:08.910 --> 09:11.940
and I'm going to search for play montage and wait.

09:12.420 --> 09:19.320
And we see this U ability task play montage and wait and it's in the header file with that name.

09:19.320 --> 09:25.320
I'm going to click on that and we see that this is a class based on U ability task.

09:25.680 --> 09:29.430
The comment says ability task to simply play a montage.

09:29.460 --> 09:35.190
Many games will want to make a modified version of this task that looks for game specific events.

09:35.220 --> 09:37.350
Now let's take a look at this class.

09:37.350 --> 09:40.920
Here in the class, we have a number of delegates.

09:41.280 --> 09:49.080
We have an F montage weight, simple delegate, and there are four of them on completed on blend out

09:49.110 --> 09:51.660
on interrupted and on canceled.

09:51.690 --> 09:55.590
Those were the names of those output execution pins.

09:55.590 --> 10:03.150
So when you create an ability task and you add some blueprint assignable delegates to it, then those

10:03.150 --> 10:07.650
become output execution pins for the ability task node.

10:08.040 --> 10:10.770
So we have some comment here.

10:10.770 --> 10:15.720
And this big comment is right above this right here.

10:15.840 --> 10:25.830
And what we have is a static function called create play montage and wait proxy that returns a pointer

10:25.830 --> 10:29.730
of type U ability task play montage and wait.

10:29.760 --> 10:36.780
Now this is a blueprint callable, it has a category, it has a meta with display name, play, montage

10:36.780 --> 10:42.870
and wait, which means that the blueprint node for this function is going to say play montage and wait.

10:42.870 --> 10:46.650
It doesn't have the u ability task in front of it.

10:46.680 --> 10:54.900
It also has hide pin owning ability so this means that the blueprint node is not going to show this

10:54.930 --> 10:58.380
input parameter for this function called owning ability.

10:58.590 --> 11:06.240
It also has default to self owning ability, which means that not only are we hiding this input parameter

11:06.240 --> 11:13.830
as a pin from the blueprint node, we're saying to default this owning ability to self in C plus plus

11:13.830 --> 11:15.030
that would be this.

11:15.030 --> 11:21.570
And we see blueprint internal use only set to true, which if we hover over it says this function is

11:21.570 --> 11:27.030
an internal implementation detail used to implement another function or node.

11:27.030 --> 11:30.150
It is never directly exposed in a graph.

11:30.390 --> 11:38.010
When we create this static function that returns the type of the class that we're in like this with

11:38.010 --> 11:45.990
these specific U function specifiers, this creates our latent node that we saw in Blueprint.

11:46.020 --> 11:53.850
Now, if we go to the CPP file and take a look at the definition of that static function, we can scroll

11:53.850 --> 11:54.780
down and find it.

11:54.780 --> 11:55.680
Here it is.

11:55.680 --> 11:57.420
We can see what it's doing.

11:57.420 --> 12:04.920
Ultimately, it's creating a new ability task with this function, new ability, task, specifying this

12:04.920 --> 12:11.550
particular task, and then it's setting a number of parameters on that new task and returning it.

12:11.550 --> 12:18.330
So these ability tasks have this static function that creates an instance of themselves and returns

12:18.330 --> 12:25.440
it after setting a number of input parameters that can be exposed to the blueprint.

12:25.440 --> 12:32.340
So this is made to be created in blueprint, although the function itself could be called in C plus

12:32.340 --> 12:33.390
plus of course.

12:33.390 --> 12:39.150
And then we know that this particular class has a number of delegates right now.

12:39.150 --> 12:46.080
As soon as we've created this ability, task ability tasks have an activate function and when they're

12:46.080 --> 12:48.480
activated, whatever we have in this activate.

12:48.510 --> 12:51.340
Function is what happens now.

12:51.360 --> 12:56.620
Play montage and wait, as we would probably imagine, is going to play a montage.

12:56.640 --> 12:58.550
We can see that right here.

12:58.560 --> 13:03.480
It's calling play montage on guess what an ability system component.

13:03.510 --> 13:07.680
How does it know which ability system component to play the montage on?

13:07.830 --> 13:12.060
Well, ability tasks have an owning ability system component.

13:12.090 --> 13:15.450
They have a variable called ability system component.

13:15.450 --> 13:20.430
And this particular ability task is just calling play montage on it.

13:20.460 --> 13:25.080
Notice that it's also binding some function callbacks to some delegates.

13:25.200 --> 13:28.250
These are those delegates we looked at in the header file.

13:28.260 --> 13:32.610
It's binding its own on montage blending out function.

13:32.610 --> 13:35.880
And what does on montage blending out do?

13:35.910 --> 13:37.110
Well, here it is.

13:37.110 --> 13:38.610
We see what it's doing.

13:38.710 --> 13:43.200
It calls clear animating ability on the ability system component.

13:43.320 --> 13:44.850
It gets the character.

13:44.850 --> 13:45.750
How does it get it?

13:45.750 --> 13:47.880
It gets it from the avatar actor.

13:47.880 --> 13:49.770
So it has a function.

13:49.770 --> 13:51.260
Get Avatar actor.

13:51.270 --> 13:56.990
It's checking for authority and then calling set and root motion translation scale.

13:57.000 --> 14:00.030
We don't have to get too deep in what all these do.

14:00.060 --> 14:02.250
This function is self-explanatory.

14:02.250 --> 14:07.650
If you're using root motion, that root motion can be scaled for its translation.

14:08.070 --> 14:10.890
This function checks to see if it's being interrupted.

14:10.890 --> 14:13.490
If so, it broadcasts on interrupted.

14:13.500 --> 14:15.750
Same thing for on blend out.

14:15.990 --> 14:22.250
So as you can see, the class has a number of callbacks bound to the delegates that it has.

14:22.260 --> 14:30.360
So the takeaway here is that an ability task is basically this C plus plus class that has a static function,

14:30.390 --> 14:36.900
a sort of factory of sorts that constructs an instance of itself that's blueprint callable exposed to

14:36.900 --> 14:37.740
blueprint.

14:37.740 --> 14:44.490
And the class has a number of delegates that are broadcast based on things that are happening.

14:44.490 --> 14:52.500
And it has an activate function usually in which those delegates have some callbacks bound to them.

14:52.500 --> 14:58.470
And these delegates can be broadcast based on whatever logic we implement here.

14:58.500 --> 15:00.270
Play montage and wait.

15:00.270 --> 15:07.890
Just happens to play a montage and broadcast delegates when the montage is finished or in any number

15:07.890 --> 15:16.560
of related cases to that, you'll see that our ability task is getting the anim instance from the actor

15:16.560 --> 15:23.400
info associated with this ability tasks, ability and owning ability system component and getting a

15:23.400 --> 15:30.450
montage set blending out delegate and then that results in this delegate having its callback executed

15:30.450 --> 15:32.850
which is on montage blending out.

15:32.850 --> 15:37.980
So as you can see, there are lots of delegates and this will make a lot more sense when we create an

15:37.980 --> 15:39.840
ability task of our own.

15:40.050 --> 15:46.740
But this deep dive is just to show what's going on behind the scenes with this play montage and wait.

15:46.860 --> 15:53.040
So now that we've seen what play montage and wait is sort of doing behind the scenes, we can use play

15:53.040 --> 15:59.610
montage and wait in our gameplay ability and that's going to make things easier for us when we need

15:59.610 --> 16:04.110
to play a montage in a given gameplay ability and wait for something to happen.

16:04.230 --> 16:09.510
Now, what if we want to wait for something that's not one of these cases?

16:09.720 --> 16:16.710
What if we want to wait until a certain point in our montage before we do the next thing, such as spawn

16:16.710 --> 16:17.910
our projectile?

16:17.910 --> 16:22.890
For example, here in our montage, we don't want to spawn our projectile here.

16:22.890 --> 16:30.570
We want to wait until a certain point in the animation, maybe right here to spawn that projectile.

16:30.600 --> 16:33.870
In other words, we might want to create some kind of anim notify.

16:34.200 --> 16:40.770
So how do we know once we've reached a certain point inside of our anim montage so that we can do the

16:40.770 --> 16:45.630
next step in our gameplay ability, such as spawning the projectile?

16:45.720 --> 16:49.830
That's going to be the topic of our next discussion.

16:49.830 --> 16:51.900
So we'll take care of that next.

16:52.350 --> 16:53.180
Great job.

16:53.190 --> 16:54.240
I'll see you soon.
