Enemy Line of Sight with Raycast - Unity 2D Game Dev Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello everyone my name is John stay scale from lost relic games so today we're going to follow on from last tutorial where we looked at enemy aggro AI systems and evolved on that using a ray cast system allowing our enemy to shoot array out of its eyes and try to locate the player this allows us to create obstructions and put crates in between the player and the enemy as always I'd like to thank these guys up here you guys are bloody fantastic much love let's get straight into this tutorial so this is what we created in the last tutorial and you can see here this is really cool it's really a nice foundation for enemy aggro and you can see when we walk out of the aggro range which is kind of like here the enemy stops tracking us the problem this proposes though if we put a crate or an object between the enemy and the player we would expect the enemy to no longer be able to see the player right but you see here when I still walk into the aggro range the enemy still wakes up and tries to chase us so we want to change that and rather than creating a distance check which is what we're currently doing in this tutorial from the last one we want to rather create a line of sight where a raycast shoots out of the enemy's eyes and looks for the player and if it hits something like a crate then it can't see the player so it's give you guys a quick tour of what is actually going on in the scene here so up here you can see I've just got a ground a player which has a player controller so if you guys want to make a play controller this is the same one I created in that a Megaman play controller 2d so you guys can jump over there I'm getting to the specifics of how I created a play controller in this video because that could easily take more than half an hour and the enemy object has a box Collider and also a rigidbody component and also an enemy script and this enemy script we can entirely created from scratch in the last video so I'll just open that up for you guys it's it's a rather short script but if you guys want to see how we made this in its entirety you can jump over to my previous video and I walk through it all there but I'll give you guys a quick tour so I've got the player the aggro range to move speed see realized that I then assign over in the inspector for the enemy and in the start function I just assigned the rigidbody component the face and matter is what I'm using to just change the facial expressions of the enemy those kind of angry eyes so this is where the tracking code is going on so you can see here I've got a distance to play a variable a float which is using the vector to dot a distance which returns a distance between two objects so here I'm passing in the enemies transform position and then the player's position and it gives us back a value and then I'm doing a simple check to see if the value is less than the aggro range then chase the player otherwise stop chasing a player and in the chase play a function then I'm just doing a simple check to determine which side of the enemy we're on if we're on the left side of the enemy sorry which side of the player we are on so if the enemy is on the left side of the player then moves right and if we are on the right side of the player then we want to move the left and here I'm assigning a negative move speed to keep us moving a left I think we've got to stop chasing a player which simply changes the velocity to zero and closes the enemy's eyes all right so how to how to expand on this to add line-of-sight so we need a new function so here we're going to create a void can see player and we'll have some parameters for this so we'll say float distance and this will be the distance of the aggro range or the how far the enemy can see so this function is actually going to return a value so I'll change is void to ball and you can see it's gone red because it um now we've told it that it needs to return a value ball just a temporary vowel which I if it's false anytime I create a function that returns a value I just create a temporary local variable inside the function called Val it's nice way to do it and then we will have a variable called cast dist equals distance so this will make sense in just a moment for the moment we just kind of blocking it in and in case you don't know you might be wondering why did I use there and what the hell is a ver I'd variables varies a variable and you're allowed to use this inside function specifically you cannot use variables up here you need to specify the data type but within functions you can use the word variable and have different types of data types assigned to that or you can also use flood up to you but sometimes I just use there that it's a bit quicker saves you working out what data type you need so we'll create a ray cast hit 2d so if you're not familiar with this this is a type that is used for shooting the Rays and it leverages the physics line cast which you might be more familiar with and I've used a in previous tutorials so physics 2d dot line cast then you can see we've got a start point and an end point so for the start point we need somewhere to shoot from I'll make it the current enemy's position but the problem is if the pivot point is at the feet then we're going to be shooting from the feet and we want to kind of shoot from the eyes so for the second value we need an end position right ok so we need to set up a quick end position before we do that so a vector to end pause equals yep we gotta have some issues here so I'm just gonna quickly turn this function off and I need to create that start point so go to our enemy and we'll just open that up and we'll right-click and select create empty this will create an empty object inside the enemy so we'll call this one and cast point or cast pause or something like that and we can assign it a gizmo so we can see it make it a green one and we just want kind of position this summer at the eye level so we can shoot out from the eye position jump back to here and we'll just need to make a serialized field to hold that cast position so call yeah we'll keep it a transform and we'll call it cast point and quickly jump back to unity again and we'll just assign that cast point so click on enemy and we should now have this cast point property reveals just drag that in all right so we should be back on track now so I'll just take those comments away and now I'll just quickly turn that off but now we can say cars for the end position we can say cast point dot position plus vector three dot right multiplied by the distance so this here is kind of like a shorthand for I mean it's the equivalent of us saying new vector three or two and position dot X plus distance kind of thing so yeah I mean there's a couple of ways to write it but this is kind of like a nice cleaner way to do it and that way if we change the cast ish distance to being a negative even though it's shooting right it will go left if that makes sense to you guys because in mathematics a positive plus a negative equals and and a negative plus a negative is a positive kind of thing so you know you might be familiar with that kind of concept so I'm comet this ray cast hit and now instead of starting the line cast at the enemies transform we can use this oops I'll just jumped up so we can use this cast point so the end position now of course we pass in the end position the last value here as you might be familiar with in all line casting you need to add in a layer mask so don't pay too much attention into how this is written because it's a bit verbose in that it's a bit complicated and long but it's kind of like a unity convention we want to get the name of the layer that we're looking for and in this case I'm going to use action so I've got an error here oh of course I need to put in position so just to explain its line more clearly we're doing a line cast we're adding the start position on line cast the end position and what it is looking for this ray cast hit is looking to make contact with anything on a layer called action so say if hit dot Collider is not equal to null first of all we just wanted to check if it's actually hitting something so the moment hip dot Collider is not null it means this ray cast hit has found something on the action layer and then we want to check to see if what it's found is actually the player then so within here will say if hit dot collider dot J mod jecht dot compare tag and here we'll type in the tag of player which is the common tag you will have assigned to your player most likely and the cool thing here which this might give you some ideas of how this can be used so you can have a lot of different objects on the action layer what we're going to do is we're gonna actually will do an Alice jump over to back into unity and we want to click on the player and you can see here on the in the layers drop-down we've got a bunch of different kind of base layers so add a new layer and we'll call this one action and we can also do the same for the crate we can click the crate in the project file and I was currently assigned to ground but we can make that also an action layer so anything on the when I say action what do I mean by action so anything that is in the play space anything that the play can or the enemy can interact with action or action layer is this a nice way to group different objects verbally because I've eyes what do you call them right foreground mid-ground you can call it play a play space or whatever but my convention is action so if the object that the raycast has found has the tag of player let's a grow the enemy and here we can now leverage this chase play a function that we set up before so we'll chase player if we have not found a player then stop chasing player I see what I've done here so I've been a bit silly let's get rid of that let's get rid of that so here value because true value equals false I hope you don't mind me going back and forth with a bit of kind of ideas I think it's a kind of good way to learn as well as you get to see my own kind of thought process and how things change as I write it and here we just want to return the value so every time we fire this function it'll give us back this value and I'm changing this value depending on if it sees the player or not so how do we you now use this so first of all we can remove this distance check from the previous tutorial we don't need that you can keep that as a record for a different type of game or whatever you want to use it's nice to have different options and that distance check is certainly applicable for some context so he will say if can see player and we need to type in the distance so we'll say aggro range if SIF can see player is true here we want aggro enemy so say chase player else if the enemy cannot see the player then stop chasing player that makes me more sense so the reason we did this you can probably write all this logic in here inside the update but just to make it a bit cleaner I've separated into this utility function so we don't have to touch that again and we can do all our checks in here and you can just see so having this simple hierarchy here makes it just a bit easier to work with and having to have to sort through with this every time you kind of want to create these utility functions and put them at the bottom of your code somewhere and try not to worry about them too much and be able to kind of have a nice clear working space within your update loop hiding a lot of that complexity so let's actually see what will happen now I'm very curious to see if this will run as you guys probably know first time you run things and softened has problems due to its not doing anything right oh okay first of all a couple of things the enemy is facing away from us so this Ray is shooting this way so we behind the enemy one thing that we'll have to track though is the facing direction of the enemy and what we're also going to do I want to be able to see this ray cast so I'm gonna create some code to actually fire a visible line so let's do that now so to do that we'll go back into this function here so we'll say debug dot draw line and we'll say the cast point dot position end position and we'll give it a color so I'll say color dot blue so all this is gonna do is it's gonna mimic what are we doing with the line cast and just draw a line in the editor so we can see the line of sight well while I'm here I'm just gonna create a just create a ball here called um is facing left and by default it will be false because the enemy graphic is facing right what we're going to do we're just kind of over here in the chase where we turn the enemy around based on its proximity to the orientation to the player rather we're just going to change this property as well so here we will save false so the enemies to the left of the player we need to move right and then we also want to change these facing left defaults because it's going to be facing right and here we'll say is facing left equals true hope in X that makes sense to you guys you might have something sin in your own games but if not then just copy what I have here all right and what we're gonna do with this we're gonna use this right so here we can see our cast distance is shooting right the problem with ray casting or not the problem the challenge is unlike child Clips within objects when you rotate or flip the objects like the facing direction the raycast will still continue to shoot in this case right so when the enemy turns left I want the raycast to also shoot left so the best way to do that it says if it's facing a left is true which is the same as riding true what one tip for beginners it's not a bad way to write it sometimes a bit of it's a lot longer way just to refer miliar eyes yourself with kind of programming I think you can just write it like that same goes for using that which means false doing it like that is exactly the same as writing that and sometimes writing it this long way is just makes it a bit easier to understand when you're learning so anyway if is facing a left is true then cast distance equals minus distance so by default it will be a positive number and if we are facing left we just want to switch that to a negative number I see here we could we made a mistake so I should be using the cast distance here so just update your code from distance to cast distance and that will change from my positive to a negative number depending on what this is so now okay so we're drawing a cast a line let's actually just see if that's kind of that's working let's move the enemy over here a little bit and we have nothing so what is going on with that right okay so I'm only here I've made it so it's only gonna draw a line if it's actually hitting something it's not right at all so I just put it else here so if it's hitting something then do that if it's not draw a blue line here and what I might actually do I'll make another line so that if the raycast does encounter an object let's draw another line that actually finishes on that object source a hit dot point which is the convention for Ray casting and it will change the color to a yellow all right something's gonna rearrange the scene ever so slightly so that's gonna move the enemy over there since he's already facing right I'll move the player over here and let's see what happens when I press play all right so we now have this blue line cast so if we enter this space it goes yellow you see that see if I jump out of the range you can no longer see me run run run run run run walk get away he's moving way too fast I'm gonna slow down this enemies moving speed because he was moving away too fast so much just make that a 2 and you can see here if I adjust this aggro range I could do it in real time to find a nice suitable distance that works for our game so you can see here we walk in and we walk out it's pretty cool so now let's see what happens with the crate which was the initial kind of thing we're trying to solve so because the crate is also on the action layer we can stop the raycast with the crate so now if the player walks in to this area the enemy can no longer see the player but what's going to happen if I move this out of the way Bing see that's really cool so that solves the problem we had of the raycast for the player I mean we have we've created a few new issues here in that the moment the player sorry the moment the enemy can no longer see the player the raycast stops working as in the aggro stops working so what you can do there's a few different things you essentially want to have some kind of an aggro time all right so if the enemy can no longer see the player you want to keep looking for the player for a period of time so I might try to hack something like that in guys I wasn't planning for this specifically but let's see how this turns out so if if the can see pave can't see play huh so first of all a couple of things we're going to be going to do we're going to add a let's make sure we haven't already got it you want to create a boolean called is aggro equals true and I'm just going to declare it in the top of this of this class here so is aggro and by default it is false you can write it like that so is aggro true chase player and here the lowered I'm just gonna say if aggro is true so if it was true and now we can no longer see the player then instead of stopping straightaway let's give it a bit of a delay let's say invoke stop chasing player so that the name that we want to use and we'll just say like um like three seconds or something one two three and it is this not the most efficient way to necessarily write this there's a lot of different ways to delay function calls you can use a KO routine you can use some kind of like um delayed call from at weaning engine oh and we need to flag this back actually we'll go to stop chasing player find that function and in here we'll just reset that is aggro to false so now we've officially stopped chasing the player a guru needs to be false so if this all works and I hope it does then the enemy will continue chasing a player for three seconds and only if after three seconds he can't find the player then he will go back to sleep so he's still chasing us look cool he knows we here he knows we're around so we may need to play with that a little bit just to get that right I'm gonna grade one more property here because it's is this getting a little bit more complicated than I thought so I'm going to create an is searching just to keep track of this little window in between losing track of the player and actually stopping chasing so I'll say is searching is true because why I'm doing this is because I don't want I don't want the enemy to continuously fire off this function and that's what's causing this problem so I will say if whoops if is searching equals false then is searching equals true and only then do we want to invoke this because what was happening is I think it was continuously calling this function and causing some issues and then in the stop chasing function will also say is search equals false they stopped searching it stopped our growing blah blah one two three four five and he stops you can't find us and he stops after five seconds however for whatever reason is not turning around which is probably into something very simple here probably miss chase player function I can see if Cassie player checked right okay so here he's set to only chase the player if he can see the player would that's wrong because we've now added this is aggro below all this stuff will create another if to say if is aggro then chase player so I've got a good feeling about this now guys so if we walk into his range he'll follow us if he walk out for long enough ah still got us so he's tracking us all around now if I stand on his head for long enough he should stop moving you see that because he lost sight of us for more than five seconds and he's gone back to sleep but now if I wake him up again look he's going to track our direction that's really cool and if we stay out of the range for long enough oh good so that's working very well I mean obviously these things are far from perfect and need to be tweaked and revised a little bit but I think it illustrates the power of the raycast I used the same kind of approach in my own projects you can see here in my game blood and I made the enemies are shooting the Ray out of the eyes just like we're doing in this tutorial oh and blood and meat is currently available to wishlist on Steam so if you want to see how this game project turns out do consider giving it a wishlist I'll put a link down below so I'm just going to quickly go back here and do a very quick recap for you guys who are beginning and want to get a bit of update also if you're kind of copying on from screen you get an idea of what's going on here so from the top I've got a bunch of variables here the player the aggro range the move speed of the enemy and we have an is facing left which we're changing and more importantly in the update function here we checking if we can see the player passing in the aggro range setting it to true if it can't see the player if you can't see the player no longer then and it is aggro and it's not currently searching then search for the player and after 5 seconds start chasing the player so this is a kind of like mini mini AI kind of you know mechanism that as I mentioned will need it when it needs a little bit of work but it's a good good starting point for you guys if you want to tinker around and then we have this can see player which has the bulk of the code we want passing in the distance changing the distance to a negative or positive depending on if we're facing a left or not defining an end point based on the cast point star direction I'm using this shorthand annotation of vector right multiplied by the cast distance to create a the end position then we passing in both the start position and the end position using a mask filter to look for the action layer and then using the raycast hit or Collider check we are looking for the player if defines the player mark the value is true if not mark it as false draw some debug lines depending on if we can see the player or not and then return the outcome of this entire function back to this check here so they are using it like that I hope this video has been useful as always patreon supporters will get full access to this entire project all the source code all the assets and thank you guys who are supporting me on patreon you guys are really really helping me to stay motivated and to keep this content coming so thanks very much if any of you want it to be patreon supporters I'll put a link down below not only will you get the code for this project but you will get the code and project files for all the different tutorials as well as a bunch of cool patreon exclusive stuff that will be coming up very soon so please do like the video if you found it useful and don't forget to subscribe if you are new here and you're not yet a subscriber alright guys see you in the next video bye [Music]
Info
Channel: Lost Relic Games
Views: 36,878
Rating: undefined out of 5
Keywords: 2d player controller, simple enemy ai, enemy agro, unity2d, unity 2d tutorial, game development for beginners unity, agro range, how to, howto, indie game developer tips, learn c# for unity, ai, agro, enemy, unity, enemy controller in unity, raycast, linecast, raycast agro, enemy look for player, enemy find player, enemy search for player, enemy follow player, enemy move, enemy controller, enemy chase player, line of sight unity, enemy line of sight
Id: 2VX8uD_xUlM
Channel Id: undefined
Length: 32min 14sec (1934 seconds)
Published: Sat Dec 21 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.