Unity Basics - Waypoint Path system in Unity Part 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video i'm going to show you how you can make this waypoint system and this is going to be flexible that you can add onto it and expand to make it a bit more advanced as you want to add features after so we're going to take a player or just a general object we want to follow a path and then we're going to create all of these waypoints and draw the gizmos and draw lines connecting the path and then we're going to make the object follow that path after we create the system in an empty scene with just some prototype assets i'm going to show you how this system is modular and you can just click and drag it into any project you want like this demo scene i have here of a car racing game thanks for watching if you like these videos please click like and subscribe to help me out a lot and let's jump right into this so the first thing i'm going to do is create a 3d object and a cube this is just going to simulate a player i'm going to reset its position here and i'm just going to create a quick material for it i'm just going to call this blue material drag that on we'll give it a bit of a blue color here i'm just going to rename it player this can be anything a player an npc just a random object that's going to move around so in this case i'm just going to call him player just for the sake of it i'm going to create another 3d object here and i'm going to make a plane this is just going to be the ground reset its transform position here again and move the y down negative 0.5 that way it's right on the bottom of our our cube and i'll just scale it to something maybe like 20 by 20. okay i'm just going to give it a darker color so i'll make a gray material drag this on set it to like a dark gray so yeah something like that's good enough and then i'm just going to make a little square inside of this one just to kind of show the direction it's pointing so i'm going to create a 3d object a cube scale this down a bunch maybe like .25 and now if i move it out we can stick it out here i'm just going to make another material for i'll just call it red material okay so there that faces forward on the z direction now the next thing i'm going to do is make an object to hold our waypoints so i'm going to create an empty object if you're not familiar with the shortcut to create a new empty object here you can just do control shift n i'm just going to name this waypoints and i'll reset its transform position as well i'm just going to add a script to it i'm going to call it waypoints and under waypoints i'm going to make a child object here just an empty game object and another keyboard shortcut if you're not familiar with it to make a child empty object you can hold alt shift n i'm just going to call this waypoint okay so that's an empty one it's at 0 0 0 for position and this is what we're going to use for a waypoint i'm just going to move this randomly somewhere off so it's off the player doesn't matter where now let's go into our waypoint script and i don't need a starter and update in here what i'm going to use is a method that you may or may not be familiar with it called on draw gizmos and this is a method that's called in the editor so that we can actually draw something in the scene view and i'll demonstrate that in a minute here let's just draw a sphere for all of our waypoints first before we do anything so i'm going to do a for each loop i'm just going to do transform t and transform we want to loop through all of the transforms that are part of waypoints and this means it's going to get all of the transforms that are children and now in here we can use a command called gizmos and then we can pick a color so i'm going to do color dot blue and we can do gizmos dot draw wire sphere this is going to draw a sphere in the scene and by wire sphere it means it's a see-through sphere it's just a wireframe you could draw a solid one if you wanted as well now we need to pass in a center position and then a radius so i just want to use t dot position and then radius we'll just do one for now what we're doing here is this for each loop it's going to take every transform that's a child of our current waypoint system so if we look back here what it's going to do is get all of the children transforms under waypoints so currently we only have one here but you can notice it actually drew this blue sphere if i select this waypoint i can drag it around and anywhere we put it in the scene view it's going to show this sphere but if we look at the game view we'll just set the camera let's select our camera and another shortcut if you're not familiar with this one you can align the camera with the current view that we're looking at by hitting ctrl shift and f and now the camera is set here so if we look in the game view we don't see that gizmo and that's exactly what a gizmo is you've seen them already like if we select the the cube here this x y and zed little gizmo thing here this is a gizmo exact same thing we can just make our own let's go back to our script here and we're going to want to make a system that can draw a line between multiple waypoints now let's actually go here and let's duplicate this a few times so i'm going to ctrl d to duplicate the waypoint i'll drag this one over here ctrl d again drag this somewhere over here maybe like there ctrl d one more so there we got four waypoints they're kind of scattered around but just looking at this here we don't know the order the player is going to take if we look here it looks like they're in order but we could scatter these in some weird roundabout way put them like this you wouldn't really know the order just by looking at them so we need to make something that displays that for us now we can see each gizmo but we don't see how they're connected so let's do another after that loop i'm going to do gizmos again dot color i'm going to set this one to be color dot red and now anything we do with gizmos after this is going to be red until we tell it something else let's make a for loop i'm going to do int i equals 0 and then we want to do i is less than transform dot child count and then we also need to subtract one on this and i'll show you why in a minute here and then we need to increment i by one all right and in here what we need to do is let's do gizmos and then another method on here is called draw a line and this will just draw a line between two points so we need to give it the first point the first one we want here is going to be our our first waypoint so i want to do transform dot get child which is going to get a child in the hierarchy and they're ordered by number so let's just go back to the hierarchy for a second here if we look at them this is the first waypoint child under waypoints so this is going to be child zero and then the next one is going to be child one so it just works in sequential number and then if you move them here so if we moved waypoint two to be this one now this is going to be child 1. so the name does not matter at all it's the position and the order that they're listed as here now for the first position we want to draw from we want to use i as the child index which is our our loop counter so the first time it runs this is going to be child 0 we want to use dot position and then for the second point we're going to do the same thing but we want to use get child and we want to use i plus 1 to get the next child dot position now if we go and look we see it drew a line between all of these and to demonstrate why we wanted to use negative one if we didn't have this in what's going to happen is when we get to the last count which is the last child is going to try to draw a line from the last child to the next child which doesn't exist and that's going to give us this error here that transformed child is out of bounds because it doesn't exist so we want to stop one time before the last child and as you notice in the game from our last child it doesn't connect back to the first one so we want to do that now so right after this loop let's just do gizmos dot draw line and we can do transform dot get child and for the child what we want to do is use dot child count which is going to be how many children there are minus one and then we want to get its position and the reason we're using minus one here is just the the simple math on it so if we look here if we use child count we have one two three four children here but remember they start at zero so this is child zero child one child two child three if we want the last child we actually have to remove one because this is child three not child four it would only work if we started this one at one instead of zero so just something to always be aware of because that can cause a lot of errors when you're starting out okay and then the next position we want to make it to is transform.getchild and then zero because we want to go to the first child all right let's go take a look this should draw a loop between all of our objects here and now you can see in the editor if you drag it around it updates real time you don't have to compile or do anything else because ondraw gizmos is running all the time in the scene but it doesn't run when you're in the game view and i just want to demonstrate that because if you look at this you might think this is going to waste a lot of resources when your game's running because every frame we're we're doing a update where we search through all the transforms we draw these spears and you think if we have a whole pile of these we're going to slow down our game i just want to show a demonstration in draw gizmos here i'm going to do debug.log and i'm just going to put test we don't need to say anything so now if we go back to our game let's refresh this okay so notice test is running it's kind of running randomly it doesn't run every frame but it is running and if i start moving on around notice as i'm moving it will update every single frame so it looks like it's doing a lot of work here and it's just updating on changes but if we go to the game tab i'll just clear it to demonstrate notice that code is not running at all and this is with the game off and the same thing happens if we run it so if we run our game even though nothing's going to move right now let's just take this off maximize so if i run it right now nothing's actually moving but the game is running if i go to the scene view now you see it's updating constantly but if we go back to the game view it's not updating so that's just something to make sure you're aware of andra gizmos is only going to run when you're on the scene view editing your game so this isn't going to cause impact when the player is actually playing the game this is just to help us visualize and see what we're creating one thing we can also add in here is i'm going to make a serialize field private float i'm just going to call this waypoint size i'll set this to be 1. i'm actually going to add in above it i'm going to add range and you can set this to be whatever you want i'm going to set this from 0 to maybe 2. if you're not familiar with range it's an attribute you can add for a variable here and it's going to make a slider bar between these two values let's take our waypoint size variable and replace it here in the draw wire sphere now if we go back to our scene view we have our waypoint system and we can actually change the size of these so you can make them be as big or small as you want and if you don't like the wire frame one you can just change this to be just draw sphere so if you save that and we go back and look now you can notice it's a solid one but when your object's moving through you're going to see it's going to go into the sphere and sometimes it gets visually hard to see so i'm going to leave them as wire sphere but that's completely your preference okay so we have that set up now when the player or the object's moving trying to use these waypoints we need a way for it to actually get what waypoint it should be moving to so i'm going to make a public method here and it's going to return a transform i'm just going to call it get next waypoint okay and what we're gonna do is we're gonna pass in a transform and i'm just gonna call it current waypoint and i'll explain this in a minute here once we actually create it now for now i'm just going to do return null just so we get rid of that error so we don't have any errors let's go back to our game i'm going to go to our player and i'm going to add a script i'm just going to call this waypoint mover so you can name this whatever you want or you could even do this right inside of something like a player script or a player controller but i like to keep them separate so that you can add this to any object so you could add the same one to a player to an mpc to just a random rock that you want to roll around your scene that way it's not locked into any other component you can just make it separate on its own first thing we're going to need to do is get a reference to the waypoint system so i'm going to make a private i'm going to call it waypoints and let's just call it waypoints okay i'm going to make a note here stores a reference to the waypoint system this object will use or just something there just so you know what it is and make another serialized field i'm just going to make a private float move speed i'll set this to maybe 5 by default this is going to be how fast the object moves and then i just also need a private transform and this is going to be the current waypoint we're moving to okay so something like that so that's our variable setup that should be all we actually need the first thing i wanted to do is if we go and look at our game here in this example here the player objects not actually at the first waypoint or any waypoint for that matter what i want mine to do and this is optional you don't have to do this if you don't want but when we start our game if i had the player over here and say this was the first waypoint i don't want them to start randomly moving to that waypoint i want them to be there so i'm going to do that in my code here the first thing i'm going to do is make the player move to the first waypoint so in start i'll do something like set initial position to the first waypoint okay and now we need to get that so current waypoint we need to call something to actually get this and we did start our get next waypoint method so i can call getnextwaypoint or sorry we need to use our waypoints script up here the reference so waypoints.getnextwaypoint and i need to pass in a transform and you're going to see why we decided to go with transform right away here but when we're getting the next waypoint what we want to do is pass in the current waypoint that this player has so if we just pass in current waypoint this is going to tell our get next waypoint method what waypoint we're using currently and if we didn't do this then we would have to do some tracking inside waypoints here so for example we would make a variable and it would be you know current waypoint or waypoint index something like that and it would track which waypoint the player is moving to and we would update it each time but the problem with that is you would only be able to use these waypoint systems with one object because if you were using it with multiple different players trying to move on this this waypoint system they would all think they're using that same waypoint number that's in here by doing it this way every time we need a new waypoint we can just say hey waypoints this is where i currently am what's the next waypoint to go to and then that way we can use it as many times as we want so let's go back in here and now we have to actually do something here so i'm going to remove this line and with the current setup that we have here what's happening is in start we're calling waypoints.getnextwaypoint passing in this current waypoint which currently has nothing in it that means it it's currently null so if we go into waypoints the first check we can do here is let's check if current waypoint equals null what we want to do is return transform.getchild0 which is our first waypoint basically what we're saying here is if something calls this method and it passes in a waypoint that doesn't exist which means it's null then tell it go to the first waypoint now we can test this out we just need to do i'll just do a return null here just to get rid of that error because otherwise it'll say if waypoint's not null it's not returning anything so we always need to return something out of this method so this is currently only going to work for this one case but if we look at this here this should work now the first time so what we can do is let's set our players transform.position equal to currentwaypoint.position let's go run the game [Music] oh and we're getting an error that's because on player we didn't drag in our waypoints yet so we got to drag in the reference to the waypoints now let's run it and if we look at our scene now our player's right on position one and if we stop he goes back okay so that's perfect don't worry about this error that's because of what we're doing right now that's just for testing okay so that works with the first position now we need to do it again so what if we pass in something that's not null so we need to do another if statement here and we need to do a current waypoint and now we need to check which waypoint this is in all of our waypoints the way that we can actually do this to check what child this current waypoint is is very similar to how we used get child with an index we can actually use current waypoint which is a transform and transform has a method on it called get sibling index so if we do this what this is going to do is just like we used get child to get the child at zero position this is going to get the actual index of that and why it's called get sibling index is when we look at it here say if we passed in this waypoint as the current waypoint all of its siblings are these ones all of the ones under the same parent so what it's going to do is it's going to get the index under this parent which in this case is going to be 0 and then 1. so it's going to have a sibling index of 1. this one will have 2. so it's the exact same thing as get child except the reverse in this case we know the object or the transform but we don't know its position so now using this this is going to give us the actual sibling index or the the child index if you want to look at it that way and then we can make sure it's smaller than transform dot child count minus one and again the minus one is because we don't start at one we start at zero now if this is true what we want to do is we're going to return transform dot get child and the child we want to return is current waypoint dot get sibling index plus one so basically we're saying if this sibling is anything except for the last sibling that's why we're adding the minus one then just add one and that's the next one so we need one more thing here we need to do else and what this is going to do is if this is the last sibling then we need to return the first one so we just return 0 again so to give a bit more of a visual if we pass in any of these waypoints we're checking with the negative 1 to make sure it's not the last one so if we pass in this one we're going to return this as the next one if we pass in this one we're going to return this as the next but if we pass in this one we know it's the last one so then we return the first one so that means the player or whatever object we're moving is going to loop through each one it won't try to go to a next one that doesn't exist now we can start testing this out so let's go back into our mover so now we added the first waypoint and we moved our player there so now let's set the next waypoint target so this is one we're actually going to move towards so let's do current waypoint actually we can just copy this whole line because we're doing the same thing okay so we have that but we don't want to move him there yet because he'll instantly just snap there and we won't even see him go to the first one so that's where we got to do it in update here so all we have to do here is let's do transform.position equals and we'll just do vector3.move towards to keep moving them there and we just need to pass in our current position and then our target position so we'll do transform.position which is where we currently are and then we're just moving to currentwaypoint.position and now for for how much we move we just want to use move speed times time dot delta time okay and that's it for moving but this is only going to move us to one so let's test this out make sure it works okay so we move to our first one and then we stopped because we didn't tell them to do anything there but that's working so now we can move on to the next one and to do this we just need to do an if statement and we can do vector3.distance and we need to pass in our two positions so our current position and then our current waypoint.position and we just need to make sure it's less than a certain amount so we should probably make this into a variable so let's do maybe i'll call it distance threshold so let's go create this we'll make it a serialized field that we can change in the inspector if we want so oops that needs to be float i'll try something like point one that should be good enough okay so if these two positions are closer than this then what we need to do is current waypoint we need to get it the next one now let's go and test this and this should be working okay so we move to the first one we move to the next one more back and we should loop all right so that's basically a simple waypoint system you notice our guy's not rotating though so a very quick solution to that we could do in here after we get our first waypoint that we're moving to we could do transform.look at and then just tell them to look at the current waypoint we don't even have to say position because lookout can take in a transform okay and then let's copy that and paste that in here so every time we get a new waypoint we're just going to look at it so now if we run it he should face the waypoint but this is going to be very snappy movement so he instantly moves there's no smooth transition okay so you see that's working so that's our basic waypoint system there is a lot that you can add onto this though i tried to keep it very basic so we're not using anything fancy in here but you could start adding things to to liven this up and make it more of a utility to use so for example in the waypoints you could make it so that you can pass in on this method to get the next waypoint you could also pass in a boolean if you're moving forward or not if you're moving forward return this but if you're not moving forward which would be reverse you would return the previous waypoint and then another thing you could do in here is you could disable it from looping instead of making it loop and go in a big circle you could make it have an end at the last waypoint so it wouldn't draw this line and it would just go from there and then you can make it kind of ping-pong and go in reverse so there's a lot of versatility that you can add to this as well for the rotation to make it more smooth on the waypoint mover you could do something in here where once you hit this this position and you get a new waypoint you could run a co routine and tell it not to actually start moving yet and do a slow rotation to that target and then once you're rotating towards it then you could start moving so something like that just adding little features here and there what i'd recommend is doing something like this and exporting the package so you could save it as your own custom package and then from there when you work on new projects bring it in and as you start adding new features just keep exporting the newest version and to demonstrate how handy that can be i'm actually just going to show you so this is our simple little kind of prototype scene here but i also have this demo scene that i set up here this is just some cinti assets that i own and what i did here is i just put this car at this spot of this track here and there's currently nothing on the car at all so to use our waypoint system what we can actually do is let's just create an empty object here so ctrl shift n i'm just going to reset its transform i'll call this car waypoints now i'll create another empty object here i'm just going to move it to kind of the first position i can put it in place and now drag it in as a child so then it's right here so i'll call this waypoint now all we have to do is on the car waypoints let's add our waypoint script okay so now we see our waypoint let's make it a little bit smaller for the gizmo and then on the car we add our waypoint mover drag in our waypoint system okay and now on waypoints control d let's make a waypoint here actually maybe i'll move the first one to where the car is this one over here make another one over here another one over here and something like that this one you're going to see them go through the wall because this isn't the whole track but i don't want to go and make the whole circuit but now notice they are raised up in the air so we just got to drop it down to i'm going to select all of them set the position to zero okay we weren't actually on the ground plane so got to move these again that's my bad there okay so there's that one do one here okay so we'll treat it like this is the end of the track so ignore this part but if you went through and you you did the whole track with all the waypoints he would go the entire path so now if we run this now we can see our car going you can see like i mentioned the the rotation just snaps but if you were to actually smooth that out you can make this car go through an entire waypoint system here and then you could start adding things you could even add in little features that make it drift when it's turning things like that all in your waypoint system so there you go that's a basic waypoint system i hope you like that one if you do want me to cover more of those topics i mentioned like other ways we can improve on this let me know and i can always make a video and we can start making it more complex i wanted to keep this one pretty simple so it's it's still fairly beginner friendly but thanks for watching and i will see you in the next video
Info
Channel: MetalStorm Games
Views: 33,797
Rating: undefined out of 5
Keywords: unity, unity tutorial, unity basics, unity waypoint, unity waypoints, unity paths, unity pathing, unity waypoint path, unity how to patrol, unity patrol, unity patrol system, unity basic waypoint, unity basic path, unity basic patrol, unity beginner, unity beginner waypoint, transform.getchild, transform.getsiblingindex, transform.childcount, childcount, getsiblingindex, unity getchild, unity childcount, unity getsiblingindex, unity path
Id: EwHiMQ3jdHw
Channel Id: undefined
Length: 31min 57sec (1917 seconds)
Published: Fri Nov 26 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.