WEBVTT

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

00:08.130 --> 00:10.410
So now we have our enemies.

00:10.440 --> 00:15.570
They're doing something, but we definitely want them to do more, Right?

00:15.570 --> 00:22.660
So we're going to continue and I'm going to start by opening up my behavior tree.

00:22.680 --> 00:28.380
So I'm going to go to blueprints I and open my enemy behavior tree here.

00:28.590 --> 00:36.510
Now we have a service find nearest player and it's setting the values of a couple of our blackboard

00:36.510 --> 00:38.760
keys every half second or so.

00:39.090 --> 00:45.150
And we can use those blackboard key values to determine what we should do next.

00:45.360 --> 00:49.540
Now, what I'd like to do is start using some decorators.

00:49.560 --> 00:57.120
Decorators can also be attached to nodes and they can provide us with conditions.

00:57.120 --> 01:05.370
Kind of like if statements that can allow us to execute a given branch or prevent the execution of a

01:05.370 --> 01:08.290
given branch, depending on those conditions.

01:08.560 --> 01:14.920
So I'm going to get rid of this move to Node, just highlight it and delete it and I'd like another

01:14.920 --> 01:15.580
selector.

01:15.580 --> 01:24.490
So I'm going to drag off, search for selector and add one and I can add a decorator to this selector

01:24.490 --> 01:29.620
by right clicking add decorator and choosing blackboard.

01:30.120 --> 01:36.810
Now I have this blue thing connected to my selector that says blackboard based condition, and we can

01:36.810 --> 01:41.190
prevent going into this selector based on a condition.

01:41.220 --> 01:43.740
The condition is based on a blackboard key.

01:43.740 --> 01:48.390
And if we choose that key under blackboard key, we can set it to something.

01:48.630 --> 01:51.480
I'd like to set it to target to follow.

01:51.660 --> 01:56.040
And key query can be is set or is not set.

01:56.070 --> 02:03.120
If it's set to is set, then target to follow must be set in order for us to execute this selector.

02:03.120 --> 02:10.590
So if I have children hooked up to the selector, then they will only be executed if target to follow

02:10.590 --> 02:11.430
is set.

02:11.460 --> 02:19.980
Now notify Observer says that when the result of this evaluation checking target to follow, if that

02:19.980 --> 02:26.430
is changed when we're evaluating it, then we will not enter this selector.

02:26.460 --> 02:31.000
We will fail and return failure back up to the parent.

02:31.470 --> 02:35.220
Now we could change notify observer to on value change.

02:35.220 --> 02:41.700
And that means if we've already made it past this decorator at some point, if target to follow becomes

02:41.700 --> 02:45.810
unset, then this node could abort itself.

02:45.810 --> 02:53.370
Depending on the observer aborts selection, it could abort the self, it could abort only lower priority

02:53.400 --> 02:55.770
nodes and nodes have priority.

02:55.770 --> 03:02.850
We can see them with these little numbers connected to each node and it can abort both, but we're going

03:02.850 --> 03:08.580
to set it to none and leave this on set to on result change for notify observer.

03:08.580 --> 03:17.070
All I care about is preventing the execution of the selector if target to follow is not set and if we

03:17.070 --> 03:20.220
make it past this first selector, it should be set.

03:20.250 --> 03:23.550
That's why I'm checking it after this selector.

03:23.550 --> 03:30.330
If I attach this decorator to this selector up here, then we would never get to set it because it would

03:30.330 --> 03:37.210
never be set in the first place and the decorator would prevent this service from being run.

03:37.240 --> 03:45.400
So we have a decorator that checks to make sure we have a target to follow, and then it can execute

03:45.400 --> 03:47.410
its children left to right.

03:47.560 --> 03:51.160
Now, I'd like to also check another condition.

03:51.160 --> 03:54.130
I'd like to see if our enemy is hit reacting.

03:54.130 --> 03:57.640
Now, that's not a blackboard key, but we can easily add one.

03:57.640 --> 04:05.080
Let's go to our blackboard and add a new key of type bool and this one can be hit reacting.

04:05.350 --> 04:08.140
So we have this blackboard key hit reacting.

