Smart Enemy AI | (Part 2: Patrolling & States) | Tutorial in Unreal Engine 5 (UE5)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] foreign welcome back everyone to part two of our enemy AI tutorial series uh in this part we're going to be creating a patrolling State like this enemy you see here that's following um a spline along uh yeah following along the spline as their patrol routes and we're also going to be switching between attacking States and Patrol States um so this is what it looks like the enemy starts out patrolling and if I press one the enemy will take out a sword and start attacking me and then if I press one again the enemy puts back the swords and goes back to patrolling and as you can see we have animations for unsheathing the sword and also sheathing the sword again so we're going to be covering how to create this animation these animation montages the patrol States and most importantly how to get our enemy AI to switch between states so let's get started all right so this is uh where we left off last time we have this uh enemy and this Behavior tree um I changed one small thing in the Wheeled sword um uh task and now the enemy does this animation this uh wielding sword animation before he attacks me uh just because we initially had it where the enemy just spawns a sword out of nowhere now I'm not going to show you how to create the um uh this this animation but we will be using a sheath sword or unwield swords uh task at the end of this tutorial so you'll see exactly how how I did it and as always I'm going to leave all of the assets any meshes and the source code for my patrons link down in the description all right so now we want to create um an additional state so right now we only have this combat State we're going to create a new patrolling State uh and basically the enemy will be patrolling a certain area so we're gonna draw a spline somewhere and the enemy will just follow the spline back and forth and this is their patrol route um and we're going to of course plug it into the behavior tree and then switch between the two states uh so first thing we need to do to create this Patrol state is we need to Route so I'm going to go over here in my Ai and um somewhere here I'm going to create a new blueprint of type actor and I'm going to call this the patrol route so this is the actor that we're going to spawn in the world that the enemy will follow so what we need here is in the components is just a spline and make sure to use spline this spline component and not spline mesh and we'll call this the patrol route and we're going to leave it as is here um and but before we dive into the implementation let me just show you what this looks like in the world so if I take my patrol route here then I have this spline and I can draw a route so I can take this point here alt and drag make another Point alt and drag sorry move that way alt and drag alt and drag yeah so this is our Patrol path now so the enemy starts here they're gonna start moving around a bit here reach the end and then go back let me just move this a little bit here so it makes more sense all right so um how do we get the enemy to move along this route well first of all I don't need any of these but what I do need is a new custom event so we're going to create a new custom event and call this increments petrol uh route um so what we want here is to get the current point that the actor is at and get the location of the next one so to do that we need two variables that we're going to plug in here first one we need to know which is what's the index of the current Patrol point that we're at which point in the spline are we currently standing at and this is going to be an integer and we also need to know the direction that we're going now the direction I'm going to make the value between negative 1 and 1. so that negative 1 is going backwards and one is going forwards and this increment Patrol route path all it does is that it gets our index and it sets it to the current index Plus the direction so if the direction is one and the index is zero then the new index is one and if the direction is negative one then it goes back um so we're basically just incrementing the current points that we're starting at and afterwards we need to check is this new Point have we reached the end and to do that we check if this new point is equal to the patrol route so pull off of the patrol route which is the spline component and call get spline uh what was it called get number of spline points so this is a total number of spline points in in this spline so for us it's one two three four five six seven and since the index starts at zero we need to subtract one from this so subtract one and if this number is equal to the new Patrol index then we've reached the end what do we want to do we want to set the direction to be negative one and on the false otherwise we need to check something else we need to check if the patrol index that we're currently at is equal to zero because then we're moved backwards and we've reached the beginning again and if that happens then we want to set the direction back to one and this is our increment function we're going to be calling this function from the behavior tree to tell the enemy AI to move to the next point on the spline but first we need something else now we just have a spline with points but we need to know the location of each each point in the spline so we're going to create another function here and call it get spline Point as world's position what this is going to do is it's going to have an output of location and type vector and it's going to get the patrol route and get spline points um yeah it was called get location at spline points yes so then we plug in the current index that we're at and make sure to set the coordinate space to Worlds because we want to know where it is in the world not where it is relative to this actor and that's this function all right so now we have our Patrol route actor and we have our enemy now how do we actually tell the enemy to how do we assign this Patrol route to this enemy well let's open up our BP enemy base by the way I press Ctrl P to open up this uh this open asset menu um and in here let's add another variable and call this Patrol uh routes uh let's add it in a category called Ai and this is going to be of type BP Patrol route this is the patrol route that we just created and make it uh instance editable out over here in the world I can click on my enemy and search for Patrol and now I can select the patrol route from my world or I can click and click this dropper and select it right here so now I have a patrol route Associated to the enemy what we want is in this Behavior tree to start moving the enemy along this Patrol route now to do that we'll be creating tasks just like we've done for everything else so up here create a new task off of blueprint base put it in the tasks folder and let's call this one BTT underscore Move Along Patrol routes right and as always call event receive execute Ai and finish execute Success Through now what we can do and what we've been doing so far is taking the pawn um casting it to our base enemy and then getting our Patrol route from here then calling increments a point on it or get a point as World position and so on um now we're not going to be doing this now uh because everything that we've been doing so far all the other tasks have been specific to this type of enemy or all the other tasks that we've needed to cast to our specific this type of enemy but now we're creating things that are generic for all types of um enemy AIS Le so it's better to use interfaces at this point let me show you what I mean so over here I'm going to again my AI folder I'm going to right click and create a search for interface and select blueprint interface and call it BPI for blueprint interface underscore enemy AI now for those who don't know an interface is just a collection of functions or not really function implementations but function definitions that you assign to any actor or any class and it tells this class what functions it needs to implement to be able to have a certain functionality so we're going to create this interface with all the functions that we want our enemy AIS to implement and the first function is going to be called get control route well sorry um gets Patrol route and this function just has one output which is our Patrol route of type BP underscore Patrol routes object reference now compile and save and back here in our base enemy um go over to class settings and on the right here under interfaces add and search for our enemy AI interface now what this does is that on the left here you're going to see that it tells you this is the function that you need to implement coming out of the enemy AI interface so we're just going to double click it and get our Patrol route and put it as the return points and we just implemented this function now the useful thing also about interfaces is that now back here to my um my behavior tree task instead of having to cast I can just take my pawn and call get Patrol routes and you'll see here that it says message between brackets and this means and it says in the documentation as well that this function does nothing if the target does not implement the required interface so this means we can call this function safely knowing that if this Pawn implements the interface we're going to get a patrol route otherwise we won't get anything so pull off of this always good to make sure that it's valid and if it is valid then we want to get um what was it called get points as World position so we're going to get our current point or the point that we're currently standing at as a world position and then we're going to do an AI move to uh so this one AI move to pass in the location here as our destination the pawn is just our controlled Pawn here let's tidy this up a bit and um let's do a 10 acceptance radius and on success before we finish we want to do something else which is off of our Patrol route here we want to increment uh the patrol routes so that we go to the next point and let's do this either on success or on fail and finally finish execute so every time we call this task we move to a new point along this route so back here in our Behavior tree um let's move this combat State just away for now and let's create a new sequence and call this our Patrol States or it's actually called passive States because you can be patrolling or just standing still and what we want here is just to say move along Patrol route and then maybe wait for one second so we move to a point wait for one second and then move again um yeah so let's see if this works now when I press play yeah here's our enemy move to the first point wait to the second move to the second Point wait a second and so on now I can also let me rotate this so that the enemy starts closer well and also let me move this point here um all right so let me also change the yeah the wait time to Let's remove it all together let me show you what it looks like if we remove it so you see how the enemy slows down before reaching a point um this is to do with the character movement component on this enemy uh if you don't want this Behavior to happen where the character um breaks or slows down acceleration before reaching um their Target's location by the way this was also happening in our combat States so if you notice before the enemy reaches me they're gonna slow down a bit let me show you yeah so see how they slow down just before they get to me if you don't want that to happen um you can go here to your base enemy class and under character movements so scroll down to yeah okay this one so under nav movements uh there is a used fixed breaking distance for path if you uncheck this or change this number to zero now this won't happen all right now back here in our Behavior tree um yeah everything looks good so if we play now you see the enemy is running between the points and doesn't break uh before reaching a point but they stop for just a short period of time at each point um also if I go over here and do simulates instead um where's our spline yeah there it is so now you can see the enemy moving along our spline points excellence all right so um one thing I also want to do is change the movement speed of the enemy so the enemy just uh let's play this so the enemy is sprinting along these points I want the enemy to be like walking smoothly to do that we need to update the movement speed of the enemy um when we do certain actions so let's go back to our blueprint to our interface again next to the get petrol route function we're going to add the new one so add function and we'll call this set movement speed [Music] um and it takes as inputs now we can directly pass in the the number here like 100 like um yeah so we can give the speed number as a float and pass in 100 500 or whatever uh but I would rather that we create an enum for this so over here on our AI folder I'm going to create a new folder and call it enums and I'm going to search for e numeration and call this e underscore movement speed now an enum is just a collection of display names or strings that you can't select a value outside of so you can think of all of the different so I'm just adding different enumerator enumerators here and you can think of all the different movement speeds that we can have so you can have an idle speed you can have a walking speed you can have a jogging speed and finally you can have a sprinting speed now save and close this and over here in our speed let's search for our movement speed enum yeah here it is movement speeds and now uh this speed is going to take one of the values that we just added in our enumeration uh if we compile and Save and Go back to oh actually let's add another thing let's add an output here which is the speed value and now this is going to be float so that the person implementing this function can return what the new speed is in terms of absolute numbers so compile and save back to our enemy Base Class and we'll see that a new function popped up here to implement in our interfaces so let's double click it and we want to provide a value for the speed and also set it on our character movement components so drag off of your character movement component and say sets Max walk speed and whatever we set here we're going to return at the end so depending on what input we're getting we want to change this max speed so what I'm going to pull out what I'm going to do is pull off of this and say select float and in your select if you plug in your enum um you can change oh actually just do select not select floats and if you plug in your enum here to this wildcard then it's going to give you a different float value for every uh value in your in your enum so for idle we're going to set it to zero for walking let's say 100 jogging let's say 300 and sprinting 500. um and now we want to call this function in our Behavior tree just before we move along the patrol routes and again to call any function Behavior tree are going to create a task for it put it in our tasks folder and call it BTT set movement speed event receive execute Ai and events true finish execute and uh what we just like we did in the Move Along Patrol point we're going to call our function which is set movement speed and we don't need to cast as well here but what we do need let me just plug in the success what we do need is a value for Speed so let's promote this to a variable and call it movement speed and click on the eye icon so that we can pass this value from our Behavior tree all right and now back in our Behavior tree let's call this task uh what was it called set movement speeds and set the speed to walking so when we're in a passive State we're going to set it to walking and maybe here in our Chase player uh let's set movement speed to always be running to make sure that we are sprinting to make sure that we Sprint if we're chasing the player but walking if we're patrolling um and of course I haven't talked about how to switch between states this is going to come just in a second now um all right so let's see what this looks like now if I press play now the enemies just casually strolling along the uh Patrol points instead of running between them now this looks a lot more like patrolling than the other one nice um also one one thing you can do is that if you want if the enemy is far away from the patrol path and you want them to run to the first point and then start patrolling you can simply call the set movement speed after the Move Along Patrol route so now if I do this the enemy runs to the first point and then starts casually walking that's this is useful in case the enemy is far away from the patrol path and wants to quickly go to it and then once they're there they just Patrol normally all right now one more thing we still have to add here is that what happens if we don't have a um Patrol route so if the enemy doesn't have a patrol route we need to handle that state as well so to check if something is the case or not we need to add a decorator so if you remember from the last one decorators are sort of like if conditions like we used for the is wielding sword so we're going to create a new decorator off of blueprint base put it in the decorator folders call it um has Patrol route now go over here to functions override the perform condition check AI and all we want to do is on our controlled Pawn we want to get our Patrol route as a message no casting needed and check if it's valid now use the is valid function not the macro because the is valid function returns a Boolean value that we can just plug in here all right and that's our decorator and we don't want to put the decorator on um this node alone because we don't want any of this to be done if the enemy doesn't have a patrol path so let's do a selector here off of roots and if the enemy has so we're gonna add decorator here so if the enemy has a patrol route then go into the sequence otherwise um just I don't know wait so here maybe you want the enemy to roam around or do something else if they don't have a patrol for me I'm just going to make them wait for like 10 seconds and this is going to keep repeating so they're not going to wait for 10 seconds and then do something no they're just going to keep waiting forever I'm going to change this one this selector to be our passive States and this one will be our petrol all right so this is what our Behavior tree looks like now we have a combat State here let me move it over here we have a passive States here but we don't have a way to select to switch between them and obviously to do that we need a selector node and under a certain condition we're going to be in the combat State under another condition we're going to be in the passive States but what is this condition this is going to depend on the state the enemy is currently in so we need another enumeration here that tells us all the possible States an enemy can be in so I'm going to right click search for uh enum once more and call this um AI States so what are all the states the anime can be in well we already know that there is a passive States and there is an attacking state uh maybe there's also a stunned or staggered States like if they're taking a hit and they need to play hit animation um we can just call this Frozen they can be um investigating we're going to be doing also things like enemy here's a sound that goes to investigate so there's going to be in investigating States and of course the anime can be dead so there's going to be a dead state now these are all the states that we have but to be able to use them in the behavior tree we need them to also be in our blackboards so if we go back to our Blackboard here you see that we only added one value which is the attack Target so let's add a new key of type enum this time just call it state and over here are the key type make sure to select your e underscore AI state that we just created and if you recall how we actually set a value to our Blackboard keys uh is over here in our AI controller AIC underscore enemy base um we set a value just over here so um I can also do the same thing get the Blackboard set value as enum and just um yeah gets a AI State literal so if you search for literal enum States you can just say a passive and plug it in here and the key name also promote that to a variable like we did with the attack Target so right click promote a variable and call this state key name and compile to give it its value and remember the value always has to be exactly what you wrote in your Blackboard so I wrote just States but I'll still copy and paste it to make sure I have no typos and if I do this now the state is set to passive and if I do this the state is set to attacking but this won't change anything yet in our Behavior tree because we are not using [Music] um these states now we want to check if the state is equal to combat or attacking go into this and if the state is equal to passive go into this to do that you can add a decorator that comes built in with the behavior trees so right click add decorator and search for blackboards now this Blackboard decorator allows you to check certain things about Keys you have in your Blackboard so if I click on it I can say the key that I'm checking something against is the state key and I want to check that it is equal to so you have equal to less than greater than lots of conditions but what I want to do is check that it is equal to um attacking so if the state is equal to attacking we're going to go into this and over here we're going to want to add the same decorator Blackboard click on it state is equal to passive then we want to go here um great so what did we start our state off with we started off with passive okay so if I play the enemy should be passive and patrolling excellent now if I change it to attacking the enemy should default by attacking me there we go pulling out a sword and attacking lovely um now let's actually create functions to switch between these two states so I'm going to take all of this copy it create a new function here and call it set State as passive just paste it in here and I'm going to duplicate its command D and say set State as attacking now the reason I created two different functions for them and not just one function that takes in the new states is that because attacking also needs to take an input that passive doesn't and that is who am I attacking and that's going to be our attack targets of type actor object reference and here we are not setting values enum actually we are getting the Blackboard and set value as oh no sorry the states we are setting value as enum it's going to be attacking but we are also setting a new value which is our attack Target uh which we are also setting here so I'm gonna copy this plug it in here and of course instead of get player character let's just plug in the attack targets all right so this allows us to call this function give the enemy different targets to attack um and because I did this I don't really need the delay anymore and let's set our default state to passive so set State as passive this is going to be our default States now I want just a quick way for now to debug to switch between the two states so I'm going to create a function to do that in our player so over here in my BP player find somewhere empty in the graph and I'm going to create a not a custom event a keyboard event one so when I press one on the keyboard what I want to do is get the actor of class uh enemy base I want to get their AI controller and I want to call set State as well I didn't compile did I no I did okay oh I first have to cast it to our AIC enemy base plug that in here and now I can call set State as passive or set State as attacking um now I want the first time I press one to set it to attacking second time to set it to passive and keep switching between them so to do that I'm going to use a flip-flop node and what flip flop does is that the first time you call it we'll do a the second time you call it will do B so let's um yeah let's plug this to B so second time will be passive and first time will be attacking and the attack Target will hero just be self because I'm already in the player so reference to myself um all right so now the enemy should switch between states um as I press one so the enemy is now attacking well why is the enemy attacking actually it should default to passive uh enemy starts set State as passive oh yeah because this one is not passed okay now it's passive yeah so enemy starts as passive and if I press one and if I press one yeah and me pulls out a sword okay press one twice now if I press one the enemy attacks but you'll notice something that if the enemies following me now I'm pressing one the enemy will keep following me and only when they reach me and finish the combat State then they go back and they don't clear the focus so obviously there's a lot we have to fix here let's start by the first one um if you notice if the enemy is moving along the path and I press one they wait a bit before actually moving to me because they're finishing the task they're already on and we don't want that we want the enemy to see what's of higher priority and ignore what they're doing to do something of higher priority and this is actually what this Blackboard decorator gives us out of the box if you check over here there's something called a notify Observer and what does the Observer abort so notify Observer is what are we observing when the result changes or when the value changes result changes means the state changed from attacking to something else and value change means that it just changed but it could be changed the same value so I'm going to do on result change because we want to know if this state changed to something other than attacking you can tell it's abort self lower priority or both and abort will just send an abort signal to all of the tasks or any task that's currently running in the tree so I'm going to say aboard itself and you'll see that everything in green will be aborted or canceled if the state changes from attacking now if I say abort self or lower priority lower priority now also marks these as blue so these are also going to be aborted and if I do both now everything is marked this is lower priority remember because this is on the left of this and execution runs from left to right so anything on the left is of higher priority than anything on the right so for now I'm just going to abort self because yeah that's the only thing I want to change if the state changes and for Passive I want to do the same as well so on Observer Observer abort so I'm going to choose self um now this is going to fix some things but not all let's see what we have so now if I press play now the enemy is running along if I interrupt her and press one he switches immediately to the attacking but is still moving along um the same Patrol point and now if they're chasing me and I press one that they stop and go to patrolling immediately now let's fix this first one where they're moving and then they switch um now why does this happen this is because even when Move Along Patrol points uh receives an abort it doesn't do anything to this AI move to because it doesn't know that I'm running a task here that takes time um so we need to tell it to uh what to do when it's uh receives this abort so to do that you can add a new event so here we receive executes you can add a new event that's called event receive abort and abort Ai and call also similarly to finish execute there's Finnish abort and here we can say what we want to do when this task is aborted so for instance what we want to do is to stop moving immediately um so on our um on our Pawn we can say sorry on our controller we can say stop movement and then plug in the upwards the Finish upward now this should look a bit better enemies moving press one there we go they stop immediately when I press one and interrupt them um one more thing we want to do is when the enemy goes back to patrolling they're still carrying their sword so now is the time to create the sheath sword or unwield sword animation and blueprint and be sorry Behavior tree tasks that I showed you [Music] great so back here in our base enemy this is the Wheeled sword function that I added and now I'm playing a montage and at the specific point of the Montage I'm spawning The Sword and on complete I call on wield sword now let's see what this Montage looks like just like this unsheeting the swords um and one actually interesting to know about this montage is that it uses the sheath sword animation which plays the opposite direction so this is an enemy putting the sword back in its place but for the um uh for the Wheeled swords uh montage um I selected the animation and set the play rate to be negative one which means it starts from the end or it's reversed so we're going to create a new Montage off of this sheet sword animation so right click create and a montage we'll call this Montage um wheeled uh sort oh sorry we don't want to wield we want to sheath or put the sword back in its place so sheet sword yeah and this animation looks good but also to fix the leg ik issues go here add curve disable leg ik double click the curve right click add key at time 0 value 1. and also we want at a certain point in this Montage to um delete the sword the sword itself from our world um otherwise the enemy will remain holding it of course the correct way to do it is to attach the sword to the enemy's hip but yeah for now we're just going to delete it um so probably at this point right here so you can go here and under the notifies track right click and add notify select Montage notify and we'll give this a name call it [Music] um I don't know um let's say drop sort so at this point they dropped the sword back in its place and we want to delete it from the world so in our enemy enemy base here we're going to create a new function our new custom event and call this sheath sword and what we do here is play montage the Montage we're playing is the sheath sword montage in our skeletal mesh components play rates ones Palm position zero everything here is fine and off of on notify begin this is which this is called when a notify happens so we're going to do a switch statement um now you can switch on notify name so pull off this and say switch and do this on notify begin and switch is similar to a branch or an if condition but instead of checking if something is equal to something it just does it automatically and gives you a pin for it so we're going to go here and in the pin options add the name that we just added so drop sword this means that if the notify name is equal to drop sword then this execution pin will happen and at this execution pin we want to delete the actor that we spawned previously and also set is wielding swords to false so we do that first let's actually create a variable out of this actor so promote this to a variable and call it the sword actor now we can easily get this sword actor and say destroy actor and set well set is wielding sword to volts and we need also to call an event dispatcher when this happens so I'm going to call this on faith sword and we're going to call it here on completed you can also set your uh is wielding sort to false on completed as well um but yeah I prefer to do it here when we actually destroy the actor in case something happens and they're interrupted um which I should actually also do here as well in the wield let's do it here is wielding sword is true only after we spawn the sword art so we need to call this from our Behavior tree so as usual go to behavior tree new task blueprint base tasks folder and call it BTT sheath sword event receive execute Ai and finish executes um now here we're gonna have to cast to our Pawn to our base anime again because this is not a function that's common to all enemy AI types that's why I'm not putting it in the um interface and here we're going to call um sheath sword pull off of our base enemy and say a sign on the sword so finish on sheath and here is when we call our finish execute again as a reminder we bind and call an event dispatcher to make sure that we only finish once the animation is done and not once the animation starts all right so now we have a task let's call our task in the tree um now we want to call this as soon as the passive state begins um but we also want to make sure that we are actually wielding the sword before we unwield it so how do we do that again similar to what we did here we had a selector and if is wielding sword we um wield it or if we're not wielding sword wield it otherwise we chase the player so here same thing off of the passive state we want the selector and in this selector we check if we are our first desk is to what was called sheath yeah sheath sword and the second task will be this uh other sequence of actions here oh actually no this is not a sequence this is a selector so here we also want another selector because if you recall we were selecting between either waiting or patrolling if they have a patrol route um and in this selector we're going to right click and we need to add a decorator we already have this decorator for is wielding sword so if is wielding sword we will do sheath otherwise we will go to this selector which checks if has a patrol route it patrols otherwise it waits um all right let's see how this looks like now play enemies patrolling interrupt the enemy and we unsheath the sword attacks me now if I press one again enemy sheets The Sword and goes back to patrolling great uh one thing we should fix though as well is the focus so if I press one now enemy is not focused on me while unsheathing but that's not the main issue the main issue is that now if I press one while they're focused on me they're going to try to Patrol without clearing the focus of course that's not what we want so let's uh oh all right so let's fix that um let's do that here so right as we are about to Patrol let's call clear Focus that should fix uh this issue um and also yeah we can do it here as well but yeah it doesn't really matter uh because if we're waiting yeah yeah actually this should be a sequence so weight should be in a sequence with clear Focus and weights all right so this is called the patrol sequence this is let's call this the idle State and this is the patrol States uh huh and also when we are beginning to attack so here in the is wielding sword we want the enemy to look at us while they take out the sword but to clear Focus before they attack us which we're already doing here um so let's also change this to be a sequence of actions instead of just one action and in this sequence we want to First Focus on our targets which is the attack targets and then then wield the sword uh let's move all this a bit down here all right so let's see what this looks like now so enemies patrolling now if I interrupt them with one they look at me then take out their sword and if they're chasing me and I press one they stop immediately unsheet The Sword and go back to patrolling excellent and now I also wanted to add perception in this tutorial so that instead of us pressing one the enemy actually sees us and then starts attacking but perception I'm Gonna Leave it to the next part so that we cover very complex perception such as perceiving damage perceiving sounds perceiving a sight and the enemy will react differently to each perception that they have so to do that I'm going to leave this for its own tutorial so we can really uh dive into making a complex system so I will see you there and thank you for watching [Music]
Info
Channel: Ali Elzoheiry
Views: 68,957
Rating: undefined out of 5
Keywords: Behavior Trees, Behaviour Trees, AI, Enemies, Unreal Engine, patrol, patrolling
Id: WFV5IewGks8
Channel Id: undefined
Length: 49min 24sec (2964 seconds)
Published: Mon Jun 05 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.