WEBVTT

00:07.090 --> 00:08.080
Welcome back.

00:08.080 --> 00:13.780
Now our fireballs for the fire blast ability are using on hit, aren't they?

00:13.810 --> 00:20.860
Now, if we go to actor and open fireball, the aura fireball, we don't have anything here for on hit.

00:20.860 --> 00:23.770
We're just using the inherited on hit function.

00:23.770 --> 00:30.070
And if we go to aura projectile, we can see what that function does on hit right here.

00:30.070 --> 00:36.820
It results in playing a sound, spawning a Niagara system, and stopping the looping sound and setting

00:36.820 --> 00:37.390
a boolean.

00:37.390 --> 00:43.000
Now this is great, but this is sort of the vanilla way to do it.

00:43.000 --> 00:50.710
This is just using gameplay statics and you Niagara function library to play sounds and spawn particles.

00:50.710 --> 00:53.890
What if we want to take advantage of gameplay cues?

00:54.130 --> 01:01.870
Well, gameplay cues are replicated by default, as we know there are PCs, and even though we've upped

01:01.870 --> 01:09.550
our projects RPC limit per net update to ten, well, we still know that our fire blast ability is spawning

01:09.580 --> 01:18.550
12 of these, so 12 is verging on a bit much for all at once, which is why we've erred on the side

01:18.550 --> 01:22.150
of not using gameplay cues, or at least using them sparingly.

01:22.150 --> 01:23.620
And we're not using them here.

01:23.620 --> 01:25.420
But what if you wanted to anyway?

01:25.420 --> 01:29.710
What if you wanted to use a gameplay cue locally without sending an RPC?

01:29.710 --> 01:36.940
Well, we could do that too, so I'd like to show how to do that with on hit and in fact, ability system

01:36.940 --> 01:44.770
components should all have a set of functions that make it easy to handle gameplay cues locally.

01:44.770 --> 01:45.670
So we'll visit that.

01:45.670 --> 01:52.480
But for now, let's talk about how we can execute a local gameplay cue in or a fireball.

01:52.990 --> 01:58.630
Well, we're already calling on hit, we're calling it on the server, and then in destroyed we're calling

01:58.630 --> 02:01.120
it if B hit is false.

02:01.120 --> 02:01.840
Right?

02:01.840 --> 02:08.680
So really we could take our A fireball and override on hit if we make it virtual.

02:08.830 --> 02:10.480
So that's the way I'd like to do this.

02:10.480 --> 02:13.360
Because if we do that we won't have to change anything else.

02:13.360 --> 02:18.070
We just have to execute a gameplay cue, which means we'll have to make one.

02:18.070 --> 02:19.510
But we'll get to that.

02:19.510 --> 02:20.260
For now.

02:20.260 --> 02:26.770
I'm going to make on hit an aura projectile, a virtual function, and then we can override this virtual

02:26.770 --> 02:29.170
function in Aura Fireball.

02:29.170 --> 02:34.420
So I'm going to go to Aura Fireball dot h in the protected section as this is a protected function.

02:34.420 --> 02:42.250
And I'm going to override on hit and now or a fireball can implement its own definition for this.

02:42.250 --> 02:48.850
And whatever we do by the end of it I'm going to set be hit to true, just like we did in aura projectile

02:48.850 --> 02:49.630
right here.

02:49.630 --> 02:54.940
The only difference is the way we're going to handle these things right now.

02:54.940 --> 02:57.370
We want to stop the looping sound component.

02:57.370 --> 02:57.790
Yes.

02:57.790 --> 03:02.140
So I'm going to copy that part and put that in the aura of fireball version.

03:02.140 --> 03:05.020
And of course looping sound component is private.

03:05.020 --> 03:10.960
So if we're going to use looping sound component in a child class that has to be protected as well,

03:10.990 --> 03:12.430
no problem.

03:13.060 --> 03:19.840
We can take looping sound component, we can cut it from the private section and paste it into the protected

03:19.840 --> 03:20.440
section.

03:20.440 --> 03:27.610
And now our fireball should be able to access it, provided that it includes the correct header file.

03:27.610 --> 03:33.070
Well, we can steal that from our projectile that CPP its audio component.

03:34.450 --> 03:39.280
So we can paste that up here and we should be good to go.

03:39.890 --> 03:40.610
All right.

03:40.610 --> 03:44.180
So on head is overridden and we're stopping the looping sound.

03:44.180 --> 03:47.000
But how do we execute a gameplay cue.

03:47.030 --> 03:52.460
Well, first of all we need to know what the gameplay cue tag is because gameplay cues are executed

03:52.460 --> 03:53.630
by tag.

03:53.660 --> 04:00.020
So for this particular gameplay cue that we're going to create for Fire Blast, we can make a gameplay

04:00.020 --> 04:03.320
cue tag by going to our gameplay tags.

04:03.320 --> 04:04.760
I'm going to do that.

04:05.240 --> 04:09.200
We have most of our gameplay cue tags made inside the engine.

