Adaptive Enemy AI Patrol System - Complete Unity Game Dev Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
still holy moly look at that yeah yeah hey what's up guys John Stossel here so you may have come across videos or systems before that have enemy patrol AI that simply moves a left and right between two fixed points based on a distance but that's a problem because if you have walls or a crevasse like a hole then the enemy doesn't know what to do so in this video I want to show you guys how to get around those things and build an adaptive enemy patrol AI system from scratch alright let's get into it so [Music] I've just set up this little sample scene here that we're going to be working from and this sample scene I'll make it available for you guys down below in the description of the video so you can follow along with me if you like so you can see here I've just got a simple enemy which has a box Collider and a rigidbody component with the standard settings and I've also got a just in terrain holder which is holding a bunch of different prefabs for the ground tiles nothing particularly exciting and those ground tiles have like a box Collider 2d just for convenience so we can later kraid like walls and stuff around the player so the first thing we'll want to do is get this enemy to move so we'll do that by selecting the enemy clicking add new new script enemies script create an ad yep and then we'll double click that open it in Visual Studio the first thing we want to do is just to create a rigidbody 2d reference RB 2d and we'll also create a float called move speed and we'll just make it 5 play with that later and in the start function we'll say RB to D equals gets component rigidbody2d and we'll want to just apply velocity to that rigidbody and we'll create in fixed update for that because you guys might know that um anything physics related should be done in the fixed update rigidbody2d dot velocity equals new vector2 and for the X parameter we'll pass in the move speed so be giving it five velocity on the horizontal and zero actually what we'll do for the Y we'll just say rigidbody2d dot velocity dot Y this means that we'll just continue applying whatever is already set as the Y velocity to the object all right so that should theoretically be enough to move this guy well he's moving well what's that he got stuck huh yeah okay so you guys might be familiar with this issue anytime you have game objects that have like tile-based box colliders it can cause like you can get stuck on the little edges you can resolve this in a few different ways you can go into like their physics and collision settings and change how sensitive it is but we'll just make this quick and we'll just say circle Collider 2d and I'll just make that really small okay so you can see what I've done here it's gonna offset the Y a little bit just want the circle Collider to kind of catch the edges it's a bit of a dirty hack but just for the sake of this tutorial so we don't get slowed down it's it's fine alright that fixed it and you can see the character is moving all the way across the screen ship it just kidding we have a bit more to do what I will do quickly I'll show you the problem right so if I create a wall here now well we know what's gonna happen the place is going to hit the wall and that's it because there's no logic to tell the player to do any differently so we want to write that in we want to give the player away to be able to see the walls and the floor and we'll do that by shooting a little line cast or array cast but in this case a line cast should be enough out of the eyes or not necessary out of the eyes but forward from the players position to look for a wall and it will also shoot one down to look for acrobats but we'll start with the wall as that's the the more obvious one so to do that we need a few things first of all we need a new layer go to edit layers and under the layers drop-down let's create one called terrain and it will be using this for both the wall and floor which is essentially the same in this case and we just want to go into our prefabs for the terrain just select it from here and just want to give that yep you just want to assign that to the terrain layer if it's not already assigned and now just with our enemies selected right-click create empty to create an empty child and we just want to create something called a cast pause or cast position for short and this is where we're going to be shooting the array or the beam from and you want to just give it a little gizmo here if you click this little box and they'll create a little visible gizmo so we can see it and instead of positioning at the eye level to look forward because we'll I want to reuse the same gizmo for shooting down I'm just going to put it here a little bit slightly to the front of the player so we can kind of shoot it that way and also shoot it down what it's looking for a hole so back to visual studio at this point we're listening to define a few more things we'll say game object cast parts you know what will make this a transform because all we need is the position we don't need the whole game object and you might know that the transform is a kinda like a sub component of the game object has been more lightweight when you don't need the full game object and will serialize field because we'll drag that in for the inspector and we'll also want to create a float and we'll call this one base cast dist based base cast distance and we'll serialize that too and this will be the distance in which the player can see the sensitivity for how far you can see all right we're going to be also turning the player left and right so we just want to create a constants for the strings so we're not writing left and right in quotes every time it's kind of Buddha practice so const string left is the convention equals left and make a new one const string right equals right so again this just stops us from creating typos and having to have to write this kind of stuff over and over just gives us a reference through these here and we'll also need to store the facing direction of the player i will do that as a string and call it a facing direction and this should be the default for whatever you which way your graphics are facing in my case it's right so facing Direction equals right you can see now I can use those constants and I'll set up up here very efficient oh one other thing we'll do because we're going to be depending to play around I might just store the scale the base scale rather so I say base scale so base scale equals transform dot local scale and just a quick comment if you're not getting your order complete like I am right now just make sure that your unity is linked to visual studio through the unity preferences I know some people are out comments into videos saying hey my my autocomplete isn't working get that working it's very important so this is where the magic happens now we're going to create a new function here called is hitting wall and we just wanted to return a ball so instead of writing void I put a bull there instead so the way I like to do it is to just declare the value up the top of vowel equals false by default and at the bottom we just want to return the vowel okay so that's how it's going to work in our logic we'll go I'll hit wall logic we'll go in here so just blocking a few things float cast dist equals base cast disk we're gonna be working with locally in this function and I'll say if facing Direction equals left then make the cast dist equals minus base cast is because we want to shoot them safe the if the character is facing a left should the array left if the character is facing right well that will be by default here and we don't have to write it alternatively you could like you know write an else you know kind of repeat the same thing as you have here but you know it's a little bit redundant because we've already got the default up there that um however you like it you know alright so now we're gonna want to define our target distance for the Rays so I'll just say vector three I'll say target pause and I'll just declare it as assigned it the value casts pause dot position and what we want to do now we just want to say target we just want to modify the x value of this target pulse also target positive X plus equals cast disc you see so we plugging in the value that we've defined here and that'll be over a negative value or a positive value I might just put a quick and comment here for you guys define the cast distance for left and right determine the target destination based on past distance okay so now we officially going to draw the Ray and look for the wall some say if physics 2d dot line cast and you can see here the first value is the start position and in position say so these suddenly make a little bit more sense and the start position will be this position here so I'm going to say cast pause dot position and for the end pause well we have our target pause right here so we're going to say target pause two for the third parameter you can see it's looking for a layer mask so we'll say one dash dash layer mask dot name it true layup forbidden close the bracket and it's gonna pass in the name of that around layout we created which is um terrain and we'll put one more closing bracket there then open and close these fun things up looks like I'm missing a bracket there alright so if you're new to unity this may look a bit like what the hell is that oh my god but if you've been using unity for some time you'll know this is pretty standard there's a c-sharp convention known as a bitwise bitwise operation and it's using it to find a layer mask so it basically means shoot or we'll shoot a rave from this position to this position and see if it intersects this layer unity probably should have hidden this I think this is a bit kind of dramatic for the eyes to be looking at it's always gonna be one don't try to change this to two or anything it won't work and this will return true so it means yes we have found a wall we've hit the wall give us a truth else vowel equals false alright and then we wrote returning this value so this whole function is just a bit of a just a bit of internal logic which then passes back to us somewhere else and we gonna be doing that from the fixed update function so I think if is hitting wall like that and then we just want to print or debug log its whoa just to make sure that's working and we'll need a wall now so I'll just duplicate one of these guys here we'll keep our eye on the oh wait a second we have not assigned that cast position thing so on the enemy script you'll notice our cast position is empty so want to grab that and it's drag it in here or click that little knob there and find it in the scene that way and we also haven't done anything with our base class position and I might just set that to maybe like a point two and we'll run that again boom look at that look at our console hit wall yes success all right so let's elaborate on that a little more now and kind of flesh it out a bit so that's cool we've hit the wall but now we want to turn the player around so let's create a new function called change facing direction and we can even take a string and say new direction so we can actually tell this function specifically which way the player should move sorry put a void there you can get rid of that now so say if facing Direction equals left then change facing Direction right make sense and else change pace and direction left I might just write this out for you guys over here just to make it clear what I'm doing so if we're facing left change right else if if we're facing right then change facing Dilek sugar direction left that makes sense yeah so now we'll just want to change the facing direction of the player using that new direction argument that's coming through so just start by defining a scale that we can muck around with and modify source a new scale Eccles vase scale because we don't want to modify the base scale so I'm just creating a new version of that that we can tweak honestly if new direction equals left's then new scale dot X equals minus base scale dot X oops holy crow Balzer okay yeah I think that'd make sense and then else we must be facing a right but I will write it again for you guys normally I just do it else but I want you guys to clearly understand what I'm doing here so I'm gonna make it bit more verbose so if we're facing a left make our new scale X dot a minus the base scale X otherwise make it like this and now we just want to map that new scale to the object itself so I'm gonna say transform dot local scale equals new scale perfect and we also just want update the current facing direction what facing Direction equals new direction so we're just mapping our class member that we put up at the top just to this one that's coming through to keep it updated so we'll have to address this this code here which is move it's got a fixed the value here so we just want to replace that based on the direction we are facing so what I'll do I might just make a float call it V X velocity X and I'll say move speed so we just give it a default value and we'll say if this was a facing direction oh my god if facing is it yeah facing Direction equals left then V X equals minus move speed and instead of giving the move speed we just want to put this V X so the move speed is the class member and that we've got up here and we're just creating another local version of that within the function changing it to a negative or positive based on left and right direction and then putting that as the velocity and that sounds pretty good to me so one thing you also may have noticed is that you can't see the raycast it's invisible so what's a good thing to do when making your game is draw the line so you can visually see it now this is a very powerful way to keep track of what's going on in your scene and we'll do that now it's a very good practice so down here just by the way we're doing that check I'm just going to use the debug API debug dot draw line and we just got to mimic see it start line and line and we're just going to mimic what we're doing here so we have our start pause and pause cool and now we need to give it a color which is pretty cool so we'll say color dots what should we make it maybe like a blue yeah alright so that should work and what we can do we can just maybe increase our class distance maybe it will say like 0.5 and you might want to just want to tweak that gizmo size so it doesn't get in the way of actual line you can do that for this gizmos tab here all right so I maybe move that wall over a bit here and I'll put in another wall over here because I've got a feeling this could be working if this works and we pretty damn excited sepra start what okay I just pause it quickly you see the line now how we can see the debug line very cool so now you can see what's going on now the moment that line hits the wall it should turn the player to left if it does it's gonna be a beautiful thing here we go yeah all right now check this out hop whoop how awesome is that so you can see now the power of this you can have any different terrain combination and you don't always have to be hard coding in values saying only walk five units or only walk three units now you can have a completely organic terrain that automatically has all the enemy AI adjust to it so I'm actually using the same system in my own game blood and meat here and you can see this patrolling enemy has that same line cast that's looking for the walls and he's also using that line class to look play yeah so this is my a game blood and meat if you guys want to support my work I'll put a link to the wish list down below see this snake is also using this ray Kasten of all right very cool so how about the crevasse or the holes rather so let's shoot it being downwards encounter for those as well so what we'll do we'll grab that is heating wall function and we just duplicate this because we're going to make a variation of this so is heating wall we all say is near edge so it's gonna be a little bit different which is why I made a duplicate of it let's tidy this up did so by default I'm gonna make this true and here instead of shooting to the right we're gonna change the Y value because we want to shoot down so I've seen - castis so this will shoot it downwards and this time will might make it a red and so this one's going to be a little bit different because we are looking for a hole where with the war we were looking for a solid object so now we're looking down we're expecting to have the floor bit bit below us it's only when we find a the wall isn't there that's when we flag it so it's gonna be back it's gonna be the opposite of how we did the wall so this would be false and this will be true now if you're if you're savvy with your code you could certainly wrap this up into one big function which caters for both the forward and shooting downwards but you know because this is largely a beginner's channel you know I don't want to tie you guys up in knots so we'll do it like this all right so now we're gonna process this ismy edge business very simply we'll go up to this um condition here so say is if is a hitting wall or is near edge then turn left all right all right good ah ah yes I see the problem we don't need this left or right cast distance business this was only relevance when we were shooting the beam forward or back on a horizontal axis because we are simply shooting it downwards on a vertical axis we don't need any of this so what we gonna do when it's gonna get rid of that and we're just gonna say yeah like that that should do it ah ah good notice down holy moly look at that yeah yeah absolutely fantastic so there we have it guys adaptive enemy patrolling so I hope you guys have enjoyed this video I clearly enjoyed making it give it a big thumbs up if you have and don't forget this up if you haven't already and a big shout out and thank you to my patreon supporters both current and past I know times are tough for a lot of people in the world and I want to thank you for showing support to this small channel and valuing online education being done properly there's a lot of clickbait out there and I try to approach it from a authentic education first direction so for those of you who recognize that and value that I appreciate you too thanks everyone see you in the next video and as always all the best on your game you [Music]
Info
Channel: Lost Relic Games
Views: 9,672
Rating: undefined out of 5
Keywords: enemy patrol system unity, simple enemy ai, enemy agro, unity2d, unity 2d tutorial, game development for beginners unity, tutorial, how to, indie game developer tips, learn c# for unity, ai, ai patrol system, enemy, unity, enemy controller in unity, raycast, linecast, enemy move, enemy controller, line of sight unity, enemy line of sight, see walls, adaptive, change direction
Id: dHkbDn-KQ9E
Channel Id: undefined
Length: 27min 19sec (1639 seconds)
Published: Thu Jun 11 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.