How to code SMARTER A.I. enemies | Unity Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello there I will not hold back the navmesh module in unity is a scam but we are still going to use it by the end of the video you will be able to make your enemies smarter you will get a few free assets along the way along with some extra learning resources and there is also a challenge for those who really want to get better at making games so make sure you stay until the very end navmesh is part of unityengine.ai package AI stands for you know what it stands for you instinctively think great I will build an AI for my game no there is nothing AI about the navmesh system it just helps an agent find the shortest path to the destination we will work on two problems today first we learn how to use a navmesh system to make a stupid enemy the enemy runs straight to the player and shoot setting second we make the enemy smarter there you will learn a few techniques about what takes to make smart enemies also you can expect quite some work with animators let's start by creating a new project I will use a universal render pipeline 3D template now we need an environment think about it very hard then snap your fingers and there you go okay that was a bit fast well here's a gift for you I've published this 3D sci-fi kit on my website you can go grab it for free it has a few basic walls floor tiles Corners ceilings and even a super cool dummy Bean which will you use as target practice the models are available as fbx and there's a bonus Unity package that you can import to get started quickly is the first version and I will add more and more objects along the way and over time probably with each release of a new tutorial alright to fill this area out I will use some prototyping boxes I'll place a few around to create some kind of interesting layout and to keep them snapping to the grid just hold Ctrl or command while moving them and to keep things clean I will group them all in a new game object called boxes once your environment is ready and it really does not need to be that fancy in the beginning we can bake the nav mesh go to Windows AI navigation there you can tweak a few settings about how the nav mesh will be baked for our agent to find the shortest path to destination it must know where he can walk and where he can't that's the purpose of baking you can set the radius height step height and maximum slope for each type of agent you can also Define areas and give them different weights or penalties so the agent might favor One path over the other you can imagine giving water more weight than the normal road so when the agent computes the shortest path that way it will influence the result to get started the default values are totally fine the process of baking is highly complex click on bake and you are done everything that is blue is navigational navigational navigational level if it's blue it's good parameters like the radius will determine the border around obstacles now how did you need to know that those are obstacles because they have been marked as static the dummy bean is not static so it is getting injured to be more precise the complete object does not need to be static it just needs to have the navigation static checked if you change the environment you have to rebake the navmesh and once we will work with large scenes you will love the nav mesh system I guarantee it for now that's enough Bakery let's set up our agent creating characters takes a lot of time so we are going to go asset fishing on the unity asset store luckily I found this gem a robot hero fully animated it even has three variants from low to mid to high poly it's great this will work very nicely for what we are doing once important in unity you will have the cipher Warrior blah blah blah folder it has all that you can expect meshes materials animations a demo scene and the prefab they all work the same so choose one you like I will go for the PBR character one drag and drop and that's it there is one animator set up for us just hit play and you can get a nice demonstration of all the animations inside that package there's shooting reloading ducking jumping and so on we'll just need a few of them for what we are doing alright time to set up this guy first to use the nav mesh that we baked we need to make this enough mesh agent add component nav mesh agent I won't go over all the parameters otherwise we'll be there until next week what you should remember is that the agent can't move and turn by itself and here you can tweak that behavior we see that the radius and height fit pretty nicely so we are going to leave it as it is however we are going to change two things first we set the angular speed to 200 so the character turns faster and since it is a shooter we will set the stopping distance to 8. this means that if we tell it go to this cool dummy Bean it will go there stop eight units before now this guy needs to shoot so we need to get a reference to the gun barrel somehow this is where the bullet comes out at least visually this next part does not feel 100 right it's probably the main disadvantage of this asset so bear with me there is a assault rifled but when you play it stays at the same position but the mesh moves because it is a skinned mesh renderer I couldn't really attach anything to it so we have to go down the rake open the hips spine shoulder left upper arm left lower arm left hand left and finally index proximal left phew let's create a new game object as a child name it gunpoint and give it a nice label now here's the ugly part set the position to -8.3 1.3 and 77.5 seriously if you play you see that it looks kind of okay we can live with that for now remember characters take a lot of time to make okay out of play mode and let's prepare the animator there are tons of ways to work with animators in a few minutes I will share a very interesting talk about animating with unity alright we will do the movement with a blend tree right click create State blend tree rename it to movement and right click on it again to set it as a default State double click on it to open and there is our blend 3 that doesn't blend much yet automatically created a parameter which we will rename to speed a blend 3 is pretty simple given some values it will blend between multiple animations click on it and let's add two motion Fields the first animation will be idle God and the second one will be run guard the speed parameter controls how much of each animation is used 0 means idle once means run in this case and everything in between is a blend between both animations it's a very natural way to implement movement let's go back to the base layer and add a shooting animation I will copy and paste the shoot burst AR State and add a transition in and out now we need another parameter which will be a bull called shooting we transition from movement to shoot when shooting is true and come back when shooting is false alright that's all we need for the first version yes there will be a second version a better one hey are you enjoying this consider describing because many more tutorials are on the way otherwise the bean gets it let's make this agent alive create a new script enemy brain stupid yeah I I really named it like that because that way of doing an enemy is too basic but we have to learn it once and let's create another script called enemy references that script will hold all the references so that any script on the enemy only need to reference that one object you can save a lot of repetitions that way let me show you we will need a reference to the navmesh agent for that we import unityai dot AI at the top in the awake method we use get component to get the nav mesh agent on this object we also need the animator so we do the same thing now they are public because other classes will use them so if we want that they don't show up in the inspector we can add in Brackets hide in inspector I also add these allow multiple components on the a class so we can't have more than one pair object let's move on to the brain the enemy needs a Target it will be the cool dummy Bean but could also be something else and we just need the transform to get started let's keep it simple in this video and we will set the reference manually in the inspector we will not implement the full targeting system next we will take the enemy references which will be private because we can do a get component in the awake method now the enemy will do three things one run to the Target in this case the nav mesh will do the movement and turning two look at the Target when you are not moving so we always aim at the Target and three finally shoot it's not a very smart enemy yet I told you but it's going to get better after that the code base works like this if we have a Target we compute the distance between us and the target if it's smaller than the shooting distance then we look or aim at the Target otherwise guys we update the navmesh we can take the shooting distance from the navmesh agent dot stopping distance that we set at 8 before and as for the navmesh agent we simply get it through the enemy references object are you ready for some quaternions of course you are so we subtract the target position from our position and set y to zero to inherit that gives us a direction vector quaternion.look rotation converts the direction to a rotation and finally instead of instantly turning we can slurp to smoothly turn from our rotation to the computed Loop rotation in 0.2 seconds for updating the path I will show you the better way already that is skipped in most tutorials on the navmesh agent you call set destination on it and it will compute the shortest path and start moving there this is something that you should not do every frame you don't need to compute the path every frame so we are going to add a path update delay a in our enemy references by default we will update the destination every 0.2 seconds next we track when we can update the path with a private float path update deadline in the brain script finally we can write the update path method first we check if we pass the deadline if yes we set the new deadline to time.time plus anime references dot path update delay and then we set the destination it's time to add those scripts onto the enemy and test let's just set the target as our cool bean and play alright it works it follows the target stops at 8 units of distance and below that range rotates to always face the player now what's left for that part is to hook up the animation to do that we can simply set the speed on the animator to the navmesh agent dot desiredvelocity dot Square magnitude for example and for shooting we set the bull to the value of in range alright looks much more Alive Now a highly motivated but very stupid enemy you can move the bean around and look at how the agent and the animator reacts it works but we can do better but before we move on to the smart stuff let's just implement the shooting and you know what we are developers we love Reinventing the wheel but we are also lazy so let's just borrow that shooting from somewhere else Liam Academy has a great tutorial for shooting with a raycast and have a visual feedback of the bullet traveling the distance so thank you very much I will take that let's start by creating our enemy shooter script and dropping it on the enemy now what's special here is that we will let the animation do the shooting if you open up the animator and finds a shooting animation used by the shoot burst State you can also directly find it in the animation folder then into the animation Tab and finally scroll down to the event section here I've added three events that we will call the function shoot just click on this little icon and it will create one I've placed those events carefully where the animation shoots and right before the recoil starts when this animation plays those events we'll call that method on the object where the animator is our animator is on the same object as our shooter script so that will work once you add your events just make sure you hit apply before continuing let's now write some code we need a few new references that are unique to this script transform shoot point will be from where we shoot the raycast that will actually be the center of the character because I have no idea how the gun is animated and when where it points transform gunpoint is where the gun barrel ends and we will use that just for the visual effects then who says Ray cars says layer mask of course in Liam's tutorial he also implemented a bullet spread which is really cool and not much work so we will do the same then we need a reference to a trail renderer and finally we keep our trusted enemy resources that we will grab in the awake method next let's define the method called Shoot and inside we start by getting the direction to shoot then we do a raycast starting from the shoot point this line of code will draw a debug line that will stay one second this is super helpful to debug the raycast and finally we create a new Trail renderer and send it to the core routine that we are going to Define in a second let's go over get direction first it's fairly simple it takes a forward Vector of the character adds a random spread on each axis and Returns the normal Vector the core routine is basically moving the trail renderer along the raycast over a certain amount of time since it is a trail it will naturally fade away still we destroyed at the end now spawning trays like this that is really not efficient and if you want to use this in production just check how object pooling works it's much better object pooling is a keyword so if you want to build something a bit more serious a bit bigger just check how it works and it's available in the latest version of unity it's very easy to use just use that we dragged the script earlier so we just have to hook up the references the gun Point into the gunpoint and for the shoot point we could take the spine for example that worked well for this character and for the layer mask let's just set it to everything for testing later we can change that to just be on the environment and other characters and finally let's drag the bullet Trail prefab into the last slot this is given as a bonus in the free sci-fi package you can easily create your own as well it's just a trade renderer with a curve that starts relatively small and Fades to zero the time is set at 0.2 seconds and the color is a gradient that goes from Orange to a darker orange but fully transparent another detailed is that the default material was not looking so nice so I duplicated it and just change the color mode from multiply to additive alright let's not forget to save hit play and let's enjoy how our cool dummy beans gets shot at so you see the race going from the spine but the visual effects goes from the gun that's how you easily can get accurate shooting but with a believable visual that's our stupid enemy I say stupid because it goes straight to the Target shoots him in the face it's very boring Behavior very boring now to make the enemy smarter we have to take a step back and prepare the terrainzo to say right now we have a changing Behavior using one simple Boolean check beginner mistake would be to add more booleans and more conditions to support more features no we need to basically use another code structure that will allow us to move forward more easily we can use a simple yet powerful solution which we certainly heard of finite State machines finite State machines are simple you have States a finite number of them so you know all the states and you have transitions from one state to another state there are no more rules than that you can organize your States and transitions as you please the animator is a state machine as well small side notes making so-called AI in video games is a big and complex subject in this video we explore finite State machines but there are also other techniques that you can use and once you go down the rabbit hole you might never come back so write this down similar to finite State machines you have Behavior trees and behavior trees are also final State machines actually the biggest difference is that a finite State machine described the function while the behavior tree describes the flow Behavior trees are more advanced and without the user interface to set them up and manage them it might become really messy plugins like opposite Behavior designer might be worth to invest in then there is goal-oriented action planning which is really really cool that's what they use in the game fear which was very Innovative at that time and this is really cool but very complex as well and then there is the challenge of having a huge crowd of computer-controlled enemies in this case you might want to look at ECS first that will give you really the high performance that you might need finally fun fact you can Define State machines visually using visual scripting that's quite interesting okay side note closed now there are many ways to implement a state machine in c-sharp should we Implement our own now let's be highly efficient developers and not to prevent the wheel thank you very much Jason he writes great call but I'm sure you know him already there are just two files one is an interface and one is a class you can find is a code in the description let's just fly over it the I stayed in an interface that will be implemented by any state that we will create and the state machine keeps track of states and transitions you add a transition by saying go from this state to this state if that condition is true the tick method is what we will call in the update method it's basically the new update method and the rest is just boilerplate code to make all work safely going back to our enemy this is what we will do our enemy will have more States and naturally appear smarter first the enemy will run and find cover from there the enemy will shoot at the player finally when he is out of ammo he will duck and reload let's duplicate our enemy rename the old one stupid and the new one smarter I will also disable the old one so it doesn't Annoy Us for the new enemy we are going to just do one small change on the enough mesh the stopping distance will be zero because we will choose better targets and not just blindly charge the player anyway don't need the old script anymore now let's take care of the cover there are many ways to implement cover you can go the procedural way or you can go the manual way that's what we are going to do the manual way because it's simple and the goal of this tutorial is not to implement or compute covers I'll create a new game object called covers and inside I will create another game object called cover give it a label and position it behind one of those boxes every cover will have a cover script and that script will just display a gizmo box nothing fancy now unleash your level design skills and duplicate the cover way it makes sense last thing is to add a cover area script on the covers game object this script will find all of its child covers and we are going to have also one method called get random cover for the moment it will just return a random cover but you can also Imagine using the agent location given as parameter to maybe filter out the cover to only choosing among the five closes for example something like that I show you simple structure keep it flexible and you can extend it as you please alright with our new plan we will also update the animator and learn a few more things I will duplicate the cipher Warrior animator that we used and rename the new one to smarter tutorial I know my naming skills are pretty rough today then we drag and drop the new one into the animator and now we can modify it we keep the movement but we will delete the other state instead we will have a substate machine called combat with a new Boolean parameter called combat we will use that to transition from movement into combat let's double click to open the state machine and let's get to work create a new blend tree call it cover we can add a transition from cover to base layer State machine base layer so it will go to the entry state of the layer above and we will transition when combat is false for the cover we use a blend 3 to easily choose how we want to cover instead of having lots of states we can use a blend tree to choose an animation among several we basically use a blend tree as a list so I will add a parameter called cover and use that as a blend let's add two motion Fields first animation will be idle gun middle and the second animation will be idle docking and you can use the cover value to choose which one we play back to the compact state we can add another state with a shoot burst shot animation we transition from combat to shoot as extra time can be turned off and its conditions we add the shooting to true now as a small variation we will add a new state called idle shoot with the idle shoot animation here we use that to add a delay between burst shots so add a transition and adjust tweak the exit time to 0.8 and transition duration to 0.2 because it was looking fine now in this stage we transition back when shooting is still true otherwise we transition back to cover when shooting is false we also uncheck has exit time okay you might wonder where is is a Reload animation well I will show you how you can use layers to overlap or override animations on the top left click on layers and from now we have only one base layer we can create another layer and name it reload every setting here is important the weight is used to determine how much this layer affects a rig the mask is used to endure certain bones and the blending is used to decide if this layer takes over the previous layers or if it Blends additively if you go to the animations folder you will see that this asset came with a default Avatar mask which naturally has a full rig enabled I duplicated it and called it shooting mask which now realize might be better called upper body mask for example or something like that anyway on that Avatar mask just click on the zones that should be disabled in this case I will disable everything below the legs then you can reopen the layer settings and set the mask reload is a good candidate to be on this layer because you might want to reload in any situation while running while crawling while talking so the legs will always be doing something different and the reload animation just should be applied on the hands now inside that layer let's create a new state put the reload animation in and right now it's default state but we don't want that we will create a new empty State called nothing that will be the default State and it will literally do nothing most of the time we will add a transition from any state to reload and from reload to exit we will use a trigger called reload to run this animation on the transition let's set the condition to use that reload trigger and on the other transition I will just change the exit time to 0 and the duration to 0.2 and that's really important for the next step because the next step is to go into the reload animation and add an event around 0.8 I added an event that will call the reload function now if the event happens to be at the very end and you have some exit time so transitions times defined there is a huge risk that the event will not be triggered you are warned alright we are good in terms of animations it seemed like a lot but really it's not and if you want to see how crazy you can go with animators I highly recommend that you watch this talk here where you will get a unique look at the animations of the game firewatch they used Unity as well and have a lot of valuable lessons to share alright back to our business we need a new enemy brain script and we will create a new folder and put all the states that we will write for that drag and drop the new enemy brain on the character take a sip of coffee and let's implement this bad boy we need two private variables as usual so enemy references and a state machine in the start method we get the enemy references and create a new state machine here we will set up the state machine but we don't have any states yet those two lines are helper functions that make adding transitions shorter and more readable that's from Jason's video in the update method we just do state machine dot tick and since each state implements I State we can get the current Gizmo color for that state that's really good for debugging the first date that we are going to implement is run to cover instead of Model Behavior it will implement the istate interface we have to implement all those methods or at least Define them then we need again to have a reference to the enemy references and we will also have to take a cover area the state will receive them through a public Constructor the rest of the methods are pretty simple and you will see that working with State machines actually make your code really easy to work with on enter is the most important one for this state when the agent enters the run to cover State we find cover using the get random cover and then we tell the navmesh agent to go there get random cover takes the location even if you don't do anything with it but maybe that's an ID for the challenge at the end just a side note the state is not a monobehavior so we don't have direct access to things like transform or even core routines okay we update our speed using the desired velocity dot Square magnitude and on exit we set the animations peaked back to zero a little tip make each state leave as they found the place when they arrived so you just reset values to the initial or default States and you will be very thankful to yourself later on and finally we can say that these states Gizmo is blue for example now this state is ready in the enemy brain we can create a new VAR run to cover and already set it to the starting State save play and it works the enemy runs to random cover position every time you start the game he will run to another one let's do more States once we arrive at the destination we will have a cover State we prepare the code but this state will basically have a substate machine to handle the shooting docking and reloading for now we set the references set the combat parameter of the animator to true on enter and to false on exit and let's make this state gray since it's not done what is great we state is that you can naturally reuse them if you did a good job I will create another state called delay which will keep track of a deadline I will add a new public method called is done which actually return true when the time passed the deadline see states are normally self-contained but sometimes the state machine needs to talk to one of the states and say like hey little state are you done maybe same with the wrong to cover let's add a public method so that we can ask if the agent has arrived at this destination alright we can finalize the state machine now we create the delay state with a waiting time of two seconds and we create the cover State finally we Define the transitions from run to cover we go into the delay State we transition when run to cover dot has arrived at destination is true from delay we go into cover State once the delay is done let's try it out the Gizmo is blue it means we want to cover we wait two seconds the Gizmo changes we enter the cover State and we can see that the combat flag is set all good next search shooting State I think that by now everything should be routine or at least the routine should start to kick in we need enemy references and a public Constructor we need the position of the Target so I don't know how exciting you are getting but calm down we are not building a full targeting system in this tutorial we do the Forbidden find with tag to find the player in the tick method we make sure we have a Target if we do we can copy paste the quaternion code to look at the Target and we simply set the bull shooting of the animator to true what changes is that we need to use the enemy references.transform when we exit we leave the place as is so we stop the shooting and we forget about the Target and this is a violent state so it's going to be red next up the reload State this one is super simple but we will have to modify the shooter script as always get those references on enter we could set the cover value to 1 and Trigger the reload when we exit we put cover back to zero Gizmo color is gray because I didn't care now back into the cover State this state will have a substate machine that we defined like this we create three states anime shoot enemy delay enemy reload see we can really easily reuse dates from shoot we transition to reload when the shooter gives us the green light to reload from reload we go into a delay once we are done reloading for that we can use the negation and from delay we go back into shooting once the delay is done Last Detail is missing and it is to do a state machine dot tick in the tick and return the sub State machine Gizmo call at this point you will have some compilation errors because some things are missing first let's add the shooter in the enemy references script next let's Implement some ammo in the shooter script public int ammo starts at 30 and private end current ammo to track it we add two public methods public pool should reload that returns true if the current ammo is zero or less and public void reload that will refill the ammo then we can reload once we are in the awake method to be sure that we have some ammo ready and the shoot method we can put a guard that will directly return if we should reload so no shooting Last Detail is to reduce the current ammo by 1 every time we shoot and you know what we are done we are ready save everything Run the game the enemy runs to cover shoots like a stormtrooper and reloads every 10 bursts since one burst shoots three bullets now wait before you leave if you made it this far that's awesome and it shows dedication you might have seen my announcement video where I talk about the game death Kingdom a new community for game developers and artists to learn together and grow like crazy well it has launched with this first video of a long series of tutorials the link to the Discord server is in the description and I really hope to see you there I have no idea how it's going to be in the beginning there might be lots of people there might be no one in any case I will be there to support and discuss things and for the challenges all the details will be given in the Discord server with that being said I thank you very much for watching I hope you learned something and have now a good base to create smarter enemies and smarter AI now go work on your game and I'll see you next that was a long video I think it was long because of the animation stuff all the animators animations transitions between states that takes really a lot of time and there is still so much more that can be done there it's crazy so yeah but it's cool it's fun
Info
Channel: This is GameDev
Views: 36,511
Rating: undefined out of 5
Keywords: make my first game, how to make a game, made with unity, game devlog, gamedev vlog gamedev, indiegamedev, game dev, indie gamedev, indie game, unity 3d, unity3d, game development, make a game, tutorial, guide, game engine, unity hub, blender 2.8, blender 3.0, blender 3, madewithunity, iOS, Android, mobile game, smartphone game brackeys, thomas brush, jason weimann, jonas tyroller, dani, danidev, blackthornprod gamedev, unity, install, how to, install unity
Id: rs7xUi9BqjE
Channel Id: undefined
Length: 32min 48sec (1968 seconds)
Published: Mon Mar 06 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.