04:09.200 --> 04:13.850
In fact, all of them are made that way, but this one we want to use in C Plus plus.

04:13.850 --> 04:22.640
So I'm going to make a native gameplay tag, and I'm going to call this gameplay cue underscore fire

04:22.640 --> 04:23.660
blast.

04:24.550 --> 04:28.870
And we'll go ahead and define Fireblast in our gameplay tags.

04:28.870 --> 04:33.100
I'm just going to copy one of these and go all the way down to the bottom.

04:33.970 --> 04:43.360
Make a comment that says gameplay queue and paste this and we'll use gameplay queue Fireblast.

04:44.460 --> 04:45.960
And it's going to be gameplay.

04:45.960 --> 04:47.700
Q dot.

04:49.010 --> 04:50.390
Fire blast.

04:51.390 --> 04:57.870
And we'll say fire blast gameplay cue tag.

04:57.870 --> 05:01.620
Now that we have that, we can close our gameplay tags.

05:01.620 --> 05:02.490
We're done with it.

05:02.490 --> 05:07.050
And here in on hit, we'd like to execute a gameplay cue locally.

05:07.050 --> 05:11.400
So how are we going to execute a local gameplay cue?

05:11.850 --> 05:19.860
Well, if we search for gameplay cue manager and we and we go to gameplay cue manager dot H, we can

05:19.860 --> 05:24.030
scroll down and see that there are a number of functions that are very useful.

05:24.620 --> 05:27.470
Here are three static functions right here.

05:27.830 --> 05:32.270
We can add, remove or execute gameplay cues locally.

05:32.600 --> 05:34.220
Non replicated.

05:35.330 --> 05:41.480
Now remember adding is for adding a instance gameplay cue, something that you add to an actor, whereas

05:41.480 --> 05:48.530
executing is just executing something that's either static, a gameplay cue, notify, burst, etc..

05:48.800 --> 05:56.240
Now I'd like to make a burst notify, so I'm going to use execute gameplay cue non replicated, which

05:56.240 --> 06:00.710
requires a target, a gameplay cue tag and some parameters.

06:00.710 --> 06:04.250
Now our fireball needs to know the target.

06:04.250 --> 06:08.300
And that target has to have an ability system component.

06:08.300 --> 06:12.950
Either it's the avatar actor or the owner actor and so on.

06:12.950 --> 06:16.250
Now our fireball could have an owner.

06:16.250 --> 06:22.010
If we set it, we could get the ability system component from damage effect params, but we're not really

06:22.010 --> 06:23.900
setting that on clients.

06:23.900 --> 06:27.500
We're setting that on the server when we spawn this thing.

06:27.500 --> 06:31.820
Now, how do we set something that the clients will know about?

06:31.820 --> 06:34.340
Well, the owner of all actors is replicated.

06:34.340 --> 06:40.640
So if we go back to our gameplay ability where we're spawning these fireballs, we can set the owner

06:40.640 --> 06:42.800
there or make sure that we're doing so.

06:42.800 --> 06:48.230
Let's go to Aura Fire Blast and go to where we're spawning these fireballs.

06:48.230 --> 06:50.540
We're setting the damage effect params.

06:50.540 --> 06:52.910
We're even setting the return to actor.

06:52.910 --> 06:56.300
We could also set the owner as well.

06:56.360 --> 07:01.610
We can take fireball and call set owner.

07:02.740 --> 07:09.010
And we can simply use the avatar actor from the actor info if we want that to be the owner.

07:09.010 --> 07:13.930
And if we have this set, the owner on all actors is replicated.

07:13.930 --> 07:19.330
So the fireball is going to know on the client who its owner is.

07:19.330 --> 07:25.930
However, we need to make sure that's a valid pointer just in case on hit gets called before that replication

07:25.930 --> 07:29.290
happens, which is unlikely but possible.

07:30.250 --> 07:34.300
So we're going to check if get owner if that's a valid pointer.

07:34.300 --> 07:40.960
And then we can call that static function on gameplay queue manager execute gameplay queue non replicated.

07:41.410 --> 07:44.140
So we're going to get you gameplay queue manager.

07:46.210 --> 07:49.210
Make sure that we have the header file included for that.

07:53.050 --> 08:00.040
So there it is, gameplay queue manager and we can call execute gameplay queue non replicated passing

08:00.040 --> 08:01.000
in the actor.

08:01.000 --> 08:07.030
We're going to use Get owner the gameplay tag we can use for gameplay tags.

08:07.420 --> 08:09.550
Gameplay queue Fireblast.

08:10.410 --> 08:13.500
Now the third parameter is gameplay cue parameters.

08:13.500 --> 08:17.430
We've seen gameplay cue parameters in the editor and blueprint.

08:17.430 --> 08:21.690
This is just an f gameplay cue parameter struct, so we can make one.

08:21.690 --> 08:28.560
We can make an f gameplay cue parameters called cue params, and I mentioned that I'd like this to be

