Easy Movement Queuing, Paths, & Tweening in Unity

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Welcome and thank you for your contribution :)

👍︎︎ 1 👤︎︎ u/dilmerv 📅︎︎ Jan 03 2020 🗫︎ replies
Captions
one thing we have to do in almost every type of game is move objects around whether it's a car moving around a racetrack just a game object floating around the screen or maybe a UI element that slides in and scales up when the player presses a button it's something that you're gonna need no matter what you're working on so in this video I'm going to show you a couple cool ways to do that including using tweening libraries we'll talk about how to use do tween to accomplish a lot of these tasks but then I'm also going to show you how to code it yourself in case you don't want to use a tweening library or you just kind of want to understand how it all works now before I get started I wanted to point out that this question actually came from a student in my architecture course if you're interested in that there should be a link down below that you can go check that out but if you're not just go ahead and hit like share and all that stuff and then we'll get started now before we get going with the UI scene I wanted to show the UI pack that I grabbed from the asset store this fantasy wooden GUI pack and also mention that we're using do tween which you can see under tools and this I I'm not sure how you pronounce that then the do tween utility panel so I've just pulled in these assets from the asset store so that we can do a good quick example of how you can use them to do cool UI stuff without having to write a lot of code so here I've got a scene set up I slightly modified the introductory scene and rescaled things a little bit we've got a large board over here that's set to a thousand by 600 and notice that the scale is at 0.7 that's going to matter in just a little while it's got a close button here that I've hooked up and then we have two buttons down here this blank one and this button that says new start the new start button has a single on click that's calling this fly-in board example dot fly-in I'm gonna press play hit it show you what it does and then we're going to talk about the code and how the tweening library actually makes this all very simple to do so let's hit play and then I'll hit start as soon as it kicks up there we go hit that and you can see it just kind of slides in and scales up my close button doesn't work yet but it's moving in and I haven't really written any code let me show you what it actually does so like I said this button is hooked up to call this fly in method on the fly board example I can click on it and see that it's on the large board and if I go to the large board I can see my fly on board example script it's two little fields here we have an end of scale which is one and remember I said that this starting scale was 0.7 we're actually ending it at 1 once we scale it up you'll see how that works in just a moment and an ending exposition of 0 you can see that the exposition here is at negative 1,000 if I put it to 0 that's where it's going to I'm gonna hit control Z and undo that though and now we're gonna dive into the code so let's open up the fly n board example here you'll see that we've got a reference to a rect transform which is just referencing the same game object it's really referencing itself we have the end scale that's the one that I showed you was at 1 and the end position this fly-in method is doing all of the work well really it's telling do tween to do all of the work all we have to do to make all of this happen is say target rect transform which again is just the object that we're on let's go take a look at that real quick to show it so here's our large board and you can see the rect transform is actually just pointing at this in fact I didn't necessarily need to put that as a field I could have just got the rect transform and awake and cached it if I wanted to but I was kind of playing around with it and controlling different objects and kind of ended up here so I just wanted to point that out though and then let's go back to the code so here we're calling do local move X and this is available because of that do tween library this is an extra extension method on top of rect transforms and on top of just transforms in general it doesn't just work for rect transforms you'll see that in just a little while when we move some other objects but it takes a couple of things it takes an x position or an end value which is that 0 that we're putting in it takes a duration which is just how long it's going to take to move over and then it has an option to snap so that we can snap by integer values and we don't want to do that here because we want to smoothly move but you can imagine if we had something wanted to pop over one at a time or something we could do that the other important part here and this is the really cool part is the callback we have this on complete this is actually just part of this call I could have it right up here if I wanted to but I like to split them out in fact I'd probably do it more like this so that you can see they're just kind of called one after another and this is done with a builder pattern you can see some videos on this later if you're curious how we stack up the methods just know that with the do tween system it's said so that you can call a method and then another method you can call it to add parameters and everything else in this case we're just calling an uncomplete callback so we're saying this direct transform should move its local exposition to this end value which is just zero so right at the center over to seconds and when it's complete we want it to call this scale method and here you'll see that the scale method just says hey same rect transform do a scale and go to our ending scale which is that one so remember we're going from 0.7 to one and we do it over half a second pretty cool right and pretty simple to do and we could also you know if we wanted to add a dot on complete here and make it do something else call another method or even put in another lambda like this we could say hey on complete fly in again that wouldn't necessarily do much because it's already at that position but if it had moved away or something or we put it into a looping system we're like flying away or whatever we could keep changing these on completes it's kind of the point right or maybe we could do like a debug log hey we finished but we don't want to do that instead what I want to talk about now is how to make them rewind able because that's another cool feature that's built in to do tween so let's go check out the rewind herbal version of it let's hit play as soon as it starts up and what we're gonna see is this button should make this thing fly in in a little bit slightly more interesting way and then we should be able to hit X and make it disappear and play it again and play it again so let's try that out so we hit play and as soon as it finishes starting up we can hit this button right here and you can kind of see what it's doing there it shakes in and then pops up and scales up and then I can hit the X to reset it and hit this again and just keep doing it see I think you can get an idea of how useful this can be for building UI stuff so that we don't have to build a whole bunch of custom stuff or a whole bunch of custom scripts to do all of these things and once I get into the code again you're gonna see just how cool it is first though let's look at that button one more time so this is oh this button right here the blank one and it's calling on the same object but we're calling sequence fly-in which you may have seen in the code right below a slightly spoiled it there let's go check it out though the sequence fly-in method is a little bit different in fact let's collapse these two because we're not looking at those anymore the sequence fly-in method creates a sequence which is just a new tie or a new class that's in the do tween library we call sequent do tween dot sequence to get it and then we also to make it rewind able need to call dot set auto kill false now if I do it without this and I just call sequence without setting Auto I'll kill the false what'll happen is once it's done running the sequence it's going to clean itself up clear out those tweens in that data so it won't be able to reset it I need to call this if I want to be able to reset it and reuse it the next thing that we do is call sequence dot append and here I think you can see that these are very similar to what we were calling in fly in and in scale we're calling a do move local X to a position with the duration and then the one thing that's a little bit different the reason it's kind of bouncy is because I'm also adding this dot set Yi so of course I could do that up here in the fly and I could just say dot set YZ and if you look once it pops up we actually have quite a few options here let's get the autocomplete up you can see there's a flash a bounce a circle cubic elastic X but there are a whole ton of them and to be honest I don't know what 90% of them do but if you play around with them or look at examples you can see how they move in and out and do some really cool stuff that I think is especially useful for UI development the other important part here is the rewind rewind just calls sequence sequence dot rewind to reset this thing and that's just being called by the buttons close button or the the board's close button so if I select the board go down here to this image which is the close button there you can see it there and scroll down you see this is just calling rewind on it so it's pretty cool and pretty interesting setup that allows you to do nice little tweens and nice little UI fly-ins flips bounces all kinds of different stuff for moving your UI around that's cool right but now I want to talk about how to do it on your own so say you don't want to use a tweening library for some reason maybe there you have some requirements some restrictions that prevent you from using it or you just kind of want to understand how to move things around on your own we're not gonna build up all of the functionality in do tween but we're gonna set up how to do some basic movement with callbacks to do that I've set up another sample scene and we'll go into well I actually named it sample scene it's a beautiful one we're gonna start with the cube and then we're gonna move on to a cool car flying around on a racetrack which i think is a little bit more interesting but I wanted to start simple and slightly boring I'm gonna go out of 2d mode for just a moment in my scene view select the cube hit F and kind of get around there we go so that I can see the actual object and then let's hit play see what it does and then talk about the code but notice here on the cube we have a mover script and it's got a speed in meters per second it's set to 25 I'm gonna hit play or it's a movable script I might have said mover there because I'm looking at the mover up here in our scene hierarchy the scene hierarchy has a reference to this mover and as soon as I turn it on this move controller's gonna kick off and say hey move or go do your thing so let's turn it on and watch what it does that just kind of bounces around if I turn it on and off again it bounces around that's because I'm using the on enable callback here to trigger this thing and make it fire off and if I go from another view you can kind of see how it's moving around now let's well what should we do let's take a look at the mover script first alright no actually first I want to show it slowing down let's slow it down by setting this to 5 select the mover turn it off and on again and watch as it moves slightly slower that's kind of important because I think it'll help understand the code a little bit more so let's go into the move controller script move controller script has a public moveable target oh I shouldn't have left that public I should have made this private and serialized let's change that right now say private serialize field got to keep the code clean when we're writing examples so there we go we've got a target that we can assign in the inspector and then we have on and able which is just calling move with mover note I also haven't moved with do tween example that we're going to show right after this so move with mover says target dot move to and we give it a vector three which is just a position that we want to move to so we want to move it to 10 on the X 0 on the Yser on the Z then we say on complete notice this comma right here it's saying on complete call this again we're saying well it's not so much call it again well call it again but with different parameters we're going to 0 comma 5 comma 0 and on complete of that we're saying target dot move 2 and we're going to 1 comma 1 comma 1 so that's why it's moving too different positions after each one of these move twos it's saying hey when you're done go do this next one go do this next movement action now that doesn't make a lot of sense if you don't know what move queue is right because move too is a method that we've coded ourselves or I've coded and I'm about to show you it's not part of the do tween library so to get to it I'm just gonna hit f12 and it's gonna take me right into my moveable script which still has a breakpoint here I'm not sure why that hasn't gone away it seems like an odd writer bug but let's take a look at the move to method I'm gonna zoom this in just a little bit and then we'll go up and look at all the code so the move to method takes a destination and then an action for on complete and this is where the callback comes in you're gonna see that in just a moment when we actually call it so we take the destination and we figure out the distance from our current position so this is the position that we're at when we call move to not like every frame it's just when we start moving in our destination what's that distance and we're putting it into this float right here and then we're saying the total lerp duration which you're gonna see the Lord ping in just a moment is gonna be the distance divided by our speed and meters per second so it's gonna tell us how long it's gonna take us to get from our starting point to our ending point we'll set our starting position which we're just cashing into a vector3 as our starting position or the position that we're at our destination will just be that destination that's passed in the elapsed duration so this is how long we've been moving our objects is gonna get reset to zero because we're gonna reuse that every time we call move two and then we set the on complete call back to this on complete that it's optional that's why it has equals null here means that we don't necessarily have to specify it but we can if we want if we want something to happen when this is done it can just be added in here as a parameter also note that that doesn't necessarily have to be a move to action if I come into my move controller and just add a comma after this last move to parameter right after this vector three parameter I could say you know I need to open up with a lambda so I'll go open closed parentheses equals greater than and then maybe do a debug dot log and say I'm done moving so this action could be anything now let's go back to how that's actually working let's go back back and we set all of this data up and none of it's actually doing anything we're just kind of setting up our fields so that our update here let's actually let's do a quick zoom out take a look at those field so you see our fields right here that we've been setting up and that move too but everything's actually getting worked upon using the update method the update method is doing a couple things first we're checking to see if our destination has a value that's because if we look at destination its nullable that's what this question mark means just means that it could be a vector3 or it could be null so if it doesn't have a value that's never been set then we just want to return there's nothing to do we don't have anywhere to go next we're checking the elapsed lerp duration if we've been moving for longer than the total duration or equal to it then we want to bail out and exit also if our total lerp duration is not greater than zero we want to bail out too so we're just making sure that we have a duration and that we haven't passed that duration if we have then there's nowhere to move to nothing to do the next thing we do is increase our in elapsed loop duration just by the time delta time then we figure out the percent of the way that we are along our time so if for one second into a ten second loop duration will be 10 percent and we'll get a point ten and then I'm just spamming it out here in the log for fun because why not spam the log for fun of course you don't want to do this in a real thing you want to delete that log entry but if you're debugging and checking it just trying to understand how it works logging is always interesting way to do it the next thing we do is set the transform position by using them vector three dollar really we're calculating out a position with vector three dollar this is returning that position and then setting it right here into our transforms position so vector three dollar works like this we give it a start position which is where we started at at the beginning of this in our move to which remember is right here we're assigning it to our original position when we call move two we give it a destination position which we have to use the dot value for because this is nullable if we don't give it the dot value we're going to get an exception saying hey or an error filled error saying this is a nullable value it's not necessarily a vector three so we use the dot value and remember we're validating that it has a value here and then we just give it that percent which is going to be between 0 & 1 so remember if we had a one second or for one second into a ten second loop it be 0.1 and we'd move ten percent of the way across then we check to see if our elapsed duration is greater than or equal to the total remember before it gets it gets through here on the first call and then their elapsed will get incremented and if it gets to the total or a little bit greater then we call the on callback complete or on complete callback by using on complete callback question mark dot invoke the question mark here just means only call this if it's not null if it's null then just don't do anything that's the same as adding a null check right before saying like if on complete callback is not null then on complete callback you can shortcut it with question mark dot and then what does that do well whatever we've passed into on complete just gets called again so if we look at our mover controller the first one happens it calls move to once it's done this on complete which is the second parameter here gets called and it says hey move to this one and then once that's done the next parameter is this on complete which is it gets really a parameter of the next one it's kind of interesting if you start putting these all on one line but it gets really messy so I like to have them on separate lines and tabbed over so that I can kind of follow the flow but hopefully you get the idea now there are ways to write this a little bit cleaner the way that do tween does it where the thing returns a reference to itself it's a whole pattern I have a video on it maybe I'll link that down below to show you how to do that I didn't want to over complicate things too much though let me show you what it looks like with do tween though so we'll comment out the move with mover and if we look at it here you'll see that it's very similar we call target transform dot do move we give it the position and the duration and then here we call dot on complete and we give it this so this is kind of the different version of it it's what it could look like if we wanted to write a little bit more code in our move with mover method or our actually be in our mover method so hopefully this is somewhat helpful and gives you an idea of how you can chain these actions together with simple events and simple callbacks in there let's go take one more quick look at the moveable remember this callback gets called in the update at the end of it essentially when it has reached the position that's what this is saying this is reached position let's type that in really this should probably say if reached position or if made it to the end or something like that or time has passed to the end something like that then call the callback but here we're just doing the check and I put a comment there not my favorite way to write it but hopefully you're understanding the idea now let's go into the car example because I think that one is probably the funnest it may not be the most useful but it's certainly the most fun so if we go into the scene our scenes folder and I look at my car move queue example here we've got a car that races around let's take a quick peek at it zoom out the scene view a whole bunch by the way that's just hitting this up arrow or this wide and it'll give us a top-down view from our camera and then I'm gonna select the car so I can see where it is on here hit play watch it drive around real quick at 25 meters a second and then we'll look at the controller that's setting this up and making it move because we don't want to necessarily say hey move from this point then this point then this point then at this point and we don't want to hard-code all of those things in we want to make it a little bit easier on ourselves and make it so that our game designers or ourselves that for the game designer can do this without having to write a bunch of code and change things every time something gets moved around or we it be a mess imagine moving across all of these different way points by writing in code you don't want to do that so what have I done here instead we have this Waypoint Move controller and I'm going to expand it out if you look underneath we actually have a bunch of waypoints and if I select them I'll just go through I want you to just look in the scene view here let's uh drag this around let's see it's gonna get a little bit better view here so you can see it more watch as I select these waypoints where they are so you see that ones over there then we go over there down a little bit more a little bit more and we're just kind of coming around and looping and essentially the waypoints are at the different corners so if i zoom in here and just take a quick look you'll see that what have we got six is down here at the bottom then we go seven eight nine ten and we're just going up the ramps and I put them at all of the turn points and they're facing in the direction of the turn that I want and eventually near the end I got a little bit lazy and just let him shortcut across the grass and stop driving because I didn't want to put a bunch of waypoints in so how does this all work because these waypoints don't have any scripts on them the car still just has that moveable script and the Move controller is the only thing a little bit different so let's open it up we have this Waypoint move can Toller script it does a couple of things first it oh no it calls the target a public movable when I should have made it private so let's change that but make it private and use the serialized field attribute again this is so that our code can't accidentally break the thing when we make them public like that it's very easy for somebody to misuse our code so if we want something that's only setup from the inspector I want to make it private and use the serialized field attribute so that it can only change from the inspector or inside this class it can't be changed from outside the class and it doesn't end up confusing people by not knowing hey should I be setting this enough about that though let's look at the rest we also have a list of transforms called waypoints and then we have an integer for our next Waypoint index our waypoints are not serialized they don't show up in the inspector instead in on and Abel I just find all of the components and children that are of type transform and put them in a list one thing that that does though is it finds itself get components and children will also find the objects that you're on and I don't want to use the Waypoint Move controller with that game objects transform as a Waypoint so I just remove it here on line 16 so ya know removing myself then I call move to next Waypoint that's it so on and able we save move to next Waypoint move to next Waypoint let's zoom it in a little bit and make it nice and big it doesn't do a whole lot it calls target dot move too and here we're getting the Waypoint @ Waypoint index and then using its position so we could also kind of pull this out if I wanted and cut that and say far target Waypoint transform equals this so we're getting the transform out of there and then we're moving to that transforms position the other thing that we have here notice this second parameter remember if I get the autocomplete up that's our on complete so on complete whenever this finishes we're not calling a method in the target we're actually calling this move to again so every time we go through it will say hey move to this one and then when you're done call this again that's it so that's that's essentially how it's gonna work every time it's gonna loop through and just keep moving to itself now I do have this one little line of code here that I'm not too happy about this should probably be in a mover or a looker or something else but we're just calling target transform dot look at the next Waypoint so while we start moving to it this code is also calling the thing to make it look at it ideally we'd probably want to set up our moveable to also be look above or something else so that we can make it look and rotate and lerp that rotation we can actually do a quaternion dot lip and have it slowly turned towards the right direction or maybe a fast return or something like that that would make more sense for the game but since it's not a game it's just a car moving around the track it didn't matter too much and I didn't want to over complicate that part the final thing that we're doing here is setting our next Waypoint index so we just increment that Waypoint index so the first time it went to index zero went to the first Waypoint second time we call through so when that finishes the move two will get fired off again from that action that we're passing in and it's gonna go to Waypoint one because we've incremented it here after calling move two you remember this move to you we're not waiting on it we're just setting some data and then that thing is going on its own we don't have to wait there's no hang here or anything else to move to it's just a method that we call the set data and then the movable handles that so once we've done it we've incremented the index so the next time it calls through it's gonna move to the next Waypoint if we get too high in our waypoints we get passed the last Waypoint we just reset back to the first Waypoint and today we have a simple loop where we just go through all of our waypoints and of course if you're building out a waypoint system you'll probably want to put in some custom editors and inspectors to make them snap to the ground and be visualized and maybe do some validation on them to make it easy to do as fast as possible so that you don't want to take shortcuts and just have your car drive across the grass you could also do some randomization pick a random Waypoint as your starting one you do all kinds of fun little things but the important part here I think is just this whole pattern of telling it to move somewhere and then telling it what to do afterwards giving it that callback and having that flexibility to make it do something else and again we don't necessarily have to say hey once you've gotten there move to the next Waypoint we could say hey once you get there sleep for a little while you know beep your horn and spin around and then move to the next Waypoint we do whatever we want there because our callback is generic just a method that we're gonna call when we're done anyway I hope this is somewhat helpful for you guys if you have questions I this don't bother or don't feel fruit what I mean is feel free to ask me just shoot me an email drop a comment down below there's something that you're curious about and wondering how to set up also again if you're interested in the architecture course there probably a link down below but most importantly don't forget to Like subscribe and share and also I really wanted to say a special thanks to everybody on patreon you guys are awesome I really appreciate it and I think that's it alright thank you again goodbye you
Info
Channel: Jason Weimann
Views: 47,486
Rating: undefined out of 5
Keywords: dotween, itween, tween, unity, unity3d, unity 2019, unity 2020, unity movement, unity movement tutorial, game development, unity movement 3d, unity ui movement, unity ui elements, unity ui animation, game development for beginners, unity movement brackeys, unity movement script, unity movement code, unity ui button movement, unity movement rotation, unity movement animation, unity pathfinding, unity path tracing
Id: PLFQp0TvsK0
Channel Id: undefined
Length: 25min 15sec (1515 seconds)
Published: Fri Jan 03 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.