04:08.140 --> 04:11.410
Now this should be false by default.

04:11.440 --> 04:15.930
We want to set it to true when hit reacting and false when we're not.

04:15.940 --> 04:17.890
So how can we do that?

04:18.070 --> 04:25.330
Well, we can do this from C plus plus if we can get a hold of the aura AI controller which has access

04:25.330 --> 04:30.610
to the blackboard component blackboard components can set their blackboard values.

04:31.050 --> 04:39.060
So I'm going to close the editor and save and I'm going to open up my character folder and open Aura

04:39.060 --> 04:42.480
Enemy, and I'll get that header file open as well.

04:42.510 --> 04:45.540
Now we have our Aura AI controller here.

04:45.630 --> 04:50.160
As soon as we have this set, I'd like to set the blackboard value of that hit.

04:50.160 --> 04:55.830
Reacting key to false just so we make sure that it's set explicitly.

04:56.130 --> 05:00.240
So I'm going to search in the CPP file for aura AI controller.

05:00.240 --> 05:05.730
We're setting it here in possessed by and after we run the behavior tree, we can get our blackboard

05:05.730 --> 05:06.720
component from it.

05:06.750 --> 05:12.930
We're going to say Aura AI controller, get blackboard component and from the blackboard component we

05:12.930 --> 05:20.340
can set a value as boolean by calling the function set value as bool.

05:20.550 --> 05:23.610
It takes a name and it's called key name.

05:23.640 --> 05:27.780
We're going to pass in the name of hit reacting.

05:28.830 --> 05:31.050
And we're going to set this to false.

05:31.470 --> 05:35.220
And we also want to set this if we're hit, reacting.

05:35.220 --> 05:39.350
So we have a couple of callback functions for when we're hit reacting.

05:39.360 --> 05:41.490
If we scroll down, we'll see.

05:41.490 --> 05:43.710
We have hit react tag changed.

05:43.710 --> 05:51.300
So it's actually one callback and we're setting max walk speed based on be hit reacting we can also

05:51.300 --> 05:58.650
set that key so I'm going to control V and paste this line where we're setting value as bool and we're

05:58.650 --> 06:03.720
going to set hit, reacting equal to the value of be hit reacting.

06:03.720 --> 06:10.830
So every time we're hit, reacting or no longer hit reacting, we should be setting the blackboard key

06:10.860 --> 06:14.460
hit reacting so I can go ahead and hit the debug button.

06:15.670 --> 06:18.190
And we can get that blackboard back open.

06:18.190 --> 06:23.200
We can go into the behavior tree and we can check that hit Reacting Boolean.

06:23.290 --> 06:25.990
I'd like to add another decorator.

06:25.990 --> 06:30.160
So I'm going to right click add decorator, select Blackboard.

06:30.160 --> 06:35.590
And this second one is going to be checking our hit Reacting key.

06:35.590 --> 06:38.890
But this time key query should be is not set.

06:38.890 --> 06:43.930
I want to enter this branch if hit, reacting is not set.

06:43.930 --> 06:45.490
In other words, false.

06:45.540 --> 06:52.840
We're going to set that blackboard key to hit reacting Now I would like to abort the self if hit reacting

06:52.840 --> 06:54.010
becomes true.

06:54.010 --> 07:00.820
So for observer aborts, I'm going to set this to self and change notify observer to on value change.

07:00.820 --> 07:07.330
So any nodes that we have going on down here will stop if hit reacting becomes true.

07:07.360 --> 07:14.710
So now that we have a couple of decorators, we can start thinking about how we're going to make our

07:14.710 --> 07:23.720
enemy move toward the character and also attack the character, I'd like to have several different cases.

07:23.720 --> 07:26.900
I'd like to have a case for our ranged attackers.

07:26.900 --> 07:32.660
I'd like them to stop just short a little distance away before they start attacking.

07:32.780 --> 07:38.060
I'd like to have a separate case for non ranged attackers that want to get close.

07:38.090 --> 07:45.620
And in order to know that I need a blackboard key that can tell me if I have arranged attacker or not.

07:45.620 --> 07:54.440
So we're going to add one last blackboard key of type bool and this is going to be ranged attacker.

