AI Behaviour in Bolt and Unity

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone i'm jim and in this lesson we're going to create ai behavior in bolt by making a patrol chase and attack finite state machine in order to jump right in i've created a package for you with everything you'll need it contains unity's standard asset third person controller an enemy free from the asset store it's a navmesh agent and it has a animation controller with the animations that we need a nav mesh waypoints that are tagged and a camera with the camera follow script i'm also including a field of view model i made along with a gradient texture the concept i'm going with is a minotaur in a labyrinth and the goal of the gameplay is to sneak around get caught and then escape through a near miss all right so the first thing to do is select your monster in my case the minotaur and add a state machine i'm going to create a new macro and i will save it in my macro folder and i'll call it minitar ai that starts us out with a state graph but let's select and delete that and instead start out with a super state which gives us a lot of flexibility for putting states within states and i'll call the superstate minotar ai inside our super state bolt sets us up with a start flow state and so i'm going to just rename that to patrol and then with control d i'll duplicate that and then make our other states which will be chase and of course attack i'm going to control d duplicate attack and make one more and i'll call this one minotaur perception this flow state is going to calculate some things we need for our transitions like the distance and the direction to the player at the start of the game i only want to patrol so i'm going to right click on chase and toggle off start and i'll do the same with attack the next thing to do is to right click on patrol and make a transition to chase and then do the same thing from chase to attack and then go back the other direction from attack to chase and then chase to patrol okay that's our overall structure so let's start with patrol double clicking on the patrol state we see that we start out with on enter update and on exit to make the graph full screen press shift and space delete the update and on exit events and we'll start with the on enter the field of view model changes color depending on the state the minotaur is in so drag out the flow from the enter state type material set color and then the color that i want the material to be is a light blue for the patrol state then we'll need to drag in the material that we want this set color to apply to so press shift and space click on your skeleton and find the field of view object and click on the material and drag it onto the material spot on that set color unit let's make another on enter state so select it and press ctrl d to duplicate it we're going to set the speed of our nav mesh agent and i'm not chaining these together because the two things we're doing are unrelated to one another so click and drag the flow from on enter state and type nav mesh agent set speed i'm putting 1.85 here for my minotaur you'll have to experiment to see what works for the skeleton along with the color of the field of view and the speed of the minotaur patrolling we also want to find our waypoints and set one of them as our goal ctrl d to duplicate another enter state and drag the flow out and type game object find game objects with tag and then the tag that we want is the tag waypoint so type that in with a capital w i'd like my minotaur to choose waypoints randomly because to go from one two three four and back again seems a little robotic to me so right click add a unit and type random range and then the one that we want is for integers which are whole numbers like the items on our list we see that random range is asking for a minimum and a maximum and we don't exactly know how many waypoints we have because it's not a fixed number we want to make it so that we can duplicate and add more waypoints or take them away pull out from the find with tag and let's get a count items unit that way we know how many waypoints we have and then we can run that number into max the first waypoint will be indexed at zero so keep zero for the minimum we'll use the number that random range gives us to get an item off of our list so if you click out the list from the find game objects you can find list get item and then connect the value from the random range into the index whatever item we get we want to set as our goal so let's make a variable for that let's call it waypoint goal and then let's make it of the type vector 3 because a vector is a direction and we are giving directions to our minitar holding the alt key and left-click dragging on the variable will make it a set variable unit and we want to have a patrol goal from the start so run the flow into the set variable for waypoint goal then connect up the get item to the set variable before we move on to moving our agent towards the goal let's group this together hold ctrl and left click drag and then let's call this group set waypoint goals for the movement let's start with an update event on update we want to check and see how close the minotar is to the waypoint goal let's get a vector3 distance unit and we can see on the unit that it's asking for two positions in space the first one type transform get position and that self means this game object the minotaur let's do another transform get position and then the second position is going to be the waypoint goal go over to your graph variables and then left click drag on our variable to bring it in which makes it a get variable unit now that we're able to find the distance between the waypoint goal and the minotaur or skeleton let's see if we're getting near the goal that way if we're close enough to the goal we can find another waypoint so add a less or equal unit and let's put in three meters now we want to create a branch because if we're within three meters we want to find a new random waypoint to go to and if we're not we just want to keep going towards the goal so bring the update flow in so we can continually check this and then run true out to the set variable and now it's time to send our navmesh agent towards the goal so i will type nav destination nav mesh agent set destination and the destination that we want is our waypoint goal and since a vector is a direction but not a point in space or thus a destination we're going to need a transform get position and then connect that to the target let's group together this bottom flow so hold ctrl and left click drag and i'll call this waypoint movement i want to include some extra tricks here for beginners because they may not occur to you let's make when the minotaur turns around a little bit more unpredictable by making a variable for this value of how close we should be before we find another waypoint i'm going to call it waypoint accuracy and let's make it of type float since it's a distance and attach that to our less or equal to since we want this value to be random let's add another random range unit and we only need to set this variable once for each white point so let's connect it up to the set variable for the waypoint goal and i'm just going to put 3 as the minimum and 5 as the maximum although a larger maximum number in here could be really fun hold alt and left click drag the waypoint accuracy variable to get a set variable unit and then connect it to random range and then let's group that up and call it waypoint accuracy randomness and the last thing we want to do on an update event is get our animator to play the patrol animation which would be walking so type animator play and then the state name that we want is patrol and with that we're done that's all we need for the patrol state now's a good place to save the project and check to see if your monster is moving around so we can see in bolt that the distance to the waypoints is getting smaller and then we can also see what waypoint we're going towards and we can see the random number that's being generated for our accuracy or how close we get to the waypoints before turning around let's make the chase state next and press shift and space to go into full screen and then i'll delete update and on exit all right let's do what we did before and do a material set color and then let's quickly go and grab that material again we could have copy and pasted this over from the patrol state but it doesn't hurt to go through again we grab that field of view material and drop it on the material and then this time i think i want to make the color yellow for the chase that works and then of course we want another enter state so ctrl d to duplicate that and we want to set our nav mesh agent speed on the chase state i want the minotaur to be faster than the player it's good that you have your own unique enemy for me in this because i think you'll learn a lot through tweaking the values to get them how you like so let's move our monsters every frame with update and similar to how we move the minotaur in patrol we want to use a navmesh agent set destination and our target here is going to be a scene variable because we might have multiple skeletons or minotaurs in our labyrinth all chasing the same thing so i'm going to type player and i will make that a game object variable and then i'm going to press shift space and grab my third person controller and drag it into the spot for the value shift space again and now let's just left click drag that and then there's a lot of aspects to a game object but we only want one we want the transform get position and that position in space is going to be our target and there's one more thing we want to do and that is to tell the animator to play chase and that's all we need for chase and i'll make a group for the bottom flow and call it chase player next there are some things we could use to know for all of our transitions and that's what this minotaur perception is all about another name you could give this is proximity calculations but perception made me think that it might be interesting later on to add something where the minotaur listens for the player let's start out with an update event so what could cause the minotaur to start chasing the player well the minotaur could chase if the player is close so let's get a vector 3 distance and we can see on the vector 3 distance unit that it looks for a distance between a and b our a will be where the minotaur is so get a unit for transform get position and we want the distance from our monster to the player so go over to the scene tab and drag out the player variable and what we want from the player is the player's position so transform get position and connect that to b and let's make a variable for that distance value so we can use it a few places we want this to be an object variable because we might use this state machine on a few different enemies and they'll each have their own unique distance to the player so call it distance to player and make it a float hold alt and left click drag to pull it out as a set variable connect things together and left-click drag to group things up and let's call it distance between enemy and player next let's make another update i only want the minotaur to start chasing the player if the player shows up where the minotaur is facing so the unit we want is a vector 3 angle this is going to give us an angle between two vector directions the first direction is going to be straight ahead from where the minotaur is facing so that's going to be a transform get forward and you can see that that's the forward of itself of the minotaur so we want the angle of where the monster is facing to the direction where the player is that means we need to figure out the direction from the monster to the player so we can take the player's position let's bring in that player scene variable and then let's get the player's position transform get position and then let's get the minotaur's position and this time i'll just ctrl d duplicate it from the top and drag it down and then add a subtract unit for vector 3 because if we subtract the position of the minotaur from the position of the player we get the direction towards the player let's visualize how that works if the minotaur is at the position 1-2 and the player is at the position 4-3 the vector to the player from the minotaur is 3-1 run that direction to the player to the 2 so we get the angle from where the minotaur is facing to where the player is so let's make a variable for angle to player and make that a float and hold alt and left click drag to get the set variable unit and then connect that up and we also want to make a direction to player variable and because it's a direction the type should be a vector 3. alt left-click that variable to set it here because we'll use the direction to the player in the attack state and then i'm going to connect the update flow and then let's group this up as angle and direction to player here's the tidy final graph and just a little note here it's a good idea to put numbers in for your variables and not let them be zero sometimes that can throw errors for distances okay let's start out with the transition to chase so let's get an update we'll end up copy and pasting what we're doing here to the other transitions just to let you know ahead of time so we're going to check if the player is within an angle go to the graph variables and pull out angle to player and then we also want to check if the player is within a certain distance to us so grab the distance to player variable and we want to start chasing if the player is within a certain amount so we want to pick less and that means 30 degrees on either side of where the minotaur is facing and this is what i made the field of view model to represent we're going to add another less than unit and this is for our distance to the player and also with the field of view model i made it extend out to 10 meters make a couple of branches from each less than and then run the update flow into each one so flow to chase if the player is within an angle and within a distance we could leave our transition at that and go right to chase but it would be a lot more fun if the player could hide behind walls and not just have the minotaur chase if we're within a distance in an angle so get a physics raycast unit and you want the raycast with origin direction hit info max distance the ray of the ray cast is going to momentarily serve as the site of the minotaur first the unit wants a origin for our ray and that origin is going to be the position of our minotaur so type transform get position and then what we want to be careful of is that this ray doesn't hit the floor so let's add a transform get up let's add another unit and we want an add unit a vector3 ad unit because we want the rate to shoot from one meter up of the minotaur's position and then that will be the origin of the ray next we want the ray to shoot in the direction of the player and we have a variable for that so left click and drag the direction to player in and connect that up to the direction and then we can put the max distance at a hundred when we shoot the ray out we want to figure out what it hits so let's pull out hit info and let's get the collider type raycast hit get collider from here we want to find out what game object that collider is attached to so type in collider game object and we want get game object what can we check about the game object to see if it is the player well we can check the tag so let's do game object compare tag and the tag we want is of course for player and that's player with a capital p and then let's create another branch here because we only want to chase the player if this is true if the game object has the tag player and moving backwards i'm going to hook all this up and i'll group up the top as is player ahead and near question mark then i need to run this into the raycast and then i'm also going to group this up and call it minotar c's player and then i see i didn't connect the update flow from the raycast to the compare tag so let's do that and then let's go ahead and grab this group here and ctrl c copy it because we can use the structure for the transition from chase back into patrol paste it in and let's think about what we need to change for going into chase we were checking if the player is within less than an angle or less than a distance but here if the player is outside of an angle and a certain distance away then patrol again and stop chasing so we want the unit to actually be greater than or equal so greater or equal and you can control d duplicate that essentially what we're doing here is saying that the player has gotten away if the player is both outside of that viewing angle of 30 degrees and farther away than 9 meters and with that we are done with the transition from chase to patrol but let's rename the group to player is far and out of viewing angle now's another good time to save your project and test it out all right minotaur is patrolling and we're being chased chasing chasing running in circles and it's kind of hard to get away at this value so in the transition to patrol i'm gonna change the distance to two okay perfect and we can see in our flow graph window that all the transitions are working as they're supposed to let's use that transition to chase group again for the transition to attack so go back and copy that with ctrl c in case you lost it and then go to the transition to attack and paste it so to get to attack i'm going to make the value a little bit higher at 60 degrees and then the minotaur should only attack if the player's within a distance of 4 meters or roughly the range of the weapon all right we're moving along so now it's time for the attack state and i have a couple things in here that i know you're going to find useful so delete our starting stuff and let's make an on enter state and just like the chase and patrol we want to do a material set color and let's grab that material and drag it in again next if you remember we had a uh nav mesh agent speed so ctrl d duplicate the enter state add a navmesh agent speed unit in my experimenting i didn't end up using the navmesh agent for the movement here but i wanted to include this because you might find it useful if you did want to do a walking or running attack you'll need to do a navmesh agent set destination just like we did in chase next we want to rotate the minotaur to the player for the attack so let's get an update unit and what we use to do this kind of rotation is a quaternion slurp let's talk about what a quaternion slurp means slurp stands for spherical linear interpolation interpolation is filling in values in a series based on calculation or estimation of surrounding values spherical means we're doing it across a sphere so you might imagine it as an arc rather than a straight line quaternions are from another dimension they are four dimensional numbers that when projected onto 3d space turn out to be really useful for 3d rotations like our slurp here and we want a transform get rotation because we're rotating from an a rotation to a b rotation so the minotaur is rotating from where it's facing to where it would face if it were facing the player so let's bring out the direction to player variable and we want a quaternion look rotation unit because this is the rotation where the minotaur would be looking in the direction of the player so connect that up to b for where to slurp to and the direction to face the player is changing all the time so let's run update into that and then look rotation into slurp t is how far to go each frame from a to b so it's a value from 0 to 1 like a percentage people often think of it as a rotation speed in order to smooth this rotation out across frames let's multiply whatever our value is by time dot delta time so the lower the number here the more steps it'll take to get from rotation a to rotation b we'll end up coming back to this next let's add a transform set rotation this puts our quaternion slurp into effect on the minotaur let's add a animator play to play the attack animation and then let's group this up and call it look at player and attack keeping the value constant in the quaternion slurp means that the minotaur is going to rotate towards us the entire time he's attacking i want to change this and make the minotaur only attack at certain points of his animations so let's add a variable for aim rotation and it's a float and then drag that out and plug it into the multiply so the minotaur is going to aim with his hammer and then when the hammer is coming down he shouldn't still be rotating because all of his strength is going into the momentum of the hammer so i'm going to move these units to the side we want to set this variable so press alt and left click drag to bring out the set variable and and do that twice because we're going to set the rotation to stop and then start up again then add some float value units to use to set the variable and what we're going to use to change the rotation of the minotaur is an animation event type animation event and we want a named animation event and we're going to have the event set this variable so this one is going to be for rotating so make it 15 and then duplicate the animation event and this time we're gonna make it a near zero value so when we're rotating let's uh call the event take aim and we've not actually made the events yet i'm just putting the names in here now that we're going to use and the other one's going to be stop aim and let's group this section up with control left click drag and we'll call it take aim and stop rotating and i'm seeing i forgot to pick a color for the material set color and so i'll make that red and slightly transparent before we make these animation events let me show you what the problem is that we're fixing let's take off this aim speed variable and take a look at what a fixed value does playing the attack animation really slow we can see that the minotaur turns towards the player the entire time if i'm nimble enough to miss the hammer smash the minotaur will continue to rotate towards me and swipe me with this hammer from the side shift space out of full screen bring up an animation window and your animator window click on your skeleton i'm selecting the minotaur of course and here i have the collection of animations bring up the attack animation and what you want to do in the animation window is to select the points where you'd like these events to happen i've already made mine here i want the minotaur to start out rotating but then once that hammer is above his head he shouldn't rotate anymore uh until he's recovered a little bit after the attack on the animation timeline you'll want to right-click to make an animation event then with the animation event selected you can go to the inspector and click on function and there you want to pick trigger animation event animation event and then you can give your animation event a string name in bolt we already called ours take aim and stop aim add an event at the beginning of your skeleton animation and give that event the string name take aim and then when it seems like the skeleton is bringing down the sword is probably when you want to stop the aim so you can see where i have that here and then when you want the skeleton to start turning around again right click on the timeline and add another uh take aim event here's the before and after this is the fixed value rotating all the time and now the changing value with animation events if the player dodges the hammer they're able to get away and there's one other thing that i want to do which is to turn off the root motion on my animator so i'm going to type in animator set apply root motion and you may or may not find this useful it depends what your animations are like i can show you mine on this minotaur here for the walk and the chase the root motion of the animation makes it so that the animation can move the character forwards their steps and the distance they're going match up and i like it for the chase and the walk but i didn't like it as much for the attack and you can see that apply root motion parameter on the animator moving on the last graph for this super state machine will be the transition back to chase so again i'm going to paste that flow graph from the transition to chase and i actually don't want to check the angle for this because if the player runs away behind the minotaur the minotaur still kind of knows that the player is there and it should keep attacking so let's add a unit and make it a greater or equal and we'll connect those up and i'll do a distance greater than 5. let's rename this group to player is too far to attack chase another thing is we don't want to go into chase at any point within the attack animation i want the attack animation to complete before we start chasing right click add a unit get current animator state info and let's pull out the little info button and see what kind of information we want we want the [Music] normalized time the normalized time means zero is the beginning of the animation and one is the end and i want to put in zero that means an animation has played and a new one has not started and then we want to connect this to a branch because we only want to go back to the chase state after the attack animation is done playing and moving backwards i'll hook this all up and then extend this existing group to cover everything and then in my case or maybe yours we want to apply that root motion again for the chase and patrol walk animations okay so our super state's done let's test it out everything is working exactly as it should and most importantly the behavior is believable and pretty fun of course it's no fun if the player can't die so on the player i have a flow machine here's the graph for reloading the scene if a collider with the tag weapon hits you and i put this collider on the skeleton for you on scene manager load scene make sure to put the exact name that your scene is not the scene that i have here everything set up to duplicate your enemy and have multiple monsters but as you'll see in a moment here they are all sharing that material color to fix this you'll want to go in and create an object variable that is of type color and then you'll want to set that variable on the enter states that's a really good challenge for a beginner so see if you can figure it out thanks so much for following along and congratulations because that was a lot my name is jim and i hope this helped level up what you can do with bolt
Info
Channel: TriggerHappy
Views: 3,317
Rating: 4.8632479 out of 5
Keywords:
Id: GRUE1PRBKmE
Channel Id: undefined
Length: 35min 24sec (2124 seconds)
Published: Thu Oct 01 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.