Full transcript
Outcome of This Part
0:00[Music]
0:05welcome back everyone to part 15 of our
0:08smart enemy AI series and in this part
0:11I'm going to be adding a long range
0:13attack for our melee enemy and it's
0:15going to look something like this so if
0:17I'm standing far away the enemy will
0:19jump boom and land attacking on me uh I
0:22can show you in slow motion far away
0:26jump
0:28and boom land on the
0:32player and if I'm close to the uh enemy
0:35he's going to do a normal attack and if
0:37I'm further away he's going to do
0:39something pretty interesting he doesn't
0:40just do a normal jump to my location but
0:43he predicts where I'm going to be so if
0:46I'm moving towards him he's going to use
0:49my velocity predict where I'm going to
0:51be so you see now he's moving backwards
0:53cuz he knows I'm going to be behind him
0:55at certain point and lands where I'm
0:58going to be so this is really useful
1:00because if I'm just running away from
1:02the enemy it's very hard for him to Boom
1:05to hit me if he doesn't calculate first
1:07where I'm going to go um and we're also
1:10going to be doing a lot of things in
1:11this uh tutorial we're going to be
1:12covering how to blend animations so this
1:15jump is actually a blend of the normal
1:17jump animation with an attack animation
1:20so I'm going to show you how to do that
1:22and once the enemy lands he no longer
1:24use the blend he uses the regular land
1:26animation from this Montage um so it's
1:29going to a lot of really cool things so
1:31let's get started all right so the first
Animation/Montage Setup
1:34thing that I want to show you is the
1:36animation that we'll be using so this is
1:38the animation I got from mixo uh called
1:41sword jump well I call it sword jump
1:43attack I'll leave the actual name in uh
1:46the description um and of course as with
1:49all the animations from mixo I added a
1:51root bone so we can have root motion um
1:54and what that means is uh you see this
1:56animation has movement in it it means
1:58that the mesh is actually
2:00moving um now if I say enable root
2:03motion then the mesh will also move with
2:06the capsule because the capsule is the
2:08actual Pawn is the actual actor the mesh
2:10is just for
2:11display um so right now if I do enable
2:14root motion then you'll see that the
2:17mesh itself is no longer moving in this
2:19space uh but the capsule will be so the
2:22actual actor will move depending on the
2:24data in the animation but we don't want
2:27to enable root motion for this attack
2:30um because if we enable root motion then
2:33this uh jump distance is decided by the
2:37animation itself I don't want the
2:38animation to determine the jump distance
2:41I want to calculate that in the
2:42blueprint because it's going to be based
2:43on where the target is might be a
2:46smaller jump a larger jump and so on so
2:48I'm not going to enable root motion but
2:51if I don't enable root motion and leave
2:52everything as is the problem is that the
2:55mesh will still move so the mesh will
2:58move but the capsule won't that means at
3:00the end of the animation you'll see the
3:02mes just teleports back to place where
3:05the capsule the actual actor is so to
3:08prevent that you can go here and say
3:10Force root lock so this doesn't enable
3:14root motion and prevents the mesh for
3:16moving as well and this is what we want
3:19uh if you don't have a root motion
3:20animation then you don't need to do any
3:21of this because nothing moves
3:24anyway um all right so now that I've
3:26explained the animation uh let me create
3:29the Montage the actual attack Montage
3:31from it so going here to our animation
3:34right click create create anim montage
3:38and I'm going to call it
3:40Montage um
3:44sword
3:46jump attack something like
3:49that all right so I'm going to open it
3:52up now first thing uh you'll see that
3:55this um animation has like a hop and
3:58then a jump I don't want this
4:00hop uh so I'm going to start the
4:03animation somewhere
4:05around here so like 0.45 seconds uh so
4:10you can do that by clicking on the
4:11animation and the timeline going to the
4:13details and say start time
4:160.45 great now the animation starts at
4:19the jump
4:22itself um great so we need two anim
4:25notifies here one to tell us in the
4:27blueprint when to jump and one to tell
4:29us when to do the attack itself the the
4:31sword swing so I'm going to jump right
4:35about here when the feet leave the
4:37ground so right click on the notify
4:39track add notify Montage notify click on
4:44it and we're going to call this one
4:47jump uh we don't have an implementation
4:49for the jump notify yet but we're going
4:51to do that and then right
4:55about here maybe yeah somewhere around
4:58here we want the
5:00uh add notify again Montage notify and
5:03call this one slash now slash this is
5:05the same notify we're using for the
5:06regular attack so we won't have to
5:09implement this it's already
5:11there
5:13um all right and that's basically our
5:16notify uh sorry our Montage so now let's
5:19implement this Montage so I'm going to
5:21go to my BP enemy
5:27melee all right
5:30and now we have only one attack right we
5:32have one uh sword slash attack that
5:35plays uh this montage and that also has
5:38a slash
5:39notify um and uh on slash it does this
5:43sphere trace and so on so I want another
5:47um attack uh that also does the slash
5:50but does a jump as well so we're going
5:53to create another one let me just move
5:55things a bit over here to give ourselves
5:57some
5:58space all right so we're going to have a
Separate Attack Functions/Events
6:01sort of default
6:04attack uh and we're going to have
6:06a short range
6:10attack and we're going to have a long
6:15range
6:17attack um and also everything here in
6:21this slash I want it to be its own um
6:24function or custom event doesn't matter
6:26because we're going to reuse it so I'm
6:28going to just just copy all of
6:32this I'm going to move it somewhere here
6:36and I'm going to make a new custom event
6:38and call it um I don't know
6:41sphere uh damage or sphere Trace
6:49damage uh does it take
6:53anything
6:55nope think that's all we need for it
7:01um all right so I'm going to just
7:04comment this and put it in something
7:06called attack
7:08helpers uh because the jump is also
7:10going to be an attack helper right so we
7:12have the sphere Trace damage uh we
7:14should also create a custom event
7:17actually I'm not going to do this now
7:18let's do this a bit later let's first
7:20call our sphere Trace damage
7:25here all right um now this is our short
7:28range attack right so I'm going to
7:31actually unplug
7:33this oh and this also the short range
7:36attack should also take input the attack
7:39Target which is an
7:43actor and the same for the long range
7:46input attack
7:49Target which is an actor all right so
7:52I'm going to make the short range attack
7:55here instead of this default attack
8:01um and the default attack what I'm going
8:03to do is just have it call short range
8:09attack all right and now we want to
8:11implement the long range attack now it's
8:13going to be very similar to this uh but
8:15I don't want to reuse it uh it's fine in
8:17some cases to copy and paste your code
8:19because uh we might want to change just
8:21the long range attack in the future and
8:23not the short range attack so it's
8:25better not to have them tightly coupled
8:27so I'm going to copy all of this
8:30and paste it
8:33here and don't forget the attack
8:41Target all
8:43right um now the differences are this
8:47one plays a different Montage we want
8:49our uh Montage sword jump attack here
8:53you can just drag
8:54it um and we also want an additional uh
8:58notify switch called jump and this is
9:02where we'll actually do the
9:05jump
9:07uh all right so right now we don't have
9:10anything calling short range attack and
9:12long range attack in our Behavior tree
9:16um if you recall we have this task melee
9:19attack and all it does is calls the
9:22default attack from the um enemy AI
9:25interface so I'm just for testing now
9:28we're going to revisit this later but
9:29for testing now I'm going to make the
9:31default attack the long range attack so
9:36that we can test it
9:38out all right so now if I play I expect
9:41this Montage to be playing but nothing
9:42will happen on jump so let's
9:46watch enemy here
9:49and yeah they're jumping and attacking
9:52so the attack is actually happening I'm
9:53getting damaged uh but uh he's not
9:57actually jumping towards me he's jumping
9:59jumping in place so let me show you
10:01again yeah he's just jumping in place of
10:04course uh let me remove the cool down by
10:06the way from the behavior tree just so
10:08to make our testing
10:11easier all right um now one thing that's
Explaining Problem With Animation
10:16really important to note is that if you
10:18I'm going to play in slow motion here
10:20watch this see the health bar is in the
10:22center of the
10:24mesh uh why is
10:26that that is because the capsule is self
10:29is not jumping and let me show you so if
10:31we go to the capsule component on the
10:33melee enemy search for hidden it's of
10:35course hidden by default we're going to
10:37uncheck that so you see the capsule in
10:40game and if I play watch the capsule as
10:43the enemy
10:44jumps the enem is jumping but the
10:47capsule the red uh capsule is not moving
10:51that means that the jump itself is uh
10:54only on the mesh it's not on the capsule
10:57and we don't want the mesh as well as
10:59the capsule to be jumping because we're
11:01going to calculate uh a jump here uh so
11:05that means the capsule will jump and the
11:06mesh will jump even higher so we we
11:08don't want the mesh to move at all in
11:10the
11:11z-axis and the reason the mesh is moving
11:13at all is because the animation
11:17itself um has the feet or the yeah
11:22starting from the the lower to lower
11:24body is jumping upwards in the z-axis
11:28and this has nothing do with root motion
11:29it's just um the mesh is moving upwards
Upper/Lower Body Animation Blending
11:33so to prevent that we're actually going
11:35to only play the upper part of the
11:37animation so I'm going to show you how
11:39to blend the upper part and the lower
11:40part with a different
11:42animation um so to do that we're going
11:45to go to our ABP Manu this is where our
11:49animation blueprint is and we're going
11:51to add another slot here so we have the
11:53default slot this is where all of our
11:55montages play I'm going to create
11:57another one and and we're going to
11:59select here the upper
12:03body so to do a blend uh blend the upper
12:07body and the lower body we need to First
12:09do one thing we need this main State
12:12here to be cached um which you can look
12:15at it as storing it in a variable so I'm
12:17going to pull off it and say um I just
12:20search for cache and choose new save uh
12:23cache pose and I'm going to call it the
12:27uh main state
12:30so now that I have this as a variable I
12:33can uh just use it like this and I can
12:36use it multiple times uh that's the main
12:38reason for caching
12:40it um so now uh I want to do uh one
12:44thing I'm going to search for layered
12:47blend per bone this is the node we want
12:51this allows you to take in a base pose
12:53and a sort of secondary pose and it
12:55Blends them so the base pose here is
12:57going to be our main State and the blend
13:00pose is going to be our upper body slot
13:04uh but it also has to have a source and
13:06the source is going to be our main State
13:08again so I'm going to copy this
13:11here um now the layer blend per bone the
13:15way it works is that you have here if
13:17you click on it uh oh don't forget to
13:19connect this if you click on it I have
13:21here this layer setup uh which is an
13:23array if I click it it's going to give
13:26me two things a bone name and a depth so
13:28it's asking me at what bone in this mesh
13:32do you want to start blending so I'm
13:33going to say spine underscore 1 so if
13:37you go here to the uh mesh itself you'll
13:41see spine one is the lowest spine so
13:44everything below spine One play the
13:47regular animation which is Jump run
13:49whatever you're currently doing and in
13:51the uh everything above spine One play
13:54the Montage that I'm giving
13:57you um and Bone depth I'm going to set
14:01to one sorry blend depth um blend depth
14:04I don't really fully understand what it
14:06does if someone knows exactly what blend
14:08depth does please tell me I have an idea
14:11but it's uh not a very uh accurate one I
14:14have to
14:15say all right so um this is pretty much
14:19what we need for now um let me show you
14:21what this looks like so now oh one more
14:24important thing is you have to go to the
14:26Montage itself and tell it over here to
14:30play in the upper body slot so I'm going
14:33to go here slot slot name upper
14:36body um this is going to happen that's
14:39fine if you just uh go away and come
14:41back it's going to be uh working
14:44again um okay now if I play oh and by
14:47the way I have the Tab Key configured
14:49whenever I press tab to do slow
14:51motion so now as the the the attack
14:56happens the actor is no longer uh
14:59jumping you'll see he's just doing the
15:01animation and he's not jumping let me
15:04show you again attack me and he's just
15:08doing the
15:10attack and only in the upper body the
15:13lower body is staying the
15:16same great um so now if we actually um
15:20do a jump then he'll start blending the
15:22jump the legs from the jump animation
15:25with the uh upper body from uh the uh
15:28montage
15:29so to do a jump I'm just going to do a
15:31dummy jump for now do a launch character
15:33and say uh launch him 500 in the z-axis
15:38so he'll just jump vertically
15:41upwards so let's see what this looks
15:43like and yep there we go and you see the
15:47capsule the entire capsule is moving
15:48this time and the legs are being Blended
15:51in with the um uh upper
15:54body uh one more thing also for the
15:57animation blueprint is in the layer
15:59blend per bone I like to enable mesh
16:01space rotation blend uh I find that this
16:04uh this uses the mesh space to calculate
16:06the rotation instead of local space and
16:09I find that it gives a better result
16:11um so uh let me show you
16:15again and jump yes much better all
16:20capsule is moving uh and
16:24the uh the legs are blended with the
16:26jump animation now one more thing that
16:29you'll notice is that as the enemy lands
16:31look what happens when he
16:35lands um you'll see that
16:37the he's still blending with the jump
16:40land animation so the the jump has this
16:44uh jump and then jump land where he does
16:46this with his
16:47hands and he's blending in with the jump
16:50land and it looks a bit weird um because
16:53the animation itself has a really cool
16:55uh Landing pose let me show you so this
16:58is what what the animation looks like
16:59when you land so why isn't uh because
17:02we're not blending the legs of the
17:04animation we're playing the uh jump land
17:07legs and I don't want that um I want if
17:09the enemy is not moving if they are uh
17:12they don't have a velocity then play the
17:14full animation because if you don't have
17:16velocity then there's no point in
17:18blending the legs because if your
17:20velocity is zero your legs aren't doing
17:23anything uh so to do that go back to the
17:25animation blueprint and here we're going
17:28to to uh to do like an if condition in
17:30animation blueprints uh there's
17:31something called a blend uh poses by
17:35bull so if true use this if false use
17:38that so in the our our condition here is
17:42if our velocity and we have a variable
17:45for velocity I think here yeah we have
17:48velocity if velocity is not equal to
17:52zero this is our
17:55condition so that means if the character
17:58is moving then blend normally uh do
18:01everything that we just did
18:02here but on the false if the character
18:06is not moving neither moving forwards
18:08backwards up or down or anything then
18:10take the upper body slot just as it is
18:14and use
18:16it well sorry move this backwards a bit
18:19take the upper body slot and use it um
18:22as uh without blending it in anything so
18:24we ignore the blend we just use the
18:26upper body slot this means it will play
18:28uh the full animation not just the upper
18:30part of the
18:31animation oh let's see how this looks
18:33like right now I'm going to do slow
18:36motion again jump and as he lands his
18:39velocity becomes zero and nice he plays
18:42the animation legs the the Montage legs
18:46itself perfect and you want to see it
18:48again not in slow motion here we go jump
18:51boom
18:53land
18:56great very nice
18:58this is something we also want to fix uh
19:00but I'll show you that fix for it later
19:02or if you didn't notice it I'll explain
19:04what it is later um all right so now we
19:08have our uh Montage playing we have a
Jump To Target Functionality
19:11fake jump here now we actually want to
19:14calculate um a jump to the
19:19player
19:20um all right so we're going to create
19:24over here in our uh next to the sphere
19:27trace and our attack helpers another
19:29custom event and we're going to call it
19:31jump to attack
19:34Target and it takes as input oh let's
19:37also the capsule let's hide it
19:42again um and it takes as input our
19:47attack Target and if you recall we
19:50already have a jump that we implemented
19:53in uh the nav links
19:56tutorial uh jump to destination oh it's
20:00not sorry it's not in the melee enemy
20:02it's in the uh base
20:05enemy uh
20:07jump to destination so uh in this jump
20:11we used the suggest projectile velocity
20:14Uh custom Arc node to calculate the um
20:18launch velocity that we need so we're
20:20going to reuse this node as well we're
20:22not going to reuse the entire function
20:23but we're going to reuse the node
20:25because the function is going to be
20:26doing a few different things so I'm just
20:28going to copy it here go back to my
20:30melee
20:31enemy and here what we want to do is uh
20:36we want to have a start position and an
20:39end position uh to jump from the start
20:42Position will just be whatever we are
20:44now so get actor
20:46location and the end position is going
20:48to be where our Target is so get our
20:51attack targets and get their actor
20:54location uh but just like with the jump
20:56from the previous one we want to add a
20:58bit of offset to the Z value so I'm
21:01going to right click here split this the
21:04x is going to be the same Y is going to
21:05be the same the Z we're going to add uh
21:08about 100 units to it that's one
21:12meter uh just to give ourselves some
21:16buffer and then uh we use this output
21:19velocity to call launch
21:22character and click XY override and Z
21:26override right now what this will do is
21:28it will just jump to where the actor's
21:30location is uh I'm going to make it a
21:33bit of a smarter jump later on uh so I
21:35don't want it to just jump where the
21:37actor is I wanted to jump where the
21:39actor will be after an x amount of
21:41seconds because if the uh Target is
21:45running away from the enemy and the
21:46enemy jumps to where they are now well
21:49by the time they land the player will be
21:51far far gone so if the enemy calculates
21:54where the player will be in say a second
21:56and jumps there then it's a sort of a
21:58predictive and more smart uh Behavior Uh
22:01but first let me show you this um jump
22:04to location
22:06first so going over here and jump we're
22:09just going to call jump to attack Target
22:13and we're going to pass the attack
22:17Target all right let's see how this
22:21looks so attack
22:25me um let's actually so right now the
22:28attack he's moving too close uh I'm
22:31going to edit this for now but remind me
22:32to change it later on so right now we
22:35move to the um attack radius right so
22:39let's go to our melee enemy here and in
22:44our get ideal range let's have the
22:48attack radius something like uh
22:51400 so that uh he attacks from a bit
22:54further
22:55away all right so now you'll see he's
22:58jumping to me he's moving and he lands
23:01where I am boom attacks
23:05nice see that again I'm running away
23:08jump very nice and the entire capsule is
23:11moving the blending is happening
23:14nicely now before we calculate the uh
23:17future location I want to fix something
23:19else and I'm going to show you in slow
23:20motion what happens watch what happens
23:22when the um when the enemy lands on the
23:25floor
23:26okay
23:29watch and see he lands and boom you see
23:34that there's slight delay between
23:36blending uh back from the uh jump
23:40animation to the Montage there so it
23:44looks very weird and the reason this is
23:46happening is because as soon as the
23:48enemy lands um uh as soon as the jump is
23:52over and the enemy lands they still have
23:55velocity that means that velocity uh is
23:58not equal to zero so we'll still be
24:00using the blend but what we can do is
24:04tell the enemy as soon as you land stop
24:06moving so your velocity becomes zero and
24:08we stop blending with the jump animation
24:11and we can do that very easily over here
24:14in our jump to attack uh there is uh an
24:18event dispatched when the character uh
24:21lands on the floor we don't have to
24:22create that it's already comes by
24:24default with the character so I'm going
24:26to pull off here and say assign landed
24:30delegate this is what it's called assign
24:32landed
24:33delegate and we say um on land or
24:39something so when we land first thing we
24:43want to do is uh well
24:46unbind so unbind event from landed
24:50delegate so that we don't do this when
24:53we're not
24:55jumping uh and the event is this event
24:58and after that all we're going to do is
25:00uh get our character movement component
25:03and call stop movement
25:08immediately great so this as soon as the
25:11enemy lands stop moving and unbind from
25:13the land delegate so he don't do it
25:15again now let's see how this looks like
25:17and again in slow motion he's landing
25:21and boom he's blending perfectly now or
25:25let's say not blending as soon as he
25:27lands and the animation looks really
25:29cool great so now I told you that uh if
25:33I'm running away from uh the enemy
25:36there's no way that he's going to jump
25:38uh to my location right he's only
25:40calculating the location when the jump
25:42begins so it's very difficult to hit me
25:46so what we want is for the enemy to
25:48calculate where I will be or where their
25:51target will be in let's say a second and
25:55jump to that
25:56location luckily we can also do that
25:58quite easily um I'm going to create
26:01another function for it so over here in
26:02our functions I'm going to create
26:04function called um right now I'm going
26:07to create it in the melee enemy but
26:08we'll move it later on to a more uh to a
26:11better place I'm going to call it
26:15um uh
26:17calculate future actor
26:23location right so this um uh this
26:27function is going to take two inputs one
26:29is the actor that we are calculating
26:32their position and the other is hate
26:36when this happens and the other is time
26:38so how long um in the future do you want
26:41to calculate their position it's going
26:43to be a float so if this is 1 second
26:45then calculate where they're going to be
26:47in 1 second if it's two seconds
26:49calculate where they're going to be in
26:50two seconds and so on and as an output
26:53it's going to return a
26:56location
26:58which is going to be a
27:00vector all right so how do you calculate
27:02uh future uh location U very easy so um
27:08the location is the uh velocity of the
27:12actor multiplies by the time plus their
27:15current location so what we need is
27:17first to get their velocity so get
27:22velocity and we're going to multiply
27:25this by the time
27:28oh but actually before we do that uh we
27:30want to ignore the Z value U because if
27:35the character is currently jumping and
27:36we calculate their position then their
27:38position is going to be somewhere in the
27:39air and so we don't want that so we're
27:41first going to multiply it by one on the
27:43X one on the Y and zero on the Z uh this
27:47ignores their upwards um uh
27:50vector and then multiply that by the
27:55time and the time let Let's uh default
27:58it to one second
28:03here all right and after that uh what we
28:06want to do is get the actor's
28:10location and
28:12add to that this uh velocity times
28:17time and that's pretty much it so again
28:21to recap in a comment here um the
28:24location is equal to Velocity multiplied
28:28by time plus um current location and
28:33that's pretty much
28:35it um to also show this visually uh what
28:39we can do so back here in our event
28:42graph let's well let's first call it
28:44instead of getting the actor location as
28:46our end position uh we are going to call
28:49our function that we just made so let me
28:51move things a bit backwards here uh
28:54we're going to call calculate future
28:57actor
28:59location give it our attack Target and
29:02yeah let's keep the time at 1
29:05second uh and I'm going to split this
29:07again because I still want
29:10to uh keep the X and the Y the same I
29:13still want to add 100 to the Z uh this
29:16offset is uh just I found makes things a
29:18bit more
29:19accurate um okay now to visualize this
29:23like I told you um I'm going to add a
29:28node here called Draw debug
29:32sphere and split
29:35this it's going to be this x well this Y
29:40and this Z it's going to be a bit messy
29:42now but this is just to show you how
29:44it's going to look like plug this here
29:46plug this here all right so now as I'm
29:49moving the enemy will predict where I
29:51will be and jump to that location so let
29:54me show if I move towards
29:56him he's predicting I'm going to be
29:58behind him so he jumps there you see
30:02that that's pretty cool yeah and now the
30:05jump is is a lot more harder to get away
30:10from uh but why aren't we drawing the
30:13debug
30:14sphere uh we do this we draw the debug
30:21sphere actually something isn't
30:26right oh the duration I didn't put a
30:28duration let's say draw for two
30:31seconds all
30:35right yes very nice so you see even
30:38slight movements and he predicts that
30:40I'm going to be there and tries to jump
30:43there very nice and again if I show you
30:46this while I'm moving towards
30:49him very nice and do it again
30:56great now it's a lot
30:58harder um perfect and we can remove this
31:01draw debug
31:06sphere all
31:09right uh one thing we can also do is um
31:12check first if the velocity is uh not
31:15equal zero then just return the current
31:17actor location there's no need to do all
31:19this calculation uh but yeah it's a it's
31:22a small optimization it's not really
31:24needed but you can do that if you want
31:27great now um the second thing we want to
Enabling Multiple Attacks In The Behavior Tree (based on distance)
31:30do is uh well right now in our Behavior
31:32tree uh we're only doing one attack
31:35we're doing this melee attack right and
31:37this is what we've been doing this whole
31:38time we only call
31:40attack um what we want now is to set up
31:44um sort of an ability system uh where
31:47the uh enemy can pick between different
31:50attacks based on which one is uh the
31:52right one at the current
31:54time um so we have a long range attack
31:56and we we have a short range attack for
31:58now right and I think it makes sense
32:01that the short range attack you should
32:02do when you're closer to the Target and
32:05the long range attack should do when
32:06you're further away from your target
32:09right um so we want the behavior tree to
32:12be responsible for this decision
32:14making um so how do we get the behavior
32:18tree to do that uh what I want is to add
32:21in our Blackboard here uh the distance
32:24the current distance from the attack
32:26Target to always have this value at hand
32:28uh to make decisions based off of it so
32:30we're going to go to our Blackboard you
32:32can either open it from um from here or
32:35click on the Blackboard
32:37Tab and we're going to add a new key and
32:39we're going to call it distance to
32:43attack Target oh what am I doing uh
32:46we're just going to be sorry a float
32:48first so select float and then call it
32:51uh distance to attack
32:55Target great so this is
32:57um a new Blackboard key that's going to
32:59be available for all of our Behavior
33:01trees but we want a way to update this
33:04value um consistently so we keep
33:07updating this value uh what we used to
33:10what we did before if you recall we have
33:12this uh service so uh a blueprint uh
33:16sorry a behavior tree service that runs
33:18every I don't know 1 second and checks
33:20if our actor is our Target is dead to
33:23stop attacking them so we're going to
33:24create a new Behavior Tree Service as
33:26well so go over here to new service say
33:29BTS service put it in the services
33:32folder and we're going to call it BTS
33:35underscore update distance to
33:41Target and just like the other BTS what
33:43we're going to do is over functions
33:45override the receive tick
33:47Ai and this is going to be called on
33:50every tick and we Define how often uh a
33:53tick happens and I'll show you how we do
33:55that but first let's calculate the
33:56distance distance um we want distance
33:59from our Pawn to our attack Target so we
34:02need to know who the attack Target is
34:04that means go over to the variables add
34:06a attack Target key we always
34:10communicate with Blackboard Keys it's
34:11going to be of type Blackboard key
34:13selector make sure to click the I icon
34:16to make it um instance
34:18editable then pull off of it and say get
34:21value as
34:25actor so we're going to get our current
34:28actor location so this is the enemy
34:30actor location and we're going to get
34:32the actor location of their target which
34:34is our
34:35player and uh we're going to get the
34:38distance between them so we're just
34:40going to search for the distance Vector
34:43node which takes two locations and gives
34:45you or takes two vectors and gives you
34:47the distance between
34:49them um and once we have this distance
34:52we want to update our uh Blackboard key
34:55the new distance to attack Target key we
34:57created with this value so that means
34:59that this server should also know what
35:01this key is so we're going to add a new
35:03variable call it our distance to Target
35:07key also click the I
35:10icon and then we are going to um uh set
35:16that so pull off of this and say set
35:20value as float we know it's a float so
35:22set value as
35:24float and this is what we're going to do
35:27on each tick just set this
35:30value as a float
35:33here excellent so then we want to use it
35:36in our Behavior tree so back to our
35:38Behavior
35:40tree
35:41uh we want to use it in
35:45our uh in all of in in in this part so
35:48let's create a new sequence node here I
35:51can just put it on the whole combat
35:52state but then it's also going to be
35:54called on is wielding sword which is not
35:56really
35:57important so I'm going to create a new
36:00sequence of actions
36:03here and I'm going to call this
36:05one I don't know combat ready so once
36:09you equip the sword you are combat ready
36:12and I'm going to put our uh new service
36:15on this combat ready update distance to
36:18Target uh the attack Target key will be
36:21attack Target our distance Target key
36:23will be distance to attack Target now
36:25here is where we set how off this ticks
36:27uh I want it to tick every 0.1 seconds
36:30with no random deviation so every 0.1
36:33seconds just tick and update the
36:36distance great so now that we do that we
36:39always know what our distance is so we
36:42can start doing conditions based on that
36:44here so to do that uh we can have a
36:50selector so I'll do a selector and it's
36:52going to select between two attacks
36:54whether I should do the jump uh attack
36:56or the short- range attack um so assume
36:59that this is an attack and this is
37:02another attack right now they're both
37:03the same but assume they are different
37:05ones uh we want to add a condition for
37:08this one so I'm going to right click on
37:10it and add a decorator called Blackboard
37:13so Blackboard decorator is where you can
37:14check certain conditions on any
37:16Blackboard
37:18key uh which by the way we use for uh
37:21the states so we check if the state
37:23Blackboard key is Frozen is
37:25investigating blah blah blah so we're
37:27going to use it as well here so click on
37:28the Blackboard condition and say um the
37:32Blackboard key is the distance to attack
37:34Target if this distance is uh greater
37:38than or equal to I don't know something
37:40like
37:41400 then do the long range attack
37:44otherwise do the short range attack
37:47obviously right now these are both the
37:48same attack so we need a way to
37:50differentiate between
37:52them I can create two separate uh tasks
37:55for short range and long range but they
37:58have a lot in common so let me show you
38:01uh this attack if you recall it's the
38:03entire attack sequence it tries to check
38:06if there's enough tokens to attack um uh
38:09if there are enough tokens then it sets
38:10the movement speed to sprinting clears
38:12the focus moves to the attack radius uh
38:17and then sets Focus again does the
38:19attack and when the attack is finished
38:22it finishes executing so everything here
38:25is going to be common between the two
38:26attacks except just this part which
38:30attack function do we call and which
38:33distance do we go to before attacking
38:37obviously for the short range one you
38:38need to be pretty close to attack and
38:40for the long range one you need to be a
38:41bit
38:42further so let's modify this existing
38:45task to allow it to um use both
38:49attacks so how we're going to do that um
38:51instead of calling this the attack
38:53radius let's actually call it the um
38:57um actually no let's keep this attack
38:59radius that's
39:00fine um and here is where we need to
39:02know uh which attack we can do right um
39:06now you can't pass in an attack as a
39:09function uh but what you can do is pass
39:10in the name of an attack to this uh task
39:13tell it to do this attack or that attack
39:16um but we don't have really names yet so
39:18let's create that so here in uh our
39:22enemies folder I'm going to create a new
39:24folder I'm going to call it melee enemy
39:27and I'm going to put the melee enemy
39:29here and next to him I'm going to create
39:31a new enum so search for
39:34enumeration and this enum is going to be
39:36called uh melee attacks so this just a
39:40list of all the attacks the melee enemy
39:42can do I'm going to add three the first
39:45one is just default it's always nice to
39:47have default the second one is short
39:49range
39:51attack and the third one is long range
39:55attack
39:57great um and over here in our uh melee
40:03attacks uh Behavior tree task I'm going
40:06to add a variable call it the attack
40:09name and it's going to be of type this
40:11enum we created melee enemy attacks also
40:16click the IE
40:18icon so over here uh before we do the
40:22attack I'm going to actually delete this
40:24attack and I'm going to do a switch so
40:26get this enum and do a switch on
40:30it um oh and by the way right now we're
40:33casting to the base enemy we actually
40:34have to cast to the melee enemy instead
40:37so I'm going to
40:39also replace this with a cast to melee
40:47enemy uh where was our Pawn we cast The
40:53Pawn all right so we're casting our Pawn
40:55to our melee enemy me uh we're binding
40:57at the end and we're doing a
41:01switch uh if the cast fails just finish
41:04uh fast fails finish execute with
41:07success
41:09false um all right so now that we have
41:12this switch we want to know which attack
41:13to do so for the default just call the
41:18attack attack message from the blueprint
41:21interface uh and give it the attack
41:25Target
41:29uh for the short range attack we pull
41:31off of the melee enemy and call short
41:33range
41:34attack and for the long range attack we
41:37do the same pull off of this enemy and
41:39call Long Range attack and they both
41:42also need the attack
41:48Target all right uh it's a bit messy I
41:51don't want to waste your time cleaning
41:52up these uh nodes but uh it's a good
41:55good idea to make sure your lines are a
41:58bit
41:58clean all right then after that uh we're
42:01going to um add a route nodes which is
42:05just uh this thing combines a bunch of
42:09different
42:10outputs and we're going to uh bind and
42:14finish execute when the attack is
42:16over uh by the way adding a reroute node
42:20uh here is the same as uh double
42:22clicking on this it's just a reroute
42:24node as well
42:26uh all right
42:29so
42:31uh oh targets yeah Target is this I
42:34forgot that guy all right so now that
42:37this um Behavior tree task is modified
42:39let's see how we can use
42:41it so for the this is going to be our
42:44long range attack we can rename the node
42:46here to long range attack and this one
42:49let's name it to short range
42:52attack so for the long range attack our
42:55attack radius let's actually use our
42:58defend radius for that so that means um
43:02you can be in the defend radius before
43:04you actually attack and the attack name
43:06is long range
43:08attack here uh tokens needed one attack
43:11radius attack radius and attack name is
43:13short range
43:15attack all right um now one final thing
43:19is we need to revert our attack radius
43:22and defend radius uh which in this case
43:25this really means the radius of the
43:26short range attack and the long range
43:28attack so let's make this one uh 200 and
43:31this one um yeah 400 is
43:34fine great so again uh what we have now
43:38is if the distance to attack Target ever
43:41exceeds 400 then do the long range
43:43attack if it is not more than 400 do the
43:46short range attack and then do the
43:48weights in all
43:50cases I'm going to decrease this weight
43:52a bit I think it's a bit too much anyway
43:55let's see how this
43:57looks all right so now the enemy should
44:00jump at me and he didn't
44:02jump uh oh okay so now he did but in the
44:08first one he didn't jump even though I
44:09was very
44:11far but he jumps the second time
44:15around this probably means that this
44:17value distance to Target isn't set the
44:20first time you enter the
44:21tree and probably because as soon as we
44:24enter this combat state we wait 0.1
44:27seconds and then call the tick so during
44:30these 0.1 seconds this actually already
44:32happened and this check happened and
44:33failed because distance to attack Target
44:35is not set so to fix it there's actually
44:38something easy we can do is uh check
44:41this box on the service say call tick on
44:45search start that means that as soon as
44:47you enter this Branch call The Tick
44:50function and don't wait for the 0.1
44:51seconds the first
44:53time uh okay so this should work let's
44:55see so he should jump now and perfect
44:59okay and if I'm close enough oh actually
45:02why is he
45:05strafing okay so he he shouldn't be
45:08strafing at all because I don't have a
45:10cool down he should always
45:13oh this is a sequence so he's always
45:16going to attack and then strafe and I'm
45:18mistaken this should be a selector
45:20because we want to choose between
45:21attacking or if we're not uh or if we
45:24can't attack for any reason like there's
45:26a cool down which I removed now uh then
45:29strafe but um right now it should always
45:32be attacking so I'm going to replace
45:34this with a
45:37selector uh put my service on here move
45:41oops move these move
45:45these and call this one the combats
45:49ready okay so now we're selecting
45:51between either attacking and strafing
45:53and since I don't have anything to
45:55prevent this node from failing so
45:56nothing makes this fail uh then we'll
45:59always attack so now let's see he should
46:03jump at me he's far away and now he's
46:05close normal attack great and if I move
46:08far
46:10away let me try moving
46:13further no still doing the normal one oh
46:17now he's doing the jump I'm far
46:19away and jump yes let's test that again
46:23farther
46:24away jump closer normal
46:31attack
46:33and further away jump
46:36perfect so one thing that you'll notice
46:38is that sometimes even though I'm moving
46:40far away he's still doing the normal
46:42attack like here this is because right
46:44now he is in the short range sequence if
46:46you recall the short range sequence
46:48already has a move to uh attack radius
46:52uh so right now he's trying to complete
46:54the short range sequence and when he
46:56reaches me he can complete it but now
47:00now he's not in any attack sequence yet
47:02so if I go closer to him I'm still
47:04within the 400 m he's going to do the
47:07jump attack and predict where I'm going
47:09to land and attack
47:14boom very
47:16nice um so you can keep playing around
47:18with these values uh with the attack
47:20range the the attack radius defend
47:22radius uh try to find Value that works
47:25for you and also you can play around
47:26with the conditions so right now the
47:28only condition I have is if the distance
47:30is greater than 400 maybe for your game
47:32you want uh a cool down for the long
47:34range attack if it's not on cool down
47:36then always do it otherwise do the short
47:38range and so on um so there's a lot of
47:40things you can do uh but for this video
47:43I showed you how and uh yeah you can
47:45make it your own and that's
Next Up In Part 16
47:48it as always thank you all for watching
47:50if you enjoyed this part please consider
47:52giving a like And subscribe and if you
47:54want to download the full project files
47:56the animation the code and everything
47:58you can get that free from my patreon
48:00and Link down the description as well as
48:02right here um and uh for the next part
48:06I'm going to continue adding more
48:08abilities to different enemies so next
48:10part specifically we're going to add a
48:11really cool like spinning attack for the
48:14melee enemy where he spins his swords
48:16and follows you around and then we're
48:18going to be adding uh some U different
48:21ranged enemy attacks Mage enemy attacks
48:23and so on so this will allow us to
48:25create multiple different abilities or
48:27multiple different attacks which we will
48:29then use all of them in the boss fights
48:31because boss fights are usually just a
48:33combination of mechanics that you've
48:35encountered in uh previous enemies but
48:37combined together to become a much more
48:40difficult and challenging fight so I'm
48:42working my way up to that uh to make
48:44something that's really uh as you see it
48:47in uh proper games and not just like oh
48:49here's a boss here's a couple of
48:50animations and a couple of attacks but
48:52this will really be a progressive system
48:54it will teach you how to
48:56uh not only create uh smart enemies but
48:59also teach the player the mechanics of
49:02certain enemies uh as they progress
49:04through your game so I hope you enjoyed
49:06it and I'll see you
49:08[Music]
49:22there