07:54.740 --> 08:02.480
And this we can also set from within C plus plus and we can check whether or not we have a ranged attacker

08:02.480 --> 08:03.890
from our selector.

08:03.890 --> 08:07.610
We can drag off and add more nodes.

08:07.610 --> 08:13.880
Now we have selectors up here, but we also have the option to make a sequence node, which is just

08:13.880 --> 08:17.090
like a selector only it has one key difference.

08:17.120 --> 08:22.100
A selector executes children from left to right until one of them succeeds.

08:22.130 --> 08:26.570
A sequence executes children from left to right until one of them fails.

08:26.570 --> 08:32.060
So I'm going to have a sequence here and I'm going to put a little comment here and say, for ranged

08:32.060 --> 08:34.430
attackers or just ranged attacker.

08:34.550 --> 08:38.120
So we'll have some nodes and some logic here.

08:38.120 --> 08:41.030
I'm going to have another sequence here.

08:41.030 --> 08:43.490
And this is going to be for melee attackers.

08:43.490 --> 08:51.200
So I'm going to comment this and say melee attacker, and we'll check first if we're arranged attacker.

08:51.230 --> 08:53.990
If not, we'll continue, Right.

08:53.990 --> 09:00.440
If this fails, we have a selector up here which will go from left to right until one of its children

09:00.440 --> 09:01.520
succeeds.

09:01.520 --> 09:02.840
So this will fail.

09:02.840 --> 09:09.500
So it will continue if this fails based on whatever decorators we put here, Perhaps the enemy isn't

09:09.500 --> 09:11.090
close enough to attack yet.

09:11.120 --> 09:14.330
Then we can have one last sequence over here.

09:14.720 --> 09:18.770
And this one is going to be for moving to the target.

09:18.770 --> 09:23.690
So this one, I'm going to have a comment that says Move to Target.

09:23.690 --> 09:27.980
And each of these will be able to fail based on whatever conditions we set.

09:28.310 --> 09:30.860
So we're going to flesh this out more.

09:30.860 --> 09:35.000
But first, I'd like my ranged attacker key to be set.

09:35.000 --> 09:37.130
So I'm going to set that from C plus plus.

09:37.130 --> 09:43.130
I'm going to go ahead and save the project and we'll go ahead and check our class to see if we're a

09:43.130 --> 09:45.110
ranged attacker or not.

09:45.110 --> 09:49.130
And we'll do that as soon as our AI controller is set.

09:49.430 --> 09:51.710
That's going to be here and possessed by.

09:52.160 --> 09:59.150
So I'm going to say if and we're going to check the character class, we're going to see if it's equal

09:59.150 --> 10:05.240
to a character class and our ranger is going to be a ranged attacker.

10:05.240 --> 10:12.650
But also our elementalist is going to have ranged attacks as well, think fireballs and things like

10:12.650 --> 10:13.310
that.

10:13.310 --> 10:16.850
So I'm going to consider both of these to be ranged attackers.

10:16.850 --> 10:19.640
So we'll really say, is it a warrior?

10:19.640 --> 10:21.590
In fact, we'll say is it not a warrior?

10:21.590 --> 10:24.980
Is character class not equal to warrior?

10:24.980 --> 10:27.350
If so, it's a ranged attacker.

10:27.500 --> 10:32.060
And we can call this line here set value as bool.

10:32.060 --> 10:34.190
In fact, we could just call it here.

10:34.220 --> 10:35.900
No need for an if statement.

10:35.930 --> 10:46.640
This right here character is not warrior is sufficient and the key is going to be ranged attacker.

10:48.800 --> 10:51.820
So we'll set ranged attacker equal to this value.

10:51.830 --> 10:56.870
If it's a warrior, ranged attacker will be false, otherwise it will be true.

10:56.990 --> 10:59.240
So we can go ahead and compile that.

11:01.020 --> 11:04.370
So these are very general blackboard keys.

11:04.380 --> 11:08.220
They're not specific to any one class.

11:08.250 --> 11:11.490
They're general across the board for the whole game.

11:11.490 --> 11:15.360
So I think it's okay to call them out directly in code like that.