08:28.560 --> 08:35.940
a burst notify, and the burst notify will spawn particles at the location in the cue parameters, so

08:35.940 --> 08:40.860
we can set cue params dot location and we're inside the fireball.

08:40.860 --> 08:42.930
I'm just going to call get actor location.

08:43.980 --> 08:46.560
And we can pass in those Q params.

08:50.810 --> 08:53.030
Now it looks like I made a typo here.

08:53.030 --> 08:54.680
This is for a gameplay tags.

08:54.680 --> 08:58.880
It should be get dot gameplay q fireblast.

08:58.880 --> 09:01.340
So typing a little too hastily there.

09:01.760 --> 09:04.310
But with that we have our gameplay Q params.

09:04.310 --> 09:09.500
We've set the location on it and we're executing gameplay Q non replicated.

09:09.500 --> 09:14.030
With this we can just compile and make our gameplay Q.

09:15.200 --> 09:16.670
Okay, so we're back.

09:16.700 --> 09:19.700
Now the next thing to do is create a gameplay queue.

09:19.700 --> 09:21.680
So I'm going to go to the ability system.

09:21.680 --> 09:25.700
Gameplay cue notifies folder and create a new one.

09:26.310 --> 09:30.000
So we'll go to blueprint gameplay cue.

09:30.000 --> 09:31.170
Notify.

09:31.810 --> 09:38.200
GCN burst and this will be called GC underscore fireblast.

09:38.590 --> 09:42.160
Let's open up GC Fireblast now because I called it Fireblast.

09:42.190 --> 09:44.830
Look at this gameplay queue tag.

09:44.860 --> 09:46.810
Gameplay queue Fireblast.

09:47.140 --> 09:48.370
How amazing!

09:48.370 --> 09:54.580
Now let's go to our burst effects and click plus for burst particles and let's select one.

09:54.580 --> 10:01.930
Now remember we have an explosion and we have nice fire explosion and fire explosion one I'm going to

10:01.930 --> 10:03.460
use fire explosion.

10:03.460 --> 10:05.110
It's this one here.

10:07.420 --> 10:08.890
So that's going to do.

10:08.980 --> 10:11.170
And now for the burst sounds.

10:12.060 --> 10:17.280
We can add one of these and we have an impact sound.

10:17.280 --> 10:19.230
It's called Firebolt Impact.

10:19.230 --> 10:21.150
And that's what this sounds like.

10:23.430 --> 10:25.890
That's the sound our firebolts have been making.

10:27.190 --> 10:36.070
So now that we have burst particles and we have burst sounds, we can go ahead and test out executing

10:36.070 --> 10:37.930
these gameplay queues locally.

10:40.440 --> 10:45.390
So we'll try on the server in a single player game, I'm going to press two.

10:47.480 --> 10:50.300
There's our gameplay cue executing.

10:50.300 --> 10:51.020
Looks good.

10:51.020 --> 10:52.700
Looks like we leveled up to.

10:55.400 --> 10:58.970
Now I'm going to change the number of players to two and press play.

11:02.450 --> 11:03.230
Boom!

11:03.230 --> 11:05.000
We even knocked aura away.

11:05.000 --> 11:06.200
Pretty exciting.

11:06.200 --> 11:07.670
So that worked on the client.

11:07.670 --> 11:14.240
We can even play as client with a dedicated server, and it doesn't matter which of these we use.

11:17.630 --> 11:21.410
And we get our cues, so we're executing gameplay cues locally.

11:22.030 --> 11:29.590
And this is great because this does not result in any rpcs, as gameplay cues by default are multicast

11:29.590 --> 11:30.610
rpcs.

11:30.610 --> 11:35.140
And that can be really expensive bandwidth wise.

11:35.530 --> 11:39.820
If we're doing this a lot and this particular ability has 12.

11:40.380 --> 11:49.140
12 gameplay cues being executed, but they're executed locally, so no information is sent across the

11:49.140 --> 11:49.770
server.

11:49.770 --> 11:57.030
This is actually really useful, and we now know that the gameplay queue manager has static functions

11:57.030 --> 12:02.400
to execute these to make things easy for us, so use these when you can.

12:02.520 --> 12:06.570
If something's already replicated, use local gameplay cues.

12:06.570 --> 12:13.620
If something is already predicted with a gameplay ability, use local gameplay cues only in the situation

12:13.620 --> 12:18.690
where you're not already replicating something and you need that effect replicated.

12:18.690 --> 12:26.580
Do you want to use a replicated queue in all other cases where you can execute them locally?

12:27.860 --> 12:28.700
All right.

12:28.700 --> 12:30.890
That's going to conclude this video.

12:30.890 --> 12:32.060
Excellent job.

12:32.090 --> 12:40.160
You now have another tool in your tool belt to make your games more optimal, more performant and especially

12:40.160 --> 12:41.180
in multiplayer.

12:41.210 --> 12:42.230
Excellent job.

12:42.230 --> 12:43.400
And I'll see you soon.
