Smart Enemy AI | (Part 1: Behavior Trees) | Tutorial in Unreal Engine 5 (UE5)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] foreign to this Unreal Engine 5 tutorial series on how to create smart enemy AI now smart enemies are ones that react to their environment like this enemy here that searches for a wall to hide behind and then after a few seconds it comes out attacks the player and hide again now smart enemies can also react to the player's actions like this enemy that teleports if the player gets too close to it and also it even reacts the player shooting an arrow at it and Dodges away from the arrow as you see here now if I damage this enemy and bring its Health low enough it can even recognize its health is low and react to its own internal state by healing now to do all of this we're going to be using a lot of AI tools that come with Unreal Engine such as Behavior trees that you see here to control the enemy's actions also the eqs or the environment query system which allows enemies to collect data from their environments and to position themselves in a smart way and make smart decisions about where they should be in the world and what's around them we're also going to be set up a perception system that allows enemy to perceive sounds and sights uh like this enemy that's perceiving um the sound of my arrow hitting the floor and it goes to investigate now in part one we're going to set up a basic Behavior tree and an AI controller that will allow the enemy to chase the player around like you see here and once the enemy reaches a player it will try to attack wait for a few seconds and then repeat so let's get started so I'm starting off with the third person templates here and I have um I'm also using Unreal Engine 5.2 which just came out at a time of recording this video and I have two small additions to this template which is uh this beautiful sword mesh that I just created really quickly to um yeah have a sword to swing around and this sword slash animation which I got from miximo and retargeted to the Unreal Engine mannequin I'm going to leave all the assets including the miximo to Unreal retargeter um that would allow you to retarget any asset from miximo to the Unreal Engine mannequin in my patreon I'll leave the link down in the description if you want to download those um all right so first thing we're going to do is let's create a player and an enemy so I'm going to right click here in our content folder and create a player folder and create one for all of our enemies we're going to have multiple enemies um and now in third person blueprints I'm going to duplicate Ctrl D and duplicate the third person character and create called player and move it to our player folder and also open up this third person game mode and change the default Pawn class to be your BP player instead of third person character um and now also let's go to the player duplicate that and call it BP enemy base and move it to our enemies folder and the reason I'm calling it base is because this is going to be the base class that all the different enemy types inherit from um all right let's open up this base enemy and delete everything here we don't need any of that we don't need a follow camera we don't need a camera boom and also let's change the mesh to be Manny underscore simple instead of Quinn and also the animation blueprint to ABP underscore many great um now back here in our level let's pop in our enemy in the world and now we have a player and we have an enemy oh and let's remove this clipping that happens when the camera gets in front of the enemy so back here in our enemy base on our mesh scroll down to Collision and switch it to custom and ignore camera and do the same for the capsule as well Collision custom and ignore camera compile and save now there should be no more clipping all right now what we're going to do now is add very basic behavior for our enemy moving and attacking things like that and we're going to do it all in Blueprints and then move it to behavior trees to show you how you can achieve the same simple results in a behavior trees and of course add more complex logic and behavior to it so let's first open up our event graph for the enemy and add a custom event [Music] call this Chase player and what this will do is it will call AI move to this one and AI move 2 just takes a pawn which will be a reference to our self which is the enemy and either a destination or a Target actor so he wanted to move to our player character so pull off of here and search for get player character right now we only have one player and one target so it's always going to be the player and the acceptance Radiance is how far it should stop before reaching this target so let's say 150 units or 1.5 meters um then on success let's add a delay let's wait for two seconds and then start chasing the player again great now search for event begin play and call this Chase player on begin play [Music] um now you'll notice that actually nothing happens and the reason is the AI move to function requires there to be a nav mesh in the world to tell the AI how to move and how to navigate so we go into our level here uh let's see the whole level in your quick add menu search for nav and take the navmesh bounds volume put it somewhere here and then just scale it until it extends the full bounds of your level um oh it's a bit too big yeah something like that and then if you press p you'll see all the areas that the player can move make sure that everything is green great now all the green areas are the areas where the enemies are you can uh can navigate to P again now if we play the Chase works the enemy chases us and after two seconds starts chasing again great now let's um let's give the enemy a simple attack function so back here in our enemy again add a custom event and call this attack and what attack will do is we'll just play an A Montage so search for play montage and make sure to select this one not the anim Montage because this one has a lot of execution pins like oncomplete on interrupt that we'll be using as well now it takes a skeletal mesh which will be our enemy mesh and we don't have any Montage yet to play so let's go ahead and create that um so in our animations folder I showed you we have this animation I'm going to right click and say create anim montage and call it Montage underscore sword underscore slash wait now you can pop this Montage here or of course select it from the drop down um for now this is all the attack is going to do just play this montage so now as soon as we reach the enemy sorry reach the enemy reaches the player let's call attack and let's see how this looks like now you see the animation looks quite strange and I see the Feats and how the and the characters leaning forward now this is not an issue with the animation itself because you can see here that it looks fine and it's actually an issue with the foot ik that comes on the mannequin what that is if you look here if I'm standing on an uneven surface like this the feet are always trying to find the ground as opposed to floating in the air like this um now this is a feature that's in the animation blueprint of Manny but it also doesn't play well with animations that move the feet so I'm gonna detour really quick from the AI tutorial and show you how to fix this in a couple of minutes so if you go to your content folder under characters mannequin animation you'll see this ABP Manny and it has here a control rig that does the ik and an alpha value now if I switch this Alpha value to zero you'll see that the animation now plays properly but we lost the foot ik functionality so we want to keep both we only want to disable this when an animation a specific animation is playing so let me show you how to do that in your Montage animation here um the sword Montage we're going to add a curve that comes with third person templates called disable leg ik and I'm going to set the value of this curve to double click the curve right click add a key and set the value to 1 at time zero so that's the value of the keys is just always F1 and then back here in our animation blueprint for the Mani I'm going to pull off of the alpha select float and if the curve's value is greater than zero I want there the alpha to be zero otherwise I want the alpha to be one so to do that I'm going to get a curve well get curve value and the name of the curve is disable leg ik and if this value is greater than zero then set the alpha to zero otherwise set the alpha to one great let's see how this looks like now animation is working properly and foot ik is also working properly nice so this will be very useful for any animation that moves the feet of the um uh the mannequin so now back to our um AI tutorial now we have a very basic uh AI functionality the enemy chases the player once it reaches the player does this attack montage and then just repeats so I'm going to show you how to move all of this over to behavior trees and then add more complex logic to it and we're going to start building now all of the behavior of the Enemy Inside the behavior tree instead of inside blueprints now let's open up our content drawer again and uh let's inside this enemies folder let's create a new folder and call it AI I'm just going to have all of the AI functionality that we'll be creating throughout this tutorial series now the first thing we want to create here is a behavior tree and a Blackboard now both of these always come together so let me show you what that looks like so right click and search for Behavior tree or you can also find it under artificial intelligence Behavior tree I'm going to call this one BT enemy base also enemy base because we can have a different Behavior tree for every different enemy type like one for a ranged enemy one for melee enemy one for defensive and so on and also under artificial Intel just create a Blackboard and call this BP enemy base as well now if you open up this uh Behavior tree you would you want to give it a Blackboard or tell it which Blackboard is associated with but since we only have one Blackboard it already found it on its own now I'm going to quickly describe what a behavior tree is and how blackboards are used but I'm not going to dive into too much detail until we actually start implementing the behaviors so that you'll see more in practice how it looks like now a behavior tree is just a sequence of actions or tasks that an enemy AI can perform and it's always um depends on two things if you pull out here you can either create a selector or you can create a sequence now a selector selects between different tasks that can be done so you either attack or you heal you either run away or you teleport whatever different task you're trying to pick from the selector is the node you want to use and sequence is a node that does a lot of tasks in sequence now of course they can be since it's a tree they can be nested like this and you have sequences followed by selectors and so on and at the end you really have to run a task so these are all the tasks that come with the behavior tree or with Unreal Engine but you also have you can also create custom tasks for yourself so um one thing to note about selectors is that they will always run the tasks from left to the right and the selector only succeeds and moves on to the next node if all of the tasks under it succeed as well so if I have a move to then a weight then I don't know play animation or something this one has to succeed and this one has succeed this one has succeed and they can fail if for example the AI couldn't reach the move to the Target then it failed then it won't do these it will go back up and see try to run it again sorry this is all under sequence by the way not selector now selector is different that it tries to to find the first one that succeeds so if I have a selector here and move to succeeds then it's not going to go to the weight because move 2 already succeeded but if it fails then it's going to try to do the weight and if that one fails then it's going to start to do the play animation and so on um now this will make a lot more sense once we start actually doing it so let's add some very basic Behavior the same behavior that we have here in fact in our blueprint um all right so first thing we want the enemy to chase the player so let's add a sequence node here because we're going to do a sequence of actions now and the first one is um luckily a task we already have which is move to now the way you um you can think of tasks as like functions in the behavior trees and the input to the function is a Blackboard key now what is a Blackboard exactly now if you go here to the Blackboard tab or open your Blackboard from the content drawer you'll see that the Blackboard is just a collection of variables or keys that can be used inside the behavior tree so you can always add new keys here of different types and then you can start assigning values to them so for example in our Behavior tree we want to move to the player character so we need the key that points to the player character or whatever we're moving so I'm going to go to my Blackboard and create a new key of type objects what we want it to be of type actor but here you can only select high level types um I'm going to call this attack Target I can also call its player attack Target is more Generals in case we want the enemy to attack other targets than the player and on the right here under key type choose actor here as your base class so inside this actor Target sorry inside this attack Target in our Behavior tree we can now select it as the move to Target so now I'm telling it move to the attack Target everything else here is similar to what we set up already so acceptable radius is 150 and yeah we can leave everything else the same you can also rename this node to maybe call it move to Target now we have this attack Target set up in the Blackboard but how do we actually run the behavior tree and assign values to the Blackboard variables all this is handled inside the AI controller now if you go to your base enemy and look at class defaults search here for AI controller and you'll see that any pawn class already comes with the default AI controller associated with it now the eye controller is sort of like the brain of the um of the pawn but we want to create our own AI controller to run the behavior tree and do other AI related things so over here in our AI folder right click create a blueprint class and the type is search for AI controller now you have also detour crowd AI controller and grid path AI controller and this is for like if you have hundreds of enemies or like simulation of crowd and you want them to do Collision detection and things like that then you'd use this one and grid path AI controller is if you have enemy AI or just AI in general that are moving in a grid pattern for us we're just going to use the base AI controller class and call this AIC underscore enemy underscore base again you can have a different AI controller per enemy type um now if you open up this AI controller and go to the event graph um looks similar to a normal blueprint because it is a blueprint at the end but we don't need this event to begin play and event tick we need a new event called events on possess now this is the event that's called when the AI controller possesses or takes control of a pawn which can happen multiple times so you better use this rather than event begin play to set up your behaviors now you can say something like run Behavior tree it's a function inside the AI controller and it takes a behavior tree that we just created here and that's it that's really how you run a behavior tree but how do you assign values to the Blackboard well if you look on your variables here on the left and by the way if you don't see this click on the gear icon and say show inherited variables you'll see a variable called Blackboard and because this Behavior tree knows which Blackboard is associated with it then this Val this variable will already have of the value of our Blackboard so you can get the Blackboard here pull off it and say set value as now we're setting the value of a Blackboard key and Blackboard keys can be of any type here so we need to specify what type you're trying to set so we want to set our attack Target key which has a type of object so use set value as object and the key name here has to be exactly the key name that we set in the Blackboard now you can just pull off and say make literal whoa and write the value here but I always prefer to make these variables so right click promote the variable and call this one attack Target key name now compile and save to give this a default value I'm going to actually go over to my Blackboard and copy it to make sure I have no typos and paste it back here now this is the key name but what's the actual value the value is the get player character so we just set the Blackboard key with this name to this value now one thing you should know is that on possess actually runs before on beginplay so get player character will probably not have a value at this point so I'm going to add a really short delay can be even a delay of zero we just want the player characters execution or begin play to finish first um great now we set up our AI controller we set up our Behavior tree now we need to go back to our enemy class our base enemy search for AI controller here and choose the one that we just created so we're switching the AI controller that's using um now if I go over here in our Chase player function I can delete it so we're not doing anything on play but let's see what um how the enemy behaves now so you see the enemy is still chasing us even though I'm not calling our uh Chase player on begin play I can actually delete this Chase player altogether I'm Gonna Keep the attack um and now you'll see that it's still working now let me show you how you can see the behavior Tree in action so I'm going to take this Behavior tree and just put it somewhere here on the right let's make sure everything is in view and I'm gonna play and you can see here the how it's this the sequence of actions that it's doing so it keeps trying to move the target over and over and over again and it's already at the Target so it's not doing anything but this is how you can debug your tree and see what's going on so let's add more functionality to it um we had its weight right so when it moved to the Target it waits two seconds so now I'm going to add the weights and the wait time is two seconds let me also keep this on the right here so you can see what's happening now the enemy reaches us Waits two seconds and then re restarts the sequence excellence we also had the enemy attacking us but of course we don't have a task for attack so this is when we start creating our custom tasks um all right so to do that first let me create a new folder inside our AI folder and call this one tasks and then in your behavior Tree on the top here say new task select where you want it to be and we're going to name it BTT which stands for Behavior tree task and we'll call this default attack well default attack great um now a behavior tree task looks like a blueprint as well and has two very important execution nodes that you have to remember so we're going to right click here and say um oh sorry AI receive so this event receive uh execute AI this one uh this is sort of your begin play or what happens when the task is starts executing and it will always give you the pawn that's executing this task or the pawn that's the behavior tree is running on and the AI controller as well and a second node is finish well finish execute now you have to call this finish execute when you're done and whether it's succeeded or not otherwise you'll be stuck in this task forever so don't forget to call this when you're done and everything in between is what the actual task does now this is the attack task and we know which Pawn we're running on um but we can cast to our enemy base because we know we're running on this enemy and We Know The Enemy also has an attack function so we can just call attack and then we can finish executes um this is not the exactly right way to do this and I'll show you why in a second but let's see what this does so again take our tree put it here on the right and now let's add our custom task that's called uh attack um and remember that this execution is from left to right so we actually want the attack to be before the weight so reach the enemy attack then wait two seconds or reach the player now let's see what this looks like so it's reaching us it's attacking and it's waiting two seconds great now what if I didn't have this weight what will happen if I didn't have the sweets this will happen you see the enemy is stuck in the attack state but it's not actually attacking because it's trying to attack then it's finishing the attack and moving back to move Target it's trying to move it to Target but then it's doing the attack so it's jumping between these two nodes really quickly because it doesn't actually wait for the attack to finish before going back to the previous task um and we want to fix that um so right now if you open up your default attack task you'll see that we call Finish execute right after we call attack but we don't actually wait for attack to finish that means that we're going to finish executing as soon as we enter uh this task and then when we finish executing then we go back up the tree and try to execute whatever we had else here which is move to Target that's why it keeps bouncing between the two states um so let's actually wait until attack is finished before calling finish execute now how do we do that now if you go here um well actually I need to remove this yeah so if you go here on the left we're going to add an event dispatcher which is what I actually just deleted now because I had it before but let me show you how we're going to add this and we're going to add an event call it on attack end and then call this when uncompleted of the Montage or on interrupted so whether the Montage completes or interrupts in both cases we want to end this attack now you can pretend that interrupt is a fail and completes a success but we're not going to do that right now we're just going to treat both both as a success so back here in our default attack task pull off of the base enemy and say assign on attack end and call this finished attacking and now we are going to plug in the Finish execute on this event instead of immediately after attack so let's see what this looks like now move the behavior tree here now if I debug this now it reaches me stays in the default attack so you'll see it stays highlighted then moves back to me to move Target only when default attack finishes so now it's still in move Target because it hasn't reached me reaches me default attack back to move Target and so on but it keeps attacking over and over again if it's already reached me and that's why I'm going to add back the weight node so let's say wait for just one second between attacks all right now this is a very basic sequence I named the sequence here Chase player you can rename the sequence uh however you like here as well um but we want to add more to it and first thing we want to add is fixing a bug that you'll I'll show you here now if I'm behind the enemy attack um the attack radius or the enemy is still within the radius so it keeps attacking even though it's not looking at me so we want to make sure the enemy always looks at the player when it attacks so to do that we're going to go back here to our Behavior tree and add a new task use blueprint base as the base and call this BTT Focus targets again call receive execute Ai and finish execute always start with these two and off of the uh the owner controller there is a function called set Focus and this takes a an actor to focus on and this actually wanted to be whatever our attack Target is now how do we actually pass input into our tasks now inputting the tasks will only be passing or mainly be passing in the form of Blackboard keys so go over here in the variables and create a new variable call it attack Target key and this is going to be of type search for Blackboard Blackboard key selector and click on the eye icon to be instance editable now this Blackboard key selector is actually a type specific for the Blackboard but it's only the name of the key but not the actual value of it so we're gonna pull off of it and say get value as and we know that the value of the attack Target is an actor so say get value as actor and then plug this actor here compile and save and now back in our Behavior tree right before we attack we're going to call this Focus Target and you'll see here on the details panel we have this attack Target key which gives us a drop down to select from one of our Blackboard Keys now we're going to select attack Target here also just for good practice I'm going to add this to a category called keys that way in our Behavior tree here you can see that it's under a keys tab now let's see if this works and now we're behind the enemy yes the enemy is um focusing us now one very important thing um You probably don't have this by default uh I must have changed it at some point but if you go on your character movement uh in your base enemy pawn and search for rotation and make sure you have use controller desired rotation and not Orient rotation to movement because if you have Orient rotation to movement then set Focus won't do anything so make sure on your character movements component in your base enemy class to use controller desired rotation great now we need to fix another issue now after attacking us the enemy stays focused on us which means that they're gonna strafe like this yeah that's not normal behavior we want the enemy when they're moving and not attacking to not be focused on us to be looking at where they're going so let's pop back to our Behavior tree create a new task off of blueprint base again uh put it in our tasks folder and call this BTT clear Focus again search for event receive execute Ai and finish execute with Success Through and then off of owner controller just call clear focus and it doesn't take any input very simple task now basically this is what you'll be doing when dealing with behavior trees you're going to be creating very simple and focused tasks that do one action and you're gonna have a lot of them and that's really how Behavior trees work um all right so back in our Behavior tree here after we finish attacking or actually maybe right before we move to the Target always clear Focus first then move to the Target then once you reach the target Focus that Target and attack that Target then wait one second and repeat the whole thing over again so let's test it again enemy is focused on us now if we go somewhere they are not strafing anymore great they look where they're going perfect um now one last thing I want to do before we end this part one is actually give the enemy a sword because right now the enemy is just hitting us with their fist so let's put a sword in their hand so go over here to our base enemy class and under mesh double click your skeletal mesh assets and I want the sword to be added here to the right hand so I'm going to search in the skeleton tree for hand underscore R right click that and say add socket now a socket is just a scene on attached to this mesh that we can attach different actors and uh and meshes to so I'm going to call this socket hand underscore r underscore sword underscore sockets now if you want to see what a specific mesh will look like attach this sockets you can say add preview asset here and select the mesh you want in our case it's sword now you can transform this so move it around until it's in the position that you want oh and also on the right here you can use specific animation and select the animation you want so that you see what it actually looks like in your specific animation all right so let's move it a bit here a bit over here yep I think that's good for now it doesn't have to be perfect um and I'm going to right click and remove attached assets again this is just a preview it doesn't really matter um so back here in our enemy we actually want to wield the sword so let's create a new custom event and call it wheeled sort I think that's how you spell wield now we want to spawn an actor or a sword actor and attach it to our mesh but we don't have that sword actor yet so let's create it in our contents folder I'm going to right click and create a new folder called weapons and inside weapons I'm going to create a blue blueprint of type actor and call this BP sword that's going to be a very simple weapon it just has a static mesh component call this our sword mesh and on the right here just select your sword mesh assets and if you do have Collision on your weapon make sure to set it to no Collision otherwise your enemy will collide with it and maybe just fly off the screen um all right now that we have this sword let's go back to our base enemy and say spawn actor from class select our sword actor and um the spawn transform you can just set anything for now I'm just going to say get actor transform it doesn't really matter because we're going to change the transform by attaching it to our mesh so pull off of here and say attach actor to component and we're attaching this actor to our mesh component and the socket names the sock we just created Created which is hand underscore r underscore sword underscore socket now very important here for the location rotation and scale rules to be snap to Target so that they take the location rotation and scale from the socket instead of where they actually spawned that's why this doesn't matter but we have to add something because it's a required input field all right now we can just call wheeled swords here in our begin play and you'll see that the enemy is carrying a sword but let's actually call it in a smart way and make it a behavior tree task um so now I'm gonna go over here back to our Behavior tree create a new task and put it in our tasks folder and call it BTT underscore wheeled weapon or wheeled swords that's what we call this right yeah um now this again event receive execute AI and finish execute off of the pawn we're gonna cast to our enemy base and call our wheeled swords now there's something really important I want to show you here um if I call this task from our Behavior tree let's say in the beginning of the sequence here we say wheeled swords this is going to be called multiple times every time the sequence runs it's going to call wheeled sword now we only want it to wield sword if it's not already wielding the sword to do that we will add a decorator and decorators are sort of like if conditions um and it will tell this wheeled sword to only run if the enemy is not currently wielding the sword so let's go ahead and create that decorator so up here on the top go to new decorator and select the blueprint base decorator I'm going to create a new folder here and call this one decorators and we're going to name this decorator BTD which is behavior tree decorator and call it is wielding weapon so it's going to be true if they're wielding any weapon let's just make the sword right now because that's we only have a sword all right so unlike the task where we add an event receive AI execution we're going to go over here on our functions and under override we're going to find a function called perform conditional check Ai and we're going to override this function now whatever we return here is what this decorator will be returning so we want it to return true if the enemy is uh wielding a weapon and false otherwise so let's actually go back to our base enemy class and add this variable so I'm going to add a variable here and call it is wielding sword um and this variable will be true we'll set it to True here after we call our wheeled sword function um all right so now back in our decorator here off of controlled Pawn we can cast to our base enemy and check if is wielding look sort and set this as our return value great and that's basically our decorator so how do we use decorators back here in our Behavior Tree on this wheeled sword task I can right click and say add decorator and select our is wielding sword so only if the decorator passes will this succeed so if is wielding sword is true we want to wield sword that's not right we want if wielding sword is false so we want to inverse this decorator and over here we have an inverse condition and you'll see about between brackets here it says inversed so that means that if wielding sword is false then make this node succeed but what if it fails if you recall we set a sequence if one node fails then it doesn't continue to do all the other we actually wanted to check if is wielding sword is not true then wheeled sword otherwise do everything else we don't want to just ignore all of this so then we have to actually then start using um a uh a selector now instead of a sequence so this will still be our Chase sequence but off of root let's get a selector and in our first part of the selector we're gonna pop in our is wielding swords or our wheeled sword task and on the right side of the selector we're gonna pop in our Chase player sequence what this means is that if is wielding sword succeeds then sorry if this decorator is succeeds then do is wielding sort if it fails move on to the next part of the sequence so it's either going to do this or that per execution of course once this finishes and is wielding sword becomes false again then it will always go to Chase player so this will then only be called once um all right so let's see what this looks like back in our base enemy yeah let's make sure we're not calling anything on begin play here and we should expect this Behavior tree task to only call wheeled sword once and never call it again all right yeah now let's see all right wheeled swords might have been too fast but it was called once and now it's only staying within this sequence so you see here it's only saying within the sequence and never going back to wield sword now I'm going to show you again because it happened really fast and ready yeah so it was called very quickly and then does it call never called again so that means that we only spawn the sword once which is what we want perfect and that's how you use selectors together with sequences and you can also name this selector so we can call it um wheeled weapon or attack or or chase so it's a selector and selects between wheeled weapon or chase we can actually also call this combat state which is good because then we'll in the next tutorial we're going to be adding patrolling States idle States stunned States and so on and we only want to make sure that this is done in the combat States excellent so then as I mentioned we're going to be covering perception States and so on the next tutorial so I'll see you there [Music] thank you [Music]
Info
Channel: Ali Elzoheiry
Views: 191,065
Rating: undefined out of 5
Keywords: Behavior Trees, Behaviour Trees, AI, Enemies, Unreal Engine
Id: -t3PbGRazKg
Channel Id: undefined
Length: 45min 31sec (2731 seconds)
Published: Tue May 30 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.