11:15.450 --> 11:20.880
So we have our ranged attacker and I want to check that here for this one.

11:20.940 --> 11:29.790
I want to place a decorator here choosing Blackboard and selecting that The key query will be is set,

11:29.820 --> 11:35.520
the blackboard key will be is ranged attacker or just ranged attacker and we'll leave the rest at their

11:35.520 --> 11:36.300
defaults.

11:36.300 --> 11:41.550
So we'll only enter this sequence if we're arranged attacker.

11:42.240 --> 11:48.360
Now, if this branch fails, then this selector will just not execute it and it'll try the next one.

11:48.390 --> 11:53.580
The next one is going to check to see if we're within attack range.

11:53.670 --> 11:55.950
So let's add a decorator here.

11:55.950 --> 12:00.880
We'll choose Blackboard and this one will check our distance to Target.

12:00.960 --> 12:04.020
Now if we choose a float blackboard key.

12:04.050 --> 12:12.420
Now our key query is is equal to and a whole bunch of other options we're going to choose is less than.

12:13.160 --> 12:18.920
And we can have some kind of threshold, some close proximity value.

12:18.950 --> 12:20.930
We'll just use 500 for now.

12:20.930 --> 12:28.820
So if distance to target is less than 500, then we can get inside of this branch and then we can do

12:28.820 --> 12:30.140
our melee attack.

12:31.040 --> 12:32.840
So what if we fail that one?

12:32.840 --> 12:38.210
Well, if we're not arranged attacker and then we check and we're not within attack range.

12:38.210 --> 12:41.150
Well, that must mean we should be moving to the target.

12:41.150 --> 12:48.110
So in that case, we're going to move to the target so we can do a move to here.

12:48.110 --> 12:54.710
We can get the tasks and get moved to and move to our target to follow.

12:54.710 --> 13:00.740
So the blackboard key will be target to follow for this and we can give it a acceptance radius.

13:00.740 --> 13:02.450
I'll give it 50.

13:02.480 --> 13:03.980
So that's what we'll do.

13:03.980 --> 13:11.690
Now I'd like to have a little bit of a delay, not much, but a little bit of a hesitation before moving

13:11.720 --> 13:17.450
to the target so we can take our tasks and get a wait and select that and the wait time.

13:17.450 --> 13:21.440
I'd like to be zero plus or -0.5 seconds.

13:21.440 --> 13:27.680
So a random deviation of plus or -0.5 seconds before moving to the target.

13:27.710 --> 13:33.240
Now I only want to move to the target if we're close enough to approach.

13:33.240 --> 13:36.780
In other words, we're not super, super far away.

13:36.780 --> 13:38.940
So I'm going to add a decorator here.

13:39.120 --> 13:41.790
Decorator Blackboard.

13:41.790 --> 13:45.180
And for this I'm going to check my distance to Target.

13:45.180 --> 13:52.770
So Blackboard Key is distance to Target, and I'm going to check if it's less than or equal to some

13:52.770 --> 13:55.050
pretty big value, like 4000.

13:55.470 --> 14:00.330
So if we're far enough away to approach, we'll approach.

14:00.330 --> 14:07.110
But if we're too close, I want to fail out of this so we can try one of the others and try to attack

14:07.140 --> 14:07.740
again.

14:07.740 --> 14:16.170
In other words, I want to abort if the distance is too close, so I'm going to add another decorator.

14:17.490 --> 14:18.540
Blackboard.

14:18.540 --> 14:21.960
And for this I'm going to check the distance to target again.

14:21.960 --> 14:24.960
But this one will be is greater than or equal to.

14:24.960 --> 14:29.240
And this will be basically our sort of attack distance.

14:29.250 --> 14:35.250
It'll be about, let's say, 500 and we'll abort unless we're greater than or equal to.

14:35.280 --> 14:42.090
So we can actually change the node names on these to make it a little bit easier to understand.

14:42.360 --> 14:47.880
For this distance to target is greater than or equal to 500.

14:47.910 --> 14:52.200
This is are we far away enough to attack?

14:52.200 --> 14:56.040
Because if we're far enough away to attack, we should attack.

