WEBVTT

00:06.820 --> 00:08.140
Welcome back.

00:08.470 --> 00:13.450
So we have our custom service and so far it doesn't do a whole lot for us.

00:13.450 --> 00:15.220
It just prints a debug message.

00:15.220 --> 00:17.410
Now I'd like to gather information.

00:17.410 --> 00:21.640
I'd like to find the nearest player and then we can set variables.

00:21.640 --> 00:24.310
Now where do we store these variables.

00:24.310 --> 00:26.830
Are they going to be on the service itself?

00:26.830 --> 00:30.190
Well no the service is not where we store variables.

00:30.430 --> 00:32.650
Is it going to be on the behavior tree itself?

00:32.650 --> 00:36.730
Well actually no, the behavior tree doesn't store variables either.

00:36.730 --> 00:43.240
What we do is we designate a specific asset to store the variables that the behavior tree will use,

00:43.240 --> 00:45.640
and that asset is the blackboard.

00:45.640 --> 00:52.270
Let's click on that blackboard tab and we'll see that right here we have all the keys right under the

00:52.270 --> 00:53.920
keys category.

00:53.920 --> 00:56.290
So there's a reason it's called the blackboard.

00:56.290 --> 01:04.750
Blackboard also known as chalkboard is what you would see in a typical old school classroom where the

01:04.750 --> 01:09.700
instructor is putting things on the blackboard with a piece of chalk.

01:09.820 --> 01:16.690
Think of this as a chalkboard used by the behavior tree, where we can put variables and their values,

01:16.690 --> 01:18.670
and we can update those values.

01:18.820 --> 01:23.620
The behavior tree has access to the blackboard that it's associated with.

01:23.620 --> 01:31.330
And here in the behavior tree we can access those values and behave based on what those values are.

01:31.750 --> 01:35.950
By default the blackboard has a self actor.

01:36.070 --> 01:41.740
Self actor is a blackboard key and the key type is object.

01:41.740 --> 01:43.750
But we can change the key type.

01:43.870 --> 01:51.040
If we click the dropdown, we'll see that there are a lot of different types that our keys can be of,

01:51.040 --> 01:57.460
and we can even pass in the values of keys into our nodes on our blackboard.

01:57.460 --> 02:05.500
For example, find nearest player could have a variable of type blackboard key if we wanted to and we

02:05.500 --> 02:06.760
can pass it in here.

02:06.760 --> 02:10.840
We can take one of our blackboard keys and pass it straight in.

02:10.840 --> 02:16.330
The way we would do that is we would go into our service blueprint and add a variable.

02:16.330 --> 02:24.550
And we can call this self actor key and change its type to key.

02:24.550 --> 02:27.970
And the type is actually blackboard key selector.

02:27.970 --> 02:31.180
If we choose blackboard key selector for the type.

02:31.180 --> 02:39.190
And we open the eye icon here and compile, then all of a sudden this self actor key variable, if we

02:39.190 --> 02:46.930
go back to our blackboard, is something that we can set on this particular node that we've attached

02:46.930 --> 02:47.830
to our selector.

02:47.830 --> 02:49.780
Here it is in the details panel.

02:49.780 --> 02:51.610
It's self actor key.

02:51.610 --> 02:56.230
And we can set it to one of our key values in our blackboard.

02:56.230 --> 03:01.360
Now if we expand the dropdown we see that there's only one option that we can set for this.

03:01.360 --> 03:10.000
And it's the self actor that we have now if we have this set then we can use it here in our service.

03:10.000 --> 03:17.770
If I take my self actor key and get it and then drag off of it, we can get the value stored in that

03:17.770 --> 03:19.480
blackboard key selector.

03:19.510 --> 03:25.480
Now we don't know what self actor key is we actually do because we know that we're setting it equal

03:25.480 --> 03:27.790
to self actor which has the object type.

03:27.790 --> 03:31.450
But really this behavior tree service doesn't know that.

03:31.450 --> 03:37.750
But we can drag off of self actor key and type get blackboard value as.

03:37.750 --> 03:43.540
And notice we can get the blackboard value as any of these types that a key can be.

03:43.540 --> 03:50.440
So if we choose object which we know this is the type, then we're accessing the value stored in that

03:50.440 --> 03:50.860
key.

03:50.860 --> 03:58.840
If it's set now because this is an object we can drag off and type get object name, which is a blueprint

03:58.840 --> 04:02.890
function node we can get and we can print this string here.

04:02.890 --> 04:05.290
And why don't we just see what it says.

04:05.290 --> 04:11.590
If we press play then we can see goblin spear and goblin slingshot printed to the screen.

04:11.590 --> 04:13.510
Now what does this tell us?

04:13.510 --> 04:20.410
This tells us that we automatically have a key in our blackboard called Self Actor.

04:20.410 --> 04:22.240
And what is it set to?

04:22.240 --> 04:28.330
Well, it's set to the character, the character associated with this behavior tree.

04:28.630 --> 04:31.990
So at least we already have one blackboard key.

04:31.990 --> 04:39.250
And we now know that we can add a variable of type blackboard key selector to a behavior tree service

