Third Person Character Controller in Godot 3.2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Pretty good!

You said super smooth but there was no smoothing/delay of the camera (especially for jumping this is nice to have).

Also a good follow-up video would be a state machine for the player based on this.

👍︎︎ 6 👤︎︎ u/G-Brain 📅︎︎ May 18 2020 🗫︎ replies
Captions
what's going on guys Tom here and in today's video I'm gonna be teaching you how to create a super smooth third person controller in the god engine so let's get started okay so as always the first thing we're gonna do is open up our go-to engine I'm gonna create a project here I'm just gonna call it third person control we're gonna create the folder and press create an edit okay so we're gonna click on 3d C I'm just gonna rename this as always to world and I'm gonna start by saving that scene there so let's create a folder for this let's call it Seaton's we're just gonna save it as willed and we're just gonna hit play so that we can define our main scene world hit play and then let's close that out okay so what we're gonna do next is we're going to create the player and to do that I'm gonna click on the tab up top here this add new scene button I'm going to choose 3d scene and we're going to call it play out I'm going to right click on the player I'm going to click change type and I'm going to change it to a kinematic body and as always you'll get this yellow triangle telling you that you need to add a collision shape so we're gonna do that but first thing we're gonna do is we're actually going to add a mesh instance and you'll probably recognize what we're doing here we're creating a new capsule mesh over on the right hand side trusty old capsule mesh we're going to come down to transform and rotate it 90 degrees on the x-axis over on the left again right click on player add child mode and now we're going to add our collision shape and on the right hand side where it says shape we're just going to click on that there and choose capsule shape and we're just going to set its transform to 90 on the X to match our mesh instance ok so the next thing we're gonna do is we're gonna add the camera for our third-person controller now to do that I'm going to right click on the player and add a child node and I'm actually going to add just a spatial node here and you'll see why in a little while I'll double click on that and I'm gonna rename it to camera pivot we're gonna drag this up to the top of our scene here and right click on the camera pivot add a new child to this and now what you want to find is a spring arm and you'll see here at the bottom it says a helper node mostly used in third-person cameras we're going to click create now what the spring arm does is it allows our camera to sort of sit like it says on an actual spring arm which means that when it collides with like a surface or a wall it's actually gonna push the camera further towards the player so that the camera doesn't get locked behind the wall and it gives us a really nice effect and you'll see what I mean a little bit later on when I show you how it works in practice but for now we're just gonna right click on the spring arm and we're going to add a new child node to that and now finally we're going to add our camera we're going to come back up to the spring arm here and on the right hand side you'll see that we have this spring length and we're going to set that to about five next thing we're going to do is we're going to move it up on the y-axis by about 1.5 units and you'll see here that what that's done is it sort of pushed it up to where the top of the players body would be and you'll see as well in the 3d editor this sort of line here now that indicates the length of our spring arm so if I change the length of this to say 10 you'll see that that gets longer and what that actually means is that the camera element itself here which you can see is right above the player it's gonna try and push that as far back as it can until it collides with something now hopefully you can see my mouse moving here but if for example there was a wall here that's gonna mean that the camera would get pushed back to here it wouldn't go all the way back it would come right up to here which means that we're not gonna get any clipping with walls and such so we're gonna change that back to five because I think that's just a quite a nice value there and what I quickly like to do is I just like to rename this spring arm just to camera boom just so that it makes a little bit more sense so let's save that and we're gonna go up a directory we're gonna create a new folder and we're gonna call it player and I'm going to save this as the class okay so now it's time for us to start writing our actual third-person controller script so we're going to come up to the player right click attach a script we're going to save it as player Gd and I'm going to remove all of this here and we're going to start off by declaring some variables so we're going to say export VAR speed we want this to be a float I'm going to set it to about 20 we're gonna have an acceleration again this is a float for now we're going to set this to 15 we're going to have a another variable here called air acceleration again this is a float and we're going to set that to 5 we're gonna have another variable gravity again and we're going to set this to not 0.98 which is roughly real-life gravity another one here is max terminal and velocity and this is going to determine how fast the player can fall at max speed again this is a float and we're going to define that as 54 which is roughly terminal velocity for an actual human another one jump power again float and we're going to set that to 20 so all of those variables are specific to the actual movement of the player so it's ability to run and jump and fall we're going to define some variables now which will also allow us to manipulate how our camera works and for those I'm going to say exports and we're going to put brackets here now what this is going to do is it's going to allow us to define some hints for the inspector window so that we have a bit of a nicer at editing experience within the expect on the right-hand side and you'll see how that works in a little while so for this we're going to say that we want this to be a float and we want it to have values between North Point 1 and 1 and this is going to be a VAR mouse sensitivity it's a float and we're going to default it to North Point 3 we're going to define another one here again we want to hint the inspector that it's a float we want it to start at negative 90 and end at 0 and this is going to be var min pitch so how much the camera can pitch up and down this is going to define the lower limit of that so this is a float we're going to say we're going to default it to negative 90 and we're going to do the upper range of that so again float this is going to start at 0 and at ninety I'm just gonna call this max pitch it's a float I'm gonna default it to ninety so we want basically a hundred and eighty degrees by default of pitch rotation however I thought it would be quite nice to add this in because actually I quite like to limit it to about eighty degrees either side it just means that you can't go fully vertical both directions and it just gives a little bit of a nicer experience in my opinion okay so a couple more variables we're gonna add in here are a velocity and this is gonna be a vector three so we want to keep track of what our current velocity is or all times so that we can modify it and another one here Y velocity and this is going to be a float now the reason I'm separating out velocity and Y velocity is because we want to make some tweaks to our actual height our Y velocity value based on things like gravity and whether or not we're currently jumping or if we're on the ground so it's just a little bit easier you can probably do it in a different way but it's a little bit easier in my opinion just to keep track of that Y velocity as a completely separate variable and that means when you're multiplying your direction velocity by things like Delta time and your current walking or running speed you're not modifying and messing about with that Y velocity there it just makes things a little bit easier okay and now what we're gonna do is are going to get some quick references to some elements within our player and to do that we're gonna say I'm ready camera pivot pivot and an unready camera equals camera pivot camera boom camera there is okay so that is a lot of variables let me just quickly run through each of them a lot of them are self-explanatory but let's just run through them again so we've got our speed that's just gonna define the speed that I carry to walks our acceleration is the rate at which our character reaches his maximum speed and then slows down again when the player lets go of the input keys our acceleration is 1 I've added in here I think it gives it a really nice feel when you're jumping in a third-person game to not have the same amount of control with regards to things like strafing and moving back and forward when you're in the air I don't feel like it feels realistic enough to be able to jump and then sort of strafe around just like you would when you're on the ground so I like to add air acceleration in here and reduce its speed a little bit so that gives you a little bit less control when you're in the air however I feel like it feels a bit nicer we've got our gravity which defines the rate per second that we're going to fall we've got our maximum terminal velocity and that is going to determine how fast we can fall at our top speed our jump power is just the power of which we jump and again these ones are pretty self-explanatory our mouth sensitivity for looking left right up and down and our minimum and maximum pitch that the camera can be at velocity and Y velocity are to keep track of our current speeds and these camera pivot and camera just give us a quick reference to some elements within the left hand side here within our players tree just so that we were asked to type these out every time we want to reference them okay so let's kick this off with a func ready and inside here the first thing we're going to do is we're going to capture the mouse so that the mouse disappears and it's locked to the window that means when you're moving the camera left and right the mouse isn't gonna go outside you're not going to click on things behind the window so to do that we're gonna type input dot set mouse mode open our brackets here and we're going to choose mouse mode captured okay and because we're capturing the mouse we also want a way to release the mouse so we're going to define our ready function I'm sorry our process function here and we're just gonna check every frame we're gonna scroll down all over here we're gonna say if input dot is action just pressed and we're gonna use the UI cancel method here and just hide this output windows will grab the more space so if we press the UI cancel button which defaults to the escape key then we're gonna release the mouse so we're going to save input set mouse mode and we're going to set that back to visible all right so now we've got our mouse being captured and released if we press the Escape key it's time to start handling the mouse move to do that we're going to use the input function so the input event function there and we're going to say if the event that we're getting past is an input event Mouse motion then what we're going to do is we're going to say the rotation degrees of this object so rotation degrees dot Y and we're going to subtract from this value what we're gonna subtract is our event got relative dot X so how much the X sorry how much the mouse has been moved on the x-axis we're going to multiply that by our mouse sensitivity and then to do our picture you'll see now why we've got the camera pivot we're actually going to use the camera pivot to do the pitch in width and again you'll if you've followed my first person tutorial you'll realize that you can run into a bit of an issue when you'll do rotation on the x and y axis in 3d way you can have gimbal lock or you can also have it just going completely out of whack when you try and rotate the same object on two different axes so we're separating this out with the player itself doing the horizontal axis and the sorry the y axis and the camera pivot is going to control our x axis rotation so for this we're gonna say camera pivots dot rotational degrees dot X so we're gonna rotate is on the x axis again we're going to subtract from that value and we're going to do event dot relative Y so depending on how far up and down you've moved the mouse that's going to control our pitch again like we did above we're going to multiply that by our mouse sensitivity and then we're going to clamp that value so that it sits in between our min and Max pitch so to do that we're gonna say camera pivots got rotation degrees dot x equals and then we're just gonna call the clamp function and we're gonna pass in our camera pivot top rotation degrees dot X I'm gonna give it our min pitch and our max pitch and that's going to clamp it to whatever we've passed in for those two values okay so we're going to save that what we going to do is we're just going to quickly jump back to the 3d view here and for our player we're going to come down to the collision tab here and we're going to actually change the layer that this player lives on now before we do that we're going to come to project settings here so project project settings and we're going to scroll down and under the layer names option on the left hand side we're going to choose 3d physics now I'm going to create some layers here I like to have layer one as all of the environment so things like walls and floors and basically collidable objects so for that I'm just gonna call it environment and then on layer 2 I'm gonna call it player so we want our player to be on a separate layer because the camera spring on we don't want that to actually interact with the player itself that's gonna cause some very weird issues with the camera so what we're gonna do is kind of close that and we're going to come over to our player here on the left hand side now we're gonna come over to the right hand side here and click on these two dots and if you don't see the layer names that we just provided before or you can do simply save this player seam close it and then reopen it again click on the player and if you come over to this on the right hand side now you'll see that they've actually loaded in I think it's a slight bobble glitch with the go to answer but it's a relatively quick fix so what we're gonna do is going to untick environment and we're going to choose player so we're going to come over to camera boom here and we're gonna look at the collision mask on the right hand side and we're gonna make sure that the only thing that this spring arm is concerned with colliding with is the environment we only want it to collide with things like walls we don't want it to collide with the actual player itself because that's going to cause issues with the camera so we're gonna save that and now what we're gonna do is we're going to come over to our weld you'll see that I've dragged in the player scene here and we're just gonna press play and we're just gonna test out our mouse controls so you'll see that we're able to go fully left and right and we can also look up and look down and we are limited to that 90 degree axis there so if I close this and on our player if we change this Max and min pitch to let's say negative 50 and 50 and we press play you'll see now that we're limited to a 50 degree pitch either side we can't go all the way up and all the down again and I just think that actually having something like negative 50 and 50 it's just a little bit nicer than being able to go fully underneath the character just sort of means that your camera doesn't end up colliding as much with things like the ground and anything that might be above the character but that's completely up to you how you want to do that okay so let's go back into our script and now what we're going to do is we're going to add in the code that's going to define the movement for our character so actually before we start jumping back into the script let's go back into our project settings and let's go up to our input map here and let's define some inputs so we're going to type move forward move backward move left and right and finally jump let's define these so let's click the plus button choose key forward W backwards s left it's going to be a write is going to be D and jump we're just going to choose the spacebar okay cool so now it's time to define our movement what we're going to do is we're going to say in font physics process we're going to call a function called handle movement I just like to separate out functions into these nice little chunks so that a little bit more descriptive and then we're going to define our handle movement function we're gonna give it our Delta okay so it's time for us to work out what direction the player wants to go in to do that we're going to define a variable bar direction and we're going to default it to a blank vector 3a now we're gonna have a series of if statements just like you'll have seen in the first person controller tutorial we're gonna have if input is action pressed I'm going to move forward if that's the case we're going to say Direction minus equals minus equals transform basis Z so that gives us the forward direction for this player we're going to add that to the direction vector or in this case we're going to negate it because negative z axis in Gowda is actually forward we're gonna have if input off is action press move backward going to do direction plus equals transform faces Z I'm not going to do here is you're actually just going to copy paste these in we're going to change that to move left and for this we're going to do minus equals transform basis dot X and move right we're going to plus equals transform basis dot X okay so once we've done that the final thing to do as always is we're going to normalize our vector so Direction equals Direction dot normalized and that means that if you're pressing the forward and left key at the same time so you've gone diagonally you're not going to be going faster than if you were just going forward or backwards or left or right so we're always going to normalize our vector to have a length of 1 and now this is where we're going to start doing our acceleration and actually trying to interpolate our current velocity so we're gonna get a variable here that defines how fast our acceleration is dependent on whether or not we're on the floor orbit in the air to do that we're going to save our I'm just going to call it excel equals so we're gonna say it's acceleration so this variable here 15 so we're gonna say it's gonna be acceleration if is on floor which is a function that you get in a kinematic body which this node inherits from so we're gonna say we want our acceleration to be the acceleration value if we're on the floor otherwise we want it to be our acceleration so if we're on the floor it's going to be 15 otherwise it's going to be 5 and now we're going to do velocity equals and we're gonna do some linear interpolation here so we're going to say velocity dot linear interpolate and we're going to give it the direction and speed that we would like to be going after is our direction multiplied by our speed and how fast are we going to accelerate towards that speed where we're going to accelerate towards that cell multiplied by Delta okay so now what we're gonna do is we're gonna add in our gravity to do that we're gonna say if is on floor so if we're currently on the floor we actually don't want to apply our full gravity because if we do that what's gonna happen is when we actually come off a platform eventually we will have been added in gravity over time and it's just gonna keep growing and growing and growing and growing and eventually once you do step off a platform it's gonna be at such a high value that you're just going to plummet instantly and we don't want that to happen however with a kinematic body if we don't apply gravity like this all the time we're gonna get some really strange issues with the is on floor function why I've noticed is especially with a capsule Collider every now and again it will report that you're on the floor and then sometimes it will report that you're not on the floor if you're not constantly applying some minor negative y-axis so what I'm gonna do here I don't know if this is a well-known thing or if people normally do this but it seems to work for me what I'm gonna do is I'm gonna say that our Y velocity it's actually going to be equal to negative naught point naught 1 now that just applies a very very minor amount of downward force to the player when they're on the floor and I feel like that just sort of pins them to the floor and that seems to fix any issues that you get with is on the floor now you can also I've heard used the moving slide with snap function however I've found some issues with that as well so I just like to brute force it really and just say look if you're on the floor apply a very minor amount of downward force to make sure that you're pinned to that floor sorry that was a really long run but basically we're gonna say if you're on the floor apply a very minor minor amount of downward force otherwise we want to apply our full gravity force so to do that we're going to say Y velocity equals and we're actually going to clamp this value so we're going to clamp it to our current Y velocity minus our gravity force and we're going to clamp it to between negative Matt terminal velocity and positive max terminal velocity what that's going to do is it's going to apply a gravity force over time but it's gonna limit it so that you can only ever go at that maximum terminal velocity which we defined here as 54 units a second okay and finally we're going to define our jumping functionality to do that we're going to say if input dot is action just pressed jump and we're currently on the floor so we only want them to be able to jump if they're currently on the floor then what we're gonna do is we're gonna say Y velocity equals our jump power okay so that seems like a lot and there's just two more lines of script and then we are done with this script we're gonna say our velocity dot Y value is equal to our Y velocity and then finally we're gonna say velocity equals and this is where we do the actual movement we're going to call move and slide we're gonna give it our velocity value and we're gonna tell it the up direction which is vector three dot okay so that was a lot of code let's briefly run through this so inside our handle movement function here let me just scroll back a little bit we're defining a direction variable we are checking our input for forward backward left and right and we are adding to our direction variable and we use in our transform basis which gives us the direction of this current player so we're going to use its Z and X values to determine our forward back left and right there we're normalizing the direction value so that if you're going diagonally you're going to be moving at the exact same speed as if you're moving forward we are working out whether or not we're currently on the floor and determining what acceleration we use so the faster acceleration if you're on the floor or a slower acceleration if you're in the air then we're using some linear interpolation to work out our ideal speed based on the players input and then accelerate up to that speed over time based on our acceleration value next we check in for our gravity so we're gonna say if we're on the floor we're only applying a minor amount of downward force to clamp us to the floor there otherwise we're gonna apply the maximum gravity by subtracting the gravity force overtime from our velocity and the clamping map to the maximum terminal velocity so that we don't fall too fast then we are checking whether or not player has pressed the jump key and if they're on the floor then they are allowed to jump we're going to apply our jump power to the Y velocity next we are setting the Y value of our actual velocity vector three up here to the Y velocity that we calculated and finally we are calling the move and slide function with our velocity with all of its forward back and upwards values calculated and we're given it our vector three dot up okay so that is basically our complete third-person player script so let's create a little world for the player to jump around in and test this out we're going to come back into our 3d scene in our world scene had a child node to the world and I'm just gonna use a CSG box here CST boxes are just really really quick ways to prototype out an environment what we're gonna do is we are going to scale this out using these little red boxes here let's scale that let's scale that and on the right hand side we're gonna check use collision let's move that down a little bit to the loaded player and I'm just gonna define a material here so on the right hand side we're gonna give it a spatial material and let's give it a color let's give it a nice red color here and then we're going to duplicate this with control D on the left hand side we're going to scale that in let's make a little platform here move it up a little bit and especially scale it that way let's kill it this way scale it that way a little bit more let's move it over okay let's duplicate that and let's move it over this way and I'm just going to create a series of platforms that hopefully the player is going to be able to jump on let's move that did you pay that again let's move it up move it across across this way this platform is actually a little bit too high so let's move these all down a little bit we could actually also just increase the jump power on our player itself we're gonna press play and now you'll see that we are able to jump around on these platforms nice and smoothly so one thing I'm going to do quickly is I'm going to select all of these and come into the material let's define a new material for it let's give it a blue color oops we chose the same material let's create a different material for the floor let's go back to a red and let's just create a wall here so that I can show you the camera boom arm so we're going to create a thin wall here let's move it across to the right hand side and let's give it a different shade of material as well just so that we can see a little bit better let's go to green oops okay it didn't use green but there we go let's press play okay so now if we walk up to the wall you'll see that the camera is fine however if we move around what you'll notice is that the camera zooms in to the player so that it doesn't collide with the wall now you might see a little bit of the mesh there that can be fixed with various things such as near clipping distances however I won't go into that in this tutorial but it's just make you aware that that spring arm is functioning properly and it is zooming into our player there and if we walk forward you'll see it comes out at the v distance again we move back towards the wall player it's closer and that's it we've created a very simple third person controller with full mouse movement pitch in up and down left and right and we've got some really nice smooth jumping and movement controls here as well if you liked this video please click that subscribe button and hit a little notification bell to be notified when I release a new content on the channel I release new videos every Monday so make sure that you don't miss out if you'd like to support this channel I have a patreon account and I'd really appreciate it if you checked it out you can download the resources for all the things you've seen in today's video as well as all the resources for every other video on the channel in my github link is in the description below as always thank you so much for watching and I'll see you guys in the next video [Music] [Music]
Info
Channel: Code with Tom
Views: 28,410
Rating: undefined out of 5
Keywords: godot, third person, third person godot, third person character controller, third person character controller godot, third person character controller in godot, third person movement godot, third person camera godot, third person mouse godot
Id: iu4ojdSRdnA
Channel Id: undefined
Length: 29min 9sec (1749 seconds)
Published: Mon May 18 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.