14:56.040 --> 15:03.330
So I'm going to rename this one to is far enough to attack.

15:03.600 --> 15:10.110
And this one is are we close enough to approach is the distance less than 4000?

15:10.110 --> 15:11.550
So this will say.

15:12.800 --> 15:15.860
Is close enough to approach.

15:16.220 --> 15:21.440
We can have question marks here as well, and we can even make it a little bit easier to understand.

15:21.440 --> 15:24.620
We can say, Am I close enough to approach?

15:24.620 --> 15:30.480
And here I can say, Am I far enough to attack?

15:30.500 --> 15:32.840
So we will move to the target.

15:32.840 --> 15:37.790
If we're closer than 4000 or equal, we will move to the target.

15:37.790 --> 15:42.590
If we're not too close, are we far away enough?

15:42.620 --> 15:47.920
It should actually say, am I close enough to attack or far enough to approach?

15:47.930 --> 15:55.340
Let's just say, am I far enough to approach trying not to make this too confusing With all the double

15:55.340 --> 15:57.070
negatives and the conditionals.

15:57.080 --> 16:03.640
If distance is greater than 500, we will approach, but otherwise we will not.

16:03.650 --> 16:06.740
If we're too far or too close, we will not approach.

16:06.860 --> 16:10.810
Instead, we'll evaluate one of these other conditions again.

16:10.820 --> 16:12.780
Now we can rename these as well.

16:12.780 --> 16:16.440
This one is checking if the distance is less than 500.

16:16.440 --> 16:17.940
So this one is checking.

16:17.940 --> 16:19.260
Are we close enough to attack?

16:19.260 --> 16:24.390
So we'll say, am I close enough to attack?

16:24.600 --> 16:28.020
And then this one we're checking am I arranged attacker?

16:28.020 --> 16:31.890
So we'll say, am I a ranged attacker?

16:32.580 --> 16:36.690
And arranged attacker should also check a distance as well.

16:36.720 --> 16:41.910
Arranged attacker should attack when it's a little bit farther away so we can have a distance check

16:41.910 --> 16:42.360
here.

16:42.360 --> 16:44.370
Let's add one more decorator.

16:44.370 --> 16:46.050
I'm going to call this one.

16:46.230 --> 16:51.570
Am I close enough to attack?

16:53.580 --> 16:56.760
And this one will also check distance to Target.

16:56.760 --> 17:01.800
But this one will be if we're less than so is less than.

17:01.800 --> 17:04.830
And we'll do a bigger value like 600.

17:05.100 --> 17:12.330
So if we're close enough by 600 units, then for a ranged attacker, we should start attacking with

17:12.330 --> 17:13.770
those ranged attacks.

17:13.770 --> 17:18.840
If we're not arranged attacker and we're not close enough to attack, we'll move on.

17:18.960 --> 17:22.320
But if we're close enough for the melee, we'll attack with melee.

17:22.350 --> 17:25.980
Otherwise we'll then see if we should approach and we'll approach.

17:25.980 --> 17:29.400
Okay, so we have a bit of a skeleton going.

17:29.400 --> 17:36.510
We do need to flesh out these other two cases and give our enemy the ability to attack.

17:36.510 --> 17:37.710
We'll get to that.

17:37.740 --> 17:40.770
I think this is a good stopping point.

17:40.770 --> 17:44.490
And in the videos to come, we'll flesh this out even more.

17:44.490 --> 17:52.050
Before we wrap up, I think we can go ahead and press play and we can see that these things are approaching.

17:58.910 --> 18:00.860
And they kind of just stand there.

18:00.860 --> 18:06.980
Once they've approached, we can see that we're basically in this move to Target.

18:07.700 --> 18:09.020
Part of our tree.

18:12.790 --> 18:15.480
We see that these nodes do nothing.

18:15.490 --> 18:19.420
So we'll get to our move to portion.

18:27.290 --> 18:30.550
And our very basic behavior is working.

18:30.560 --> 18:35.990
We just need to flesh out those other two branches there and we'll do those next.

18:36.080 --> 18:37.110
Great job.

18:37.130 --> 18:38.270
I'll see you soon.
