Creating a 3D Character Controller in Godot with Animations! C#

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys this is Mitch with finepoint CGI and today we're going to talk about how to build a 3D character controller in C sharp in Godot so we're going to go through the process of building out our 3D character controller we're going to talk about how to code the different interactions so running jumping things like that we're going to talk about how to handle our camera and make it so our camera can go up against walls and not get pushed through the wall we're also going to talk about how to set up animations it's a common thing that a lot of people don't cover is is how animation trees work how State machines work and how the blend shape 2D actually operates so once we're done with all this hopefully it'll have yourself a pretty decent character controller so with that being said let's go ahead and get started okay so the first thing that we're gonna do is we're going to build out our character now I already have a character built specifically for this tutorial and if you guys want to know how I built that character go ahead and take a look at my previously released tutorial where I talk about how to take a miximo character and basically compile all your animations and things like that and then put it out for Godot now I do have a link to the starter scene which is this guy here and this little character.glb if I right click that guy and I make a new inherited scene this is what you're going to see is a character object here it's going to have some animations right here already created for it so you can see my idle animation my strafing animation my walking animation things like that so make sure you guys download that starter scene if you don't want to do that that's totally fine and you can actually follow this with just a capsule shape or of course you guys can use your character if you have one now what I'm going to do is I'm going to right click my character here and I'm going to change its type and we're going to make its type a character body 3D and that's going to de-link it from blender so if you have a DOT blend file or something like that just keep in mind that you've now de-linked from your inherited scene so that's just something to keep in mind now once we have that we need to add some kind of collision to it so we're going to right click our character attach a child node and we're going to add in a collision shape 3D and then we're going to make our shape into a capsule shape we're going to hit control and we're going to drag this guy up one unit and that's going to encapsulate our entire character now from here we need to actually set a script for our character so we're going to come into our character we're going to right click it attach a script we're just going to stick with character.cs and we're going to use the character body basic movement template and that's really nice because this template basically does a lot of that additional work for us so if we click create you'll see in a second Visual Studio is going to load and I'll make it snap into the correct size for your guys's screen and you can see here that it already did a bunch of the work for us that's one of the really cool things about the um template system is that it has a template already built for us now if we go back to Godot we hit Ctrl s and we save this as player.tscn we go back to our node 3D and we drag our player into our node 3D you will see here is our player now you can't use a character without having some kind of camera so if we right click our character and we add a child node and we add in a camera 3D we just drag them up like this and just kinda face it in the general direction of our player here and we hit Ctrl s and play you'll see hopefully if it all builds correctly that we have a character here if we hit left and right you'll see we can move left and right forward and backwards so we can move forward and backwards and we can jump so awesome and if this is really all you need for your character controller there you go you have yourself a well-built little character controller now in our case I want to add in the ability to make it so that we can move our camera with our Mouse so if we close this let's do some additional work here so first things first I'm going to decouple my camera from my character body and the reason why I'm doing this is not because it's a better way of doing it but it's because it's a different way of doing it so when you decouple your camera you're basically creating a node putting your camera under that node and having that node follow your character around the nice thing about doing that is if you need to move your camera away from your your character for some reason you can if you want to make some adjustments to your character without it affecting your camera you can do that as well so that's just something to keep in mind now I'm going to right click my node 3D I'm going to add in a child node and I'll add in a node 3D and I'm going to drag my character camera underneath my node 3D so now when this moves it's going to move my camera and what I'm going to do is I'm going to rename this as camera controller like that and then I'm going to right click my camera controller I'm going to attach a script and I'm going to attach a camera controller.cs we're going to go ahead and create that and basically to get it so that it follows our character all we need to do is basically in our process just get where our character's position is and then move it to that location now you could do this in a lot of different ways but the easiest way to do it is by going into your character going into your character scene and then coming over to node groups and then adding it to a group and I'm going to add it to the player group and that's basically going to allow us to get a universal reference to that player's location so we can come over to our camera controller right here and we can basically just say get node get tree dot get nodes in group player and we need to cast it as some kind of object so we'll cast it as a character because it's a character type and then we'll pull back our first reference of that object and you'll see that we have it underline here so non-generic method string name cannot be used oh I guess we can't use it with type arguments we're going to have to do it like this and then we'll need to say if we come over here character character is equal to this and we'll pull back our first element as a character and that will basically cast it as a character object and dump it into our character value now from here we can basically just say Global position is equal to character dot Global position and that'll basically handle that aspect so now if we hit play and we allow ourselves to play and you can see that it didn't work but why didn't it work right it should have worked I mean if you look uh we have camera controller we have our script here which has camera controller and and we have our stuff and it should have worked well here's the reason why it didn't work if we look at our debugger and you look into errors you can see cannot instantiate script because it Associated class cannot be found script res camera space controller.cs so here's the thing you cannot have a space in your file name of your Crypt and if you take a look at the actual script itself you can see it's camera underscore controller and Godot was nice enough to attempt to fix it for us by adding in an underscore but the problem is is that it didn't insert an underscore right here so it's camera space controller and so since there's a name mismatch there it is a common problem that people run into where they add a space or something like that and it completely breaks their entire c-sharp project that's just something to keep in mind you have to check four special characters as well so if you're using a non-standard character set then that can break your entire project as well same thing with using the Sharp key or the at key or the dollar sign key any of those symbols can also break your project so we're going to right click our character controller we're going to rename it and just say camera controller with no space and then we'll come in here and we will get rid of the space as well and now if we refresh our screen here and we're gonna need to reassign it so we'll just drag that up to our camera controller and then hopefully if we've done everything correctly if we hit play it won't crash on us it'll probably crash on us and it definitely didn't work so let's see what this is so it says substantiated class could not be Associated camera controller CS and let's take a look at the script see if there's something wrong with the script probably I thought I changed this but apparently I didn't so we'll do that and then we'll refresh it and hopefully it will work this time there we go and now we're basically back to where we were awesome so now we got to get it so that our actual Mouse can rotate our camera and that is where capturing your mouse and that is where the Godot event system comes in so inside of Godot we have this thing called the input event and basically it's a function that exists inside of the character controller that you can use to actually take your input events and then run code based off of it so in our case we're just going to come in here and say public override void input input event and what this is going to do is it's going to allow us to actually capture that event and what this does is it captures every event that happens on your project so you want to be really cautious with using these okay you should only use them when it's something that is not able to be done any other way so for instance every time you hit G or any key on your keyboard or anytime you move your mouse this function is going to run so you need to be super cautious about that now in our case we have to do this because we want to use our Mouse motion to control our camera but we need to know what our event is so we can't just be like hey move our camera based off of our event when we don't know if it's actually a mouse click event or if it's a mouse motion event or if it is a keyboard press we don't know so we need to check for that so we have to say if at event is input event Dot Mouse motion like that and if this is an event Mouse motion then we need to cast it as such because unfortunately uh c-sharp doesn't know that this event is a input event Mouse motion it just knows that it is an event and to pull back the things that we require we need to cast it so we'll say input event Mouse motion motion is equal to input event Mouse motion add event and then we can just take our motion and basically set our rotation now inside a C sharp it's a bit more finicky than doing it in other languages like GD script we actually have to set our rotation as one solid thing we can't just say rotation dot Y is equal to this we actually need to um set up our stuff so that it is one giant equals if that makes sense we have to say rotation is equal to and we'll have to say new Vector 3 and we'll need to pass in some stuff so what we'll do is we'll first pull out our x and x rotation is actually important if we take a look at our character controller here and we look at our camera and we look at these little lines here okay X rotation actually is up and down so if we look and we do this you'll see that it rotates the camera you really can't see it because Godot likes to use pink and pink is awful for this and my compression is probably not helping but if we rotate it on X on the red axis you can see that our camera goes up and down if we rotate our camera on the y-axis you'll see that our camera rotates around the character and if we rotate on the z-axis you'll see that our camera kind of can't to the side if that makes sense so we don't really want to rotate on the z-axis we want to rotate on the Y and the x-axis and you'll notice that if we move our Mouse side to side on the x-axis we'll want to move on the y-axis and if we move up and down on the y-axis of our screen then we need to do it on the x-axis so that's something to keep in mind so if we head over here and we take a look at this to do our x-axis so to go up and down that means we have to pull our event relative y so we can say rotation dot x minus motion dot relative dot y divided by one thousand multiplied by our sensitivity now you'll notice that this wasn't here before and that's because I'm just realizing during the recording that this already existed but basically I put a sensitivity value up here now the reason why I did that is because it's going to allow us to access this on the inside of the Godot editor so make sure we add this guy up here and we'll be good to go I forgot to delete that when I was doing my second pass at recording this part so my apologies and then we need to rotate on our y axis and I'm going to hit enter so that way it just looks a little bit better and when we do our rotation on our y-axis we need to do this our relative X so we'll say rotation dot y minus our motion dot relative dot y divided by a thousand multiplied by sensitivity and we should be good to go and then we can just drop in a zero right here on Z because we don't want to rotate our can't at all now I know what you might be asking why are we using a thousand well a thousand is just a good value that translates from 2D to 3D space if that makes sense so technically speaking it could be a hundred it could be whatever you want but I found that dividing it by a thousand gives us a good one-to-one ratio in terms of movement so if we hit Ctrl s and we go back to our project here and we hit play if we move our Mouse well it kind of works but not really so what in the world's going on well if we head back here and we take a look at it you'll see that our rotation x minus our relative y for our x value that's correct our rotation y minus our relative y we need to change that to relative X and let's try that and see if that works and there we go awesome so now you'll see if we go up you'll see we can get past our camera's rotation like that and you'll also notice that we can go into the floor and that's a pretty big problem so we need to do something called clamping and clamping allows us to clamp our camera in between two values we only really want to clamp the top and the bottom of our camera not the left and right so let's do that real quick so if we head back to our script here and we'll want to clamp it on our X rotation right because we have our X Y and Z and since we're moving up and down that is the X rotation I know that's kind of confusing still but that's just how it is so we'll come in here and we'll say math dot clamp and we'll clamp this value here on two values so we'll just put in parentheses right here we'll hit comma and then we have two values that we want to clamp this guy by in our case we're going to go minus one comma point two five F and those are just values that with my testing works so I'm going to go with those of course if you guys want to mess around with it you're more than welcome to so now I know I get a lot of questions about the difference between math and math f so what's the difference between math and math F so math is an integer math and math f is float math so if you're doing something that requires 1.25 you want to use math F if you want something that's going to go one two three four then you want math so that's the difference between the two generally speaking math is faster than math F but you lose the capability of using floats so that's something to keep in mind I'm going to hit Ctrl s and then we're going to go ahead and test this so let's hit refresh and you'll see if I go up it now stops me from going any further so if I go up it stops if I go down it stops right about here now we could go a little bit lower than um I believe I did 0.25 F we could probably go a little bit lower than that if we want to because looking at this you can see that we get to about here ish so you could go a little bit lower if you wanted to give the character the ability to look up further but that's up to you guys you can set this to something like maybe 0.5 F and that would give you just a little bit more space so if we hit play we come down you'll see that that gave us just a little bit more space so that's up to you guys on what you guys want to do but there you go now something else that we got to check out is we can actually move our mouse outside of our screen do that and that's a really big problem because it basically makes it so that we can't control our character without coming over here and then kind of coming around our screen and then continuing around like that to do a full 360 on our character so how do we fix that well if we go back to our code here we go up to our ready which runs whenever our node enters our scene we can basically update our Mouse mode and our Mouse mode is like how our Mouse presents itself within our game we could just come in here and say input dot mouse mode is equal to input dot mouse mode enum and we can set that to captured and that's going to capture our Mouse so if we come over to our project and we refresh you'll see that now my mouse has been captured so now no matter how many times I move it around or I rotate it around it doesn't leave our screen and we can hit alt f4 to close our game now something else I'm going to do real quick because I'm going to make it so we can actually see what we're doing so I'm going to click on these three dots up here I'm going to add a sun and I'm going to add an environment and that should allow us to actually see our scene there we go now once we have this we're actually getting there right we can move our character around and we can actually use our character but you'll notice that if we go up against this wall here and we rotate our camera we go into the wall what if we actually want it so that our camera kind of Zooms in to our character right if you've ever seen character controllers a lot of times that's what they do is they don't intersect into the wall they kind of Bounce forward into the character if that makes sense so how we do that is by using what's called a spring arm it's an actual feature that the Godot developers have implemented that makes our life way easier so if we right click our camera controller we add in a child node and we add in a spring arm 3D and we just put our camera onto our spring arm that will basically take care of it for us now we're going to need to take our camera we're going to need to zero it out so let's zero and then let's zero our rotation out as well and that way our spring arm is now actually taking control of our camera so if we hit play you'll see that we now are zoomed in on our character's feet now obviously this is way too close for our comfort right we can't we can't really use this like this right but what we can do is we can actually increase the distance that our spring is located you can see we're about one meter away we could change it to something like five and you'll notice that now we're about five meters away and when we go up against the wall it zooms in on our character which is awesome that's exactly what we want but you'll notice that now we are not looking at our character we're looking at our character's feet we're actually zoomed in on our character's feet and if you guys want that feature that's great but generally speaking you want to look at your characters back right you want to look at where our character's head or our shoulders are located so how can we do that well we can set up what's called a look at and look at our character's shoulders but to do that we're going to need some kind of reference so let's head over to our player and let's right click our character controller and add a child node and let's add in a node 3D like that and then we'll take this node 3D and we'll just drag this guy up to the center of our character's neck right about there we'll rename this as look at like so and then all we have to do is tell our camera to actually look at that location we can come into our camera controller right here and we can go into our process node right here and we need to get a reference to our camera so we'll say get node camera 3D quote and we got to get a node path now in our case it's actually pretty simple it's just spring arm camera 3D so we'll type spring arm I believe up spring arm 3D we want to make sure we get that correct camera 3D like that and then we can say dot look at and we'll pass it something to look at now we don't want to look at obviously our Global position we want to look at our players look at position so we'll say get tree dot get nodes in group 0 as character so we'll say character dot get node and we're going to say node 3D as type quote look at and then we'll just pass in our DOT Global position like that and there we go simple enough now something that we should do is we should pull this guy out because having a get tree dot get nodes in group and pull back our first reference doing that a lot is really slow and a lot of times in code you want to make sure you just pull a reference and hold on to it instead of pulling a reference every single frame so let's grab this guy let's copy it let's put it up here like so let's get rid of character like that and let's get rid of this guy like that and then let's just come up here and say character character like that and that's going to basically allow us to keep that reference in memory so we're not doing it every single frame we only have to do it once and then we're good to go now we can just hit Ctrl s hit refresh and hopefully it will work for us and there you go now we are focused on our character and our character's shoulders now you'll see that if I come down like this we actually are going through the floor once again so we'll probably need to come in here and make a quick adjustment to our clamp here so we'll just put it at 0.25 and see if that works because it's probably my fault why it's doing that and Godot just crashed again so something that I've noticed is this is the third or fourth time Godot has crashed randomly within the um c-sharp version of it I'm not sure if this is a bug inside of Godot but it definitely makes things difficult when you're trying to do stuff and unfortunately I don't get any error messages or anything it's just a pop-up that's blank so I will be right back all right so now that godot's back up and running let's take a look at our stuff here so basically we have it so that our character can actually go forward backwards side to side and you can move the camera around so you can see forward backwards side to side which actually we should probably rotate our character 90 degrees so that it you know matches with what we have but you'll notice that if we move our camera our controls still are rotated incorrectly our controls are not actually moving with the camera location so how do we solve that well to do that we need to come in to our character and make it so that our character can actually face the direction our camera is facing so the easiest way to do that is actually to do a look at and you could do some fancy math and things like that to make it so that your camera basically when it's out here you could say okay do the opposite of that so somewhere over here and then get like the negative values but that's a lot of work and it's a lot easier to just right click on your camera controller add in a child node and add in a node 3D and then just add a look at much like we did for our camera so if we just place this out in space like this and name this look at like that then we can actually use that to fetch our Lookout location now the way we're going to do that is we're going to come into our camera controller we're going to go into our node and we're going to grab our group much like we did with our character here we need to have some kind of universal method to fetch that camera location so we'll come in here and we'll just type camera controller like that and I'm going to copy that so that way I have it and then we can come into our character here and we can basically just look at where our camera is facing so if we come in here we can just type look at get tree dot get nodes in group paste that camera controller fetch back that first element Dot and you'll see when we do a dot it doesn't actually come up with anything right now we could do this one of two ways we could get a reference to the object like so and just say camera controller camera controller and make that equal to get tree that as a camera controller and then we could come in here and just say look at camera controller dot get node like this node 3D and fetch our look at like that dot global position like that and we could do it this way or we could just wrap this guy in parentheses and then just basically say camera controller and then we could code from there and pull back our node it's up to you guys and which one you guys want to do but right now I will use this so we hit Ctrl s we come back here and we refresh you'll see that our character is now facing our camera now that's just because we need to flip our character but if we hit W you'll see we're going forward a we're going left and right and we can actually walk around as if our camera is dictating where our character goes so that's awesome right so kind of what if we want it so that we are able to Pivot around our character and what if we want it so that we don't can't look up and down and have our character actually look up and down because we don't want our character actually look up and down when we're moving our camera because that's going to cause some issues right especially if we do something like jumping or something like that it could cause problems so how do we fix that well if we head back to our character here when we're fetching our look at we're just grabbing our Global position here and what we should do is we should just do the x and z values because we don't need to do the Y values I don't care which direction the character looks up and down I only care where the character looks left and right if that makes sense so we can come in here and just say Vector 3 look at is equal to and we can just grab this bit of code here copy it paste semicolon and then we can just come in here and say new Vector 3 pass in look at dot X comma globalposition dot y comma look at dot Z and that'll basically allow us to control our characters look at so they don't look up and down they only look left and right and that's it now the reason why we want to use our Global position is because our Global position is always going to be the correct position if that makes sense to where our look at would be so that's just something to keep in mind now if we hit Ctrl s and we test this real quick you'll see when we look up and down our character no longer looks up and down they just look straight ahead which is perfect now let's solve the issue where our character is not looking in the correct direction and let's solve the issue where what if I'm not moving and I don't want my character to rotate with me what if I want to look around my scene and not have my character follow my exact movements well to get our character to rotate correctly if we go into our character scene we can grab our Armature and just flip it 90 degrees like so and we're good to go and we'll hit Ctrl s and for our character to do kind of that nice rotation thing where it's only when we're moving if we grab this guy here we hit Ctrl X we come down here and we say if direction does not equal zero then look at this location and there we go but what this is going to do is it's going to make it so that our character snaps into position and we don't want that necessarily what if we want our position to be kind of like a lazy rotation kind of like if I told you to look in a direction you're not just going to quickly snap into position you will slowly turn your head and look at that position so the best way to do that is with what's called lurping and lurping allows you to lerp between two values now the easiest way to do that is to get your characters last look at position then lerp between the last Lookout position and the direction we want to go and then set our last look at Direction equal to our lerp Direction so that's pretty simple to say but how do we actually do that well if we come up here and we set up a vector three and we'll call it last look at Direction and we'll make that equal to a new Vector 3 like so and then if we come down here we can just say Vector 3 lerp direction is equal to we could type lerp but you'll see that nothing happens it doesn't actually exist we could go godot.lurp but that also doesn't exist so where do we find lerp from well we find it with math F dot lerp just like that math F dot lerp is where we would fetch that instead of fetching it just from the Godot code base we can actually just pull it from our math F libraries and now we have a from a 2 and a weight so our from is our last look at Direction our two is our look at Direction which would be this new Vector 3 right here so we'll copy that guy and then our weight is how much we want to do it by so that's going to be Point O F like that and you'll notice well hold on a minute that didn't work cannot convert Godot Vector 3 to a float and that's where C sharp and Godot separate quite heavily C sharp expects for you to have that knowledge that you're going to need to break apart your vector math into three separate maths and then return that value whereas Godot will just do that for you so for us to do this and for us to do this efficiently we're going to create a helper function that will do it for us we'll come down here and we will add in a function so we'll say private Vector 3 lerp Vector 3 and we'll pass in a vector three value to lerp like that and then I'm going to do what's called a short-handed function so I'm going to hit equals pointer new Vector 3 like this and then we're going to lerp those values so we'll say right here we'll say math F Dot lerp and we'll take our from which will be our value to lerp dot X and then we need to give it some kind of value to lerp too so we should have another one Vector 3 value 2 lerp to and we'll pass that in here so value to Alert 2 dot X or comma and then we need a weight so we should probably pass that in as well like that and we'll pass in our weight just like that and then we'll do a comma and then we need to do the exact same thing again so we can grab this guy pass it in and then do one more comma pass this guy in we'll say Z Y and Y just like that and now we can just come up here and say math F Dot lerp and instead of doing that we can just say lerp Vector 3 pass in our two which would be our last look at Direction comma our look at comma and then our weight which in our case is going to be something like 0.05 F now something that I made a mistake on is our last Lookout direction is up here and it actually should be all the way up at the top we don't want it inside of this function so we'll just go ahead and grab this guy Ctrl X we'll come up here and paste it in like that and that should allow us to use it so once we have our lerp Direction here we can basically say okay we're good we can look at our lerp Direction like that and then we can set our last look at direction is equal to our lerp Direction and hopefully that should do it for us so now if we've done everything correctly we can come back here we can refresh and let's see what it does well it failed to build so that's never a good sign so let's see we need a semicolon so I forgot to do a semicolon right here so we'll do that and hopefully if we hit play it will build there we go and we have a failure because I need to be on my node 3D so we'll hit play and you can see our character is not rotated to our camera and then when we hit forward now our character rotates to our location but you'll notice that for some reason our character rotates to kind of follow our Mouse location and I thought we fixed that right well here's the reason why so if we take a look at our values here we are lurping our y value from a value to another value and if we take a look at what we're passing in we're passing in our last look at Direction which should be a vector 3 0 which is generally fine but it's probably not if we look at our look at we're passing in our Global position so this isn't going to work because we're just passing in our actual Global position where we're going to and since we need to set our globalposition.y equal to our player position so we can fix that rotation issue we have to do that somewhere so we'll do that right here so we'll say look at is equal to look at new Vector 3 look at dot X comma Global position dot y comma look at dot Z and there we go and hopefully that will work for us so let's come back here let's refresh and you'll see that that fixes our problem you'll also notice that our character doesn't just snap into where our camera is located they kind of gradually slide into that location and that's basically how we'll solve that now something you may have noticed is your character is rotating quite a bit when you turn left to right and the reason why that is is because your Lookout position is probably too close so if we pull this really far out that'll help mitigate that issue you can see here now the character doesn't rotate very much at all and it basically solves our problem now if we wanted to we could make it so that you know we want our character only rotate for instance when we click another button all you really have to do is just basically pull this look at section here and basically just put that underneath wherever you want your character to actually when you want your character actually look at a specific position so that's something that you could do at this point we basically have everything we need we have the ability to move our character jump and move our camera so if this is basically what you are looking for congratulations we're basically done at this point but how would you add movement well basically to add animations we have to go into our player controller here and we can come down here and take a look at our animations now you can see we have a bunch of really cool animations right here right now we could call them out inside of our code but that can get really difficult and that is where the animation tree comes in it simplifies calling all of your animations to a singular area and you could use parameters to basically determine which animation you want to be in so how do we use an animation tree well if we come up to our character we right click add in a child node and we add in a animation tree node like this you'll see if we go to our inspector we have what's called a tree root right here if we click on that we have a bunch of options here now I'm not going to go in in depth on each option but I will go through two of them the two that we'll be going through is the blend space 2D and the node State machine now I'm going to click on the Node State machine because that's the one we're going to use first and then we'll use the blend Tree in one moment once we have selected our node State machine we need to select an animation player right you can see it says animation tree is inactive activate enable playback and check node for warnings and you'll see if you see a warning here it says path to animation tree node containing animations is not set and the reason why that has to exist is because we need to play our animations through some kind of Animation player animation tree just basically tells animation player what to play and when not exactly how to play animations so to hook up our animation tree we can come over to anim player and click assign and we can assign our animation player and we'll hit OK now once we have that we're ready to go we can actually start using our actual animation tree so the easiest way to use your animation Tree in my opinion is the actual animation State machine here now the easiest way to do a lot of things is using the state machine if we right click add animation you can see we have a bunch of animations right here now I'm not going to go into a super detail about how to do everything inside of here because there's so much in here it's kind of crazy so what we'll do is we'll just drop in idle and if you click up here on the connect nodes button and you drag this guy to here and you let go and then if you click on this guy here you should see your player start to play the animation now if it doesn't then you have to click on your animation tree and turn it to active and you'll see that your player is now playing that animation now if you want your character to play for instance a walk animation you can do a transition into that walk animation you can click and drag and then let go add animation walk and then click and you'll see that the character is now playing the walk animation now you'll notice that the character stopped playing the walk animation once it completed now why is that and the reason why is because if we go to our animation player and we go to our walk animation you'll see over here on the right there is a animation looping button you click that now your character will Loop that animation forever now that means we should also do that for something like falling idle we should turn that on we should do the same thing for strafe left and strafe right and we should probably do that for idle as well so we'll turn that one on for that and then we'll go back to our animation tree and you'll see that we can go from idle to walk but we can't go from walk to idle because there's no link back to walk so if we click and drag this guy down and let go you'll see our character is now freaking out so what happened well our transition is happening instantly if we click on this thing right here this little transition you can see we have this thing called switch we can change our switch mode so you can see if we change this to end you'll see we'll do our idle animation and then when it finishes it's going to go into our walk animation if we change this transition as well to end it's going to do the same thing now in our case we don't really care about this right so you'll see once this finishes it's going to do the walk animation and it'll switch back immediately now that's great and all but that's not really what we want we want it to switch immediately right we want for our player to be able to stop idling and walk immediately so what can we do to make it so that it doesn't go crazy like that because if we switch it back to immediately like so and we switch it back to immediately you'll see that they freak out well that is where Advanced comes in so you can see that there's Advanced and you have this thing called a condition and if you type in this condition moving you'll see that now we are not going into our walk cycle and if we click on this transition and we change it to idle like that you will see that if we go into our walk cycle so if we click on this little button here and we do a transition you'll see that we're not going into our idle cycle however if we click on our animation tree and we go over to parameters conditions you'll see we have idle and moving so if we click the check box right here now we are in our idle we click on our moving checkbox now we are moving easy enough and you'll see if we uncheck moving we're still moving and that's something to keep in mind so this is cool but how do we hook this guy up well this is actually pretty simple if we go into our code here and we come up to the top and we add in a reference to our animation tree so we'll say animation tree tree like that and then we'll come in here and say public override void underscore ready and then we'll say tree is equal to get node and we'll pass animation tree and we're gonna get back our animation tree so it should just be as easy as grabbing this pasting it and then there we go and now once we're in here we'll come down to the bottom here which is where I usually like to do my animation switching logic and we'll say animationtree dot tree dot set and we'll need to set a name of a property and the variant and this is where things are going to get difficult so if we hit quote we don't have any intellisense so we're going to need to know exactly what we're doing so if we come over here and we click on our animation tree we hover over idle you'll see it's parameters slash conditions slash idle so what are our conditions for idle well if a character is idling they're usually on the ground and they're usually not moving right that's an easy way to determine if you are in idle state so we'll come over here we'll put a parenthesis like so we'll say is on floor comma and if you look up here we have a section here where we're getting our input direction if we have an input direction we know that we're moving right we cannot move without an input Direction so we'll say and input dur is equal to Vector 2 Dot zero and there we go so how do we know if we're moving we'll see exact same thing right we are on floor and our input direction does not equal zero right because we know if our input direction does not equal zero we must be moving somewhere and then we can just come in here and update this to say I believe our parameter is moving so we'll say moving like that we'll hit Ctrl s and then we'll hit play and now if we hit W our character walks if we let go our character stops walking there we go easy enough so now what if we want to handle jumping so you can see when we jump our character doesn't actually do a jump animation well that's pretty easy if we head back to our animation tree here and we draw out a line from our idle and we let go we can add in an animation called Falling idle and that's basically our character falling right and when your character Falls they need to be able to land so we're going to drag this down add in animation fall land and then when they land they can go back to their idle State now you're gonna see they're gonna freak out again so let's come in here add in a condition called it falling and then since we don't want to transition immediately from Fall idle let's come in here and just say landed like that now something to keep in mind and I'll show you guys this if we come in here and we scroll down and we duplicate these parameters and we have one for falling like so and we have one for land did I believe is what we called it let me check real quick falling and landed so if it's falling we know that if we're following it's not on floor so we know that that's true right there if we are landed that means that we are in fact on the floor now something to keep in mind about State machines is it doesn't matter if landed is true if we're in our idle state or for walking right because if we do this there are no transitions from idle to fall land so falling or so landed can be true and it's not going to cause any issues so that's something to keep in mind so once we have this if we hit Ctrl s and we refresh you'll see once we jump our character does our animation what you'll notice that they immediately basically like pop almost into their land but we don't want that right we want our character when they fall and land we want them to actually land and play that land animation right so how can we do that well if we go into our animation tree we can come into this transition go to Advanced and change go into switch and change it to at end and then we can hit refresh and you'll see our character lands and there you go now there's a little pop there I don't know if you've seen it when you jump and you land there's kind of like a little secondary pop there and that's because of the animation choice I chose so don't worry if you choose a different animation it will be better or if you just want to get rid of that fall land animation that will also solve your guys's issue but in my case it's fine for the tutorial but that's just something to keep in mind now something else that you'll notice is if we walk and we jump you'll see that our character does not go to idle state or does not go to jump State you'll see that now why is that that's because walk does not link to fall Idol at all so it's not going to work so we can just kind of drag this guy here like so and then we can click on this guy and say falling and when we're Landing we also can go from idle to walk or we can also go from Fall land to walk right so we can just drag this guy like that and there we go we could just say if we are moving like so so now we can jump and do fall idle and we can land and we can walk and we can idle and we can fall idle easy enough right so if we refresh this guy we come in here and we're moving around and we jump you can see now we can do our jump we land and we're idle our character does their land animation when they jump and they land they don't do a land animation because we don't want it to do that that full land animation now something you'll notice is if we're moving around you can see that our character kind of snaps into position and if we jump and we're moving you can see how it's even worse right it just just kind of does this big snap here and that's where transitions come in so if we come into our animation tree right here we select our fall land let's say and we come over here and we select our transition and we come over here we look at our what's called X fade time x fade time will actually fade animations together so if we set it to something like 0.2 which is kind of like my go-to for animations if you set it to 0.2 that'll give you a good solid transition if that makes sense so now basically what I'm going to do is I'm going to run through all of these guys and I'm going to transition them to 0.2 and now I'm going to hit refresh and you'll see if I move my character doesn't quite snap into the walk animation you kind of smoothly guides into the animation if I hit space you'll see that when I go into my walk my character kind of instead of straight up snapping into the position the character kind of Glides into that position it makes it a little bit smoother a little bit easier to work with if that makes sense and at this point basically you have the basic understanding of how to set up your animations so now that we kind of grasp the basics of a state machine let's talk about how we could do something a little bit more advanced let's talk about how we can do a blend space 2D so if we head back here when you're doing something that requires multiple transitions or that have things that kind of transition almost like a chord a coordinate based transition that's when you want to use a blend space transition system so if we come up here and we right click and we add in a blend space to D and we grab this guy and we transition to it and we add in an advanced transition and we say moving and then we transition back down to this guy whenever it's idle and then we'll transition to this guy when he's falling we'll come in here falling and we'll grab these guys and set them to point two much like we were doing with our walk and then we just delete our walk like that let's head into this and take a look at some of the options here so if we click on this little pencil that will let us go into it but before we do that let me give you guys a quick basically brief on how cool this is so something that's really cool is how you can actually do SUB animation trees in here so you could do a sub blend tree or a blend space or a state machine you can actually have state machines inside of State machines that are controlled by other animations that basically control blend spaces so you can get really in depth and you can get as far down in this root path as you want and you can actually build really complex animations with this system and I'm just kind of scratching the surface with how all of this works so there's gonna have to be a whole dedicated tutorial series or just tutorial on this something I've been investigating is how I could use this to execute code I think it'd be cool to make some finite State machines with this but that's something for me to kind of research and pay attention to but to get into a sub node basically is by clicking on this little pencil here so if we click on it you'll see that we are now in a blend space 2D so the way a blend space 2D works is by basically taking this guy and moving it around and based off of wherever it's located it will blend between your animations so what does that mean for you well if you come over here to the pencil and you click right here and you added an animation and you add in the strafe left animation and you come over here you click add animation strafe right and then you come up here and you click and you add animation walk you'll see suddenly you have a triangle then if you click down here add animation walk like that you'll have a full Triangle Well it's more of like a trapezoid I think and if you click and you drag this guy over to the right well if we're in the correct state so let's go into our root let's click on our blend shape there we go so now it's going to play that animation you click on the pencil and we move this guy to the front you'll see that now we're walking forward moving this guy to the left now we're walking left and move this guy down and we're once again walking forward now obviously we don't want to walk forward for this one so what if we click on this guy we come over here and we change it to play mode backwards now our character is doing a backwards walk now we can walk forwards and backwards left and right easy enough now something to keep in mind about this is it since it goes off of coordinates you're gonna have to be cautious with how we do our movement inside of the code since this works off of values we're going to need to lurp our values to get a nice smooth transition so I'll show you guys how to do that but first let's make this part work so if we come in here and we come down here and we actually go into our animation tree you'll see that if we hover over this you'll see we have properties parameters and you can't quite see it on your guys's end but it's blend space 2D blend underscore position so if we come in here we can basically duplicate this guy and we could say conditions I believe it's under blend space 2D so slash conditions slash blend underscore position like that and then we can just set it as our input direct Direction like so and that should hopefully just work for us so basically what it's going to do is if we go into idle it will jump out of this blend space 2D if we go into moving it will go into this blend space 2D and if we're falling it'll automatically drop out of this blend space So in theory if we hit play this should work so you'll see if I hit W the character walks forward if I hit a well not much happens our character is not doing what I expected which is about par for the course for this so let's take a look at what's going on so if we look at our code we are putting in our input direction oh I think I know what's going on so when we did our parameters blend space 2D if we hover over this and I'm not sure if you guys can see it but it says properties parameters blend space 2D blend position we have conditions blend position so if we get rid of that and we hit Ctrl s and then we refresh let's take a look at it we hit W or uh front Arrow back arrow left or right left like that and there we go cool I think that'll work though I do think I'm getting some kind of backwards motion I think I have my uh forward and backward reverse I think input dur might be putting ourselves in a backward or forward uh reverse here for some reason so we might need to just grab our Direction instead so let's try Direction so we'll do this we'll say new Vector two this we'll say Direction dot X comma Direction dot Z because we don't want to pull our Direction dot y because if we pull Direction dot y that's that's our up and down value not our front to back so we want x and z and then if we refresh this let's see if that fixes our problem and if not we'll have to do some inverting stuff no I think it's still backwards but let's see what's going on here so we go to our animation tree and let's grab this guy let's select this point and let's drag this guy down let's select this point drag this guy up and that'll basically flip our positions and if you want you can always just kind of drag these guys like so if it goes outside of the bounds what'll happen is that if we put this at one you'll see it still does the proper animation so that's just something to keep in mind so now if we refresh this since we flipped these that should solve our problem so if we hit w no it's still now everything's backwards that's interesting so that's not ideal I'm curious what's going on here there we go that's better I just had to go back to input Direction and that solved my problem so there you go so now your character is doing proper animations like you would expect if they were walking like that awesome cool all right so now what if we wanted to lurp between these values well basically we can do the same thing that we did down here with a lerp vector three but instead we could do a lerp vector two right or we can basically just kind of cheat it a little bit and basically just do a math F lerp our input Direction so what we'll do is we'll come down here and we'll say last input Direction is equal to input dur and then we'll just copy this guy we'll come up here and we'll save Vector 2 last input der and we'll make this equal to a new Vector two so we'll just do new we'll scroll down here we'll just say new Vector 2 math F Dot lerp and then we'll take our from which will be our last input Direction comma 2 and we'll pass in our input Direction and we'll need to pass in a weight so we'll do something like a let me see what did we do earlier .05 so let's do a point zero five F and then basically let's do the same thing for our other Vector now we're going to need to pass in a X and Y value so we'll just say dot X like that and we'll also do that here so dot X and then we will grab this guy copy it comma paste close that parentheses off do dot Y and Dot Y and hopefully that will work for us so if you hit Ctrl s we hit play we have a failure so it says that we are missing a parentheses here it says parentheses except expected so we'll add an additional one real quick and then we will hit play and let's see what happens so left up and you'll see that it's a lot more smooth it's not super smooth so if we set this to something like maybe 0.15 perhaps if that'll give us a better value here let's see if that'll give us a better more reasonable value there we go and that'll smooth out our movement just a tiny bit awesome and that's basically how you can build a 3D character controller with animations using a state machine and a blend space 2D and something I just noticed is that we're going to need to drag this guy up here and add in the advanced moving there we go and that'll solve that problem but if you like this video go ahead and hit that like button hey you know if you dislike that video go ahead hit that dislike button because I'm here to make content for you guys this video is a viewer suggested video so hey you know if you have any suggestions throw them in the comments below because that's pretty much how I do all of my content and what's next on my list is I'm going to be recording my item investigation system for my horror game so look forward to that and hopefully we'll get this um horror game moving a bit quicker with some level design stuff and maybe some sound asset creation as well so look forward to that and hey if you have any questions or comments please leave them in the comments below or hit me up on Discord link is in the description and I'll be more than happy to help you out with any issues you might have but that is all I have for you guys today so thank you so much again for watching and I will see you all next time thanks thank you
Info
Channel: FinePointCGI
Views: 7,363
Rating: undefined out of 5
Keywords: making a game in godot, character controller, c# godot | creating a celeste like character movement system, third person character controller with animation, godot, 3rd person controller godot, godot character controller, godot engine, godot game engine, third person character controller in godot, creating games in affinity designer, intro to 3d in godot, can you make a game in godot engine without programming, game development, gamedev
Id: 0qv2va2BPgo
Channel Id: undefined
Length: 66min 23sec (3983 seconds)
Published: Mon Mar 06 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.