04:39.250 --> 04:43.810
blueprint and expose that to the details panel.

04:43.810 --> 04:49.150
And if we do that then we can set the value based on one of our blackboard keys.

04:49.150 --> 04:50.740
So that's kind of cool.

04:50.740 --> 04:57.310
But because I don't need that right now I'm going to go ahead and just remove all that and remove self

04:57.310 --> 04:59.620
actor key compile and save.

04:59.620 --> 05:03.520
And I'll come back and see that that's no longer in the details panel there.

05:03.790 --> 05:06.070
I really don't need to pass self actor.

05:06.380 --> 05:08.300
And to find nearest player.

05:08.300 --> 05:13.760
What I really want is for find nearest player to do its job.

05:13.760 --> 05:18.200
Find the nearest actual character controlled by a human player.

05:18.200 --> 05:18.800
Right?

05:19.250 --> 05:24.950
And once I find that player, I'd like to set the value of one of my blackboard keys, but not self

05:24.950 --> 05:25.670
actor.

05:25.670 --> 05:32.690
I want a blackboard key for a target for this particular AI character to follow.

05:32.720 --> 05:39.800
I'd like a blackboard key based on object that I can move towards and potentially attack.

05:39.800 --> 05:43.190
So I'm going to add a new key to my blackboard.

05:43.190 --> 05:47.480
And I go back to my blackboard tab to do that and click on New Key.

05:47.480 --> 05:49.280
And I can choose the type for it.

05:49.280 --> 05:50.990
It's going to be object.

05:50.990 --> 05:56.120
And this object I'd like to call target to follow.

05:56.330 --> 05:58.640
And we see that its key type is object.

05:58.640 --> 06:01.100
Now notice key type has a drop down.

06:01.100 --> 06:06.950
And for the base class we can change it from object to really any base class we like.

06:06.950 --> 06:13.310
And that would make this act kind of like a subclass of it'll restrict it to that type or lower in the

06:13.310 --> 06:14.210
hierarchy.

06:14.480 --> 06:16.070
And we can choose actor.

06:16.070 --> 06:21.560
And I'd like to choose actor for target to follow so that we can only follow actors.

06:21.560 --> 06:28.430
And there are certain things in our behavior tree that we can do with actors that we can't do with objects,

06:28.430 --> 06:30.380
and we'll learn about those soon.

06:30.710 --> 06:36.980
Now, if we were to check this one instance synced, then that would mean that this field would be synchronized

06:36.980 --> 06:39.440
across all instances of this blackboard.

06:39.440 --> 06:45.710
Now we have multiple enemies, potentially all using this blackboard and instance synced would make

06:45.710 --> 06:48.380
this variable shared among all of them.

06:48.380 --> 06:52.820
If one of them sets it, then all of them have access to that same variable.

06:52.940 --> 06:58.940
But if it's unchecked, then each instance of the blackboard has its own version of that variable.

06:59.360 --> 07:02.510
So now we have a target to follow blackboard key.

07:02.540 --> 07:07.610
I'd also like another key for the distance to that target.

07:07.610 --> 07:09.860
And that's going to be a float key.

07:09.860 --> 07:17.090
I'm going to call this one distance to target because I'd like to set that as soon as I find the nearest

07:17.090 --> 07:17.780
player.

07:17.780 --> 07:20.330
And then we can act based on distance.

07:20.330 --> 07:26.750
So now that we have these keys, we can flesh out what our behavior tree service does, how it actually

07:26.750 --> 07:28.220
finds the nearest player.

07:28.220 --> 07:35.330
So back here in our behavior tree service, the first step to finding the nearest player is getting

07:35.330 --> 07:36.320
all players.

07:36.320 --> 07:44.630
Now if I'm going to say get all actors of a certain class, maybe it's the character class, for example,

07:44.630 --> 07:50.090
that's going to include all actors of the character class, including all the enemies.

07:50.090 --> 07:55.760
But we want only those characters that are controlled by a human player.

07:56.030 --> 07:58.040
So how do we make that distinction?

07:58.580 --> 08:05.000
Well, one way is through tags, and I'm not talking about gameplay tags like what we've been using,

08:05.000 --> 08:11.240
but there are actor tags that are basically set with f names on actors.

08:11.450 --> 08:18.320
We can identify actors with actor tags pretty easily, and these tags are exposed to the details panel

08:18.320 --> 08:21.830
for all actors, and we can set those tags.

08:21.830 --> 08:30.260
I can go into blueprints into character, and I can open BP enemy base, and in the details panel I

08:30.260 --> 08:32.120
can simply search for tags.

08:32.120 --> 08:38.750
Now here we have under advanced tags, it says an array of tags that can be used for grouping and categorizing.

08:38.990 --> 08:43.400
So these are almost as useful as gameplay tags but they're a little more simple.

08:43.400 --> 08:45.200
They're based on f names.

08:45.200 --> 08:48.230
If we click plus we can add one of these.

08:48.230 --> 08:53.270
For example the base enemy class could just have the tag enemy.

08:53.870 --> 08:56.330
And we can always check an actor for its tags.

08:56.330 --> 08:59.720
We don't have to cast to Ora enemy or anything like that.

08:59.720 --> 09:01.760
We can just check the actor tags.

09:01.760 --> 09:04.340
So this makes it really nice and useful.

09:04.340 --> 09:09.710
And if we want to distinguish between, say, Ora and any of the enemies, the enemies could have the

09:09.710 --> 09:13.910
enemy tag and Ora could have, say, a player tag.

09:13.910 --> 09:21.860
So I can open BP Ora character and search for tags, and I can add a tag for Ora and this can be player.

09:21.860 --> 09:27.500
Then by checking these tags, we always know if we're dealing with an enemy or if we're dealing with

09:27.500 --> 09:28.100
Ora.

09:28.100 --> 09:31.220
So after doing that I'm going to save all.

09:32.450 --> 09:36.650
So here is where we're going to try to find the nearest player.

09:36.770 --> 09:42.440
Before we do, I'm going to add a couple of variables to this behavior tree task.

09:42.440 --> 09:50.690
And the type for these variables is going to be blackboard key selector.

09:50.720 --> 09:55.190
This is a struct for generic blackboard keys.

09:55.190 --> 09:57.320
So we have a blackboard key selector.

09:57.320 --> 10:02.300
The first one is going to be called target to follow.

10:03.850 --> 10:05.710
Underscore selector.

10:05.860 --> 10:09.130
So we have a target to follow blackboard key selector.

10:09.130 --> 10:15.220
We're going to add another one called distance to target selector.

10:15.400 --> 10:21.130
This will allow us to make a link between this service and our blackboard keys.

10:21.130 --> 10:25.900
So we have those for whenever we find the nearest player.

10:25.900 --> 10:33.970
But the player may not be an aura if this behavior tree belongs to a pet that's following aura around,

10:33.970 --> 10:38.410
well, it's nearest player from its perspective may be an enemy.

10:38.410 --> 10:46.690
So now that we have tags on both aura and on enemies that we can use to identify whether they're players

10:46.690 --> 10:53.230
or enemies, we can find all actors with one of the two tags, either player or enemy.

10:53.230 --> 11:01.300
If our controlled pawn is a player as or as pet would have in that hypothetical case, then we'd want

11:01.300 --> 11:03.310
to find all actors with the enemy tag.

11:03.310 --> 11:10.540
But if the controlled pawn has the enemy tag, we'd like to find all actors with the player tag and

11:10.540 --> 11:11.020
so on.

11:11.020 --> 11:18.160
So what we can do is have a tag for the target of this AI controlled pawn.

11:18.160 --> 11:19.840
We can add a new variable.

11:19.840 --> 11:24.760
We can call it target tag, but this can be an F name.

11:24.760 --> 11:31.270
Because these actor tags are implemented as f names, they're simpler than gameplay tags and we can

11:31.270 --> 11:33.970
check our controlled pawn.

11:34.330 --> 11:37.360
We can see if it has a tag we can use.

11:37.360 --> 11:39.970
The function actor has tag.

11:40.740 --> 11:47.880
Now, if the actor has the tag player, then the target tag is going to be enemy.

11:47.880 --> 11:53.280
So let's put a branch here and we'll set target tag to enemy.

11:54.640 --> 12:01.780
Otherwise the actor does not have the player tag, and we'll just assume that it has the enemy tag and

12:01.780 --> 12:08.380
its target tag will be player, which is the case for our goblins, right?

12:08.620 --> 12:14.710
So this could be collapsed to a function and we can call this set target tag.

12:16.210 --> 12:23.260
And the input parameter is going to be what this input is controlled pawn.

12:23.260 --> 12:26.380
So the first thing we do is we set the target tag.

12:26.380 --> 12:32.020
Then all we have to do is find all actors with the tag we can use.

12:32.020 --> 12:35.110
Get all actors with tag.

12:35.660 --> 12:37.370
Passing in the target tag.

12:37.370 --> 12:41.990
And this gives us an array of all the actors that have this tag.

12:42.170 --> 12:46.730
Now, if this eye is an enemy, this will be all the players.

12:46.850 --> 12:50.720
And if this eye is a player, this will be all the enemies.

12:50.990 --> 12:54.770
So we can prove this with a for each loop.

12:54.770 --> 12:57.890
And in the for each loop we'll take the array element.

12:57.890 --> 13:04.850
We'll call get object name, and we'll print that name just to prove that this array contains what we

13:04.850 --> 13:06.350
think it contains.

13:06.380 --> 13:11.900
In the case of a game where there's one aura, we'll see one aura printed to the screen.

13:11.930 --> 13:17.810
Of course we'll see three messages because we have three goblins every 0.5 seconds.

13:17.810 --> 13:18.800
Let's check it out.

13:19.650 --> 13:20.760
There we go.

13:20.760 --> 13:24.090
All of them are finding aura perfect.

13:24.090 --> 13:26.520
So that's as expected.

13:26.520 --> 13:31.050
We now have all actors with the target tag.

13:31.050 --> 13:37.920
The next thing we need to do is find the nearest of these actors, and we'll implement that algorithm

13:37.920 --> 13:38.730
next.

13:39.360 --> 13:40.320
I'll see you soon.
