FPS Character Controller in Godot - Make an FPS in Godot Part 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on guys Tom here and in today's video I'm going to be teaching you how to create your very own first person controller and go down so let's get started the first thing we're going to want to do is open go to so I'm running three point one point one we are going to create a brand new project I'm just going to call this fps tutorial one I'm going to create a folder here opengl 3.0 is fine create an edit okay so here we are in our Godot editor we're going to choose 3d scene from the top left now I'm gonna be going a little bit faster than I did in my make your first game in Godot tutorial because I'm assuming you've watched that if you haven't please go back and watch that and it covers all of the fundamentals of the gada user interface the scripting language and things like that so go back and watch that I highly recommend it come back to this we're gonna be moving a little bit faster I will be explaining things as we go but like say we'll just be a slightly faster pace so we've created our 3d node here we're going to call it world it's just something I like to do the next thing we're going to do is we're going to create a player object so to do that we're going to press add child node we're going to type kinematic body and we're going to rename this to player now we need a collision shape for the player and to do that we're going to right click add a child node type of collision shaper and here we're going to define the shape for our player and the shape is going to be a capsule shape typically in first-person games the player would just be a capsule Collider because it's sort of roughly represents the shape of a human body now you'll notice here that this doesn't really represent the shape of the human body it's sort of sitting on this side it's a bit fat and chunky so we're gonna make some changes to this to do that we're going to come over to the right hand side first we're going to choose the transform and we're going to change the rotation degrees to 90 on the x-axis that just sort of makes it stand upright which is great and the next thing we're going to do is we're going to click on capsule shape here just where it says shape click capsule shape and we're going to get some options for this shape I'm going to change the radius to null point seven five which just makes it sort of thinner a little bit smaller and then because we've made it smaller on the radius we want to up the height a little bit so 1.25 and that just sort of gives us a nicer shape to work with I think you can change it to anything you like but I quite like working with this shape the next thing we're going to do is we're going to create a head for our player and the head is going to be where we put the camera it's all going to be where our eye level is so to do that right click on the player add a child node and we're going to this time use a speacial which if we look down here it says the most basic 3d game object it's the parent of all 3d related nodes it basically just means an empty object in space that has a position and a rotation and things like that we don't really care about displaying anything for the head as such we just want an object that sits in 3d space so we're going to choose a spatial press create we're going to rename it to head I just like to move this up to the top of the player hierarchy I don't know why it just feels logical to have heads in at the top of the player hierarchy next I'm going to do is going to add a camera to that head so we're going to right click the head add a child node this time is a camera so we've got this camera here you can see it's pointing forward there it's sort of pointing along on the z axis here so I'm going to click on the head and I'm just going to move it to where it looks like the head should fit within this capsule cleitus we're just going to move it up sort of like not pointing mine on the y-axis so roughly about there it's fine the next thing we're going to do is we're going to right-click the player add a child node and this is completely optional really I just like it because it helps you visualize the player a little bit better in the scene so I'm going to type mesh instance in the mesh option over on the right here I'm just going to choose capsule mesh I'm going to click on the mesh choose a radius of null point seven five and choose a height of 1.25 and in the transform just down here we're going to rotate it from the 90 on the x-axis now this just gives us like a solid capsule that we can visualize within our scene it really doesn't affect gameplay at all it doesn't have its own collider we're still relying on the collision shape here but I just like having this available because when your scene gets quite busy it's sometimes quite difficult to see this very thin sort of mesh here for where your player is so just like having this about just to make it easier to visualize the player okay so that is basically the structure of the player the next thing we're going to do is going to create some ground for him to collide with and in order to do that we're going to right-click on our world add a child mode and we're going to say let's just say mesh instance and we're gonna create a cube just create a simple cube cube mesh we'll move it down a little bit because we're gonna be wanting to test gravity later on we will scale it on both axes in fact absolute what we'll do is we'll just scale it on the X and the z-axis there we don't want to make it bigger on the y axis and in order to create a collision shape for this there's multiple ways you could right-click you could add your own collision shape but sometimes it's easier just to click the mesh button up here just above the 3d view press mesh and you can create a convex collision sibling so if you click on that it creates a collision shape and I just like to drag it just underneath again you can do other ways you can click on the mesh you can press create convex static body and that will sort of create this nested hierarchy and either way works or you could create a static body and it going to show you don't even have to have the mesh completely up to you but for now this will work I'm gonna rename this to ground alright so that is pretty much yeah I'm gonna save this scene really quick create a folder call it seems it's already called weld press save and just to make things a little bit cleaner and we're also going to create the player scene as well so we're going to right click the player node and press save branch as seem great a folder called player I want to save the scene as the player scene okay so we've got ground we've got our player the next thing we need to do is you need to start programming this guy so we're gonna click into the player scene we're going to expand our nodes here just so we've got a clear view of what's going on let's zoom into our player character here we're gonna right click on the player and we're gonna attach a script here we're gonna leave everything as default it's gonna create a player GD script and we're gonna press create so if you watch my previous video you'll know that you can export variables from a script and that basically allows you to modify them in the inspector window on the right hand side so just let me bump up the size of the code here just so it's easier to read if you're watching this in a small YouTube window what we're gonna do is going to export for variables they're gonna be the speed of the character and now let's just say ten they're going to be the acceleration of the character we'll say five they're going to be the gravity that is affecting this character or sane or point nine eight we're going to export the jump power of the character and let's just say 30 now all of these values I'm just plucking out of thin air will tweak them as we go as we start to get familiar with how our player controller handles we can come in and tweak the individual settings and you know refine that as we go but for now these numbers will be fine the next thing we're gonna do is we want to respond to keyboard input we want to respond to the W a s and D for moving the player around and we also want to respond to the spacebar for being able to jump in order to do that we're going to have to make some modifications to our input map and we're going to go to project project settings input map and here we're just going to define five more actions so they're going to be move underscore forward move underscore backward move underscore left move underscore right and jump we're going to assign these keys W for forward s for backwards a for left d for right and finally spacebar for jump okay so we're gonna start responding to these inputs now but there's a few things we need to do first we want to get access to the camera object because what we're gonna do is when we're moving the mouse around we're going to actually rotate that camera and we also want access to the head because we're gonna rotate the head as well we can say on ready bar head equals and then we can say dollar sign and this basically says I want to get access to a node that is in my current hierarchy so this hierarchy on the left hand side here the player hierarchy I want to get a node inside of that now you notice it's also populated here so I can get the collision shape I can get the mesh I can get a head and I can get the head camera so I'm gonna say we want the head and we also want unready Bar camera equals dollar head slash camera now the unready basically means when all of the objects all the nodes within this scene have fully loaded assign this variable to that which is a better way of basically saying func ready and you know assigning all the variables within inside that funky and function okay so we've got access to our head object we've got access to our camera we've defined some variables for the speed and acceleration and things like that so we're ready to start implementing our actual movement code so to do that we're going to define a funk for the physics process we're gonna say var Direction equals vector three so basically we will create a brand new vector three objects which we're going to populate with information based on what the player has imported the keyboard so we're gonna say if input dot is actually pressed and we're gonna say move forward so if they press the move forward button then we want to say direction now what we want to do here is we want to add the forward vector to our players Direction vector but in order to do that we need to know what forward is and forward is basically the direction that the head is looking so we're going to do one more thing here we're gonna save our head basis equals we're gonna say head dot get global transform dots basis now this is gonna get us the heads current transform object and on that there is a basis object which basically is its local transform so the local rotation axis and all that sort of stuff so we're gonna basically get that for the players head and what we can do here now is we can say Direction plus equals head basis so a head basis dot and then we want to say I think we just want to be easy yet we just lanzi and actually forward in go dot land is negative on the z axis so we're gonna say Direction minus equals head basis does e we're going to do something similar for if we want to move backwards so LF input is action pressed I'm going to say move backwards and we want to say Direction plus equals head basis dot Z now we're going to do similar for left and right so we're going to say if input dog is action press notice I've started a new if statement here because we want to be able to move forward but not backwards at the same time we want to be able to move backwards but not forwards at the same time but we do want to be able to move forward and left or forward and ride backwards and left backwards and right at the same time so these are two separate if statements here now we could just change this to an if but you're never really going to be moving forward or backwards at the same time they'll cancel each other out so it doesn't really matter to have this as an if-else is action pressed here so we want to say move left this time you want to say direction- equals head basis that X elsif input dot is a compressed move right OS a direction let me just scroll it down here Direction plus equals head basis dot X okay so if we save that now we are basically saying that we've defined the direction that we want our player to move now there's one thing that we do need to do here and that is we need to normalize the vector if we don't normalize the vector what's going to happen is if you're pressing forward or backwards it's going to be fine if you're pressing left and right it's going to be fine if you're pressing forward and left or forward and right basically two different directions at the same time you're going to be moving faster than if you would just moving in one direction so to do that we're going to say Direction equals directions dot normalized and that's just going to normalize the vector so it's got a length of 1 I believe is what normalization does so let's save that the next thing we're going to do is we are going to want to move our player now to do that we're going to define a variable at the top here and we're gonna save our velocity equals vector 3 so we're going to keep track of a constant velocity for our player and that is what we're going to use to move the player so down here is going to say velocity equals mu and slide velocity now we need to assign velocity of variable and to do that we're going to say velocity we're gonna say equals velocity dot linear interpolate now all this is going to do is we're gonna we're gonna start to move the player in the direction that we want to go but we're gonna do it at a rate that sort of speeds up reaches its max and then slows down again when the player takes the input way so when they open the players arts pressing the W key it's gonna ramp up to a speed that it's it's the max for his movement speed and then when you'd let go of the W key it's gonna slow down gradually to a stop now we can change all of that by tweaking the acceleration variable to get a natural feel but it's basically just to stop the player from immediately starting to move and immediately stop and again it just makes it feel a little bit more natural so what we're gonna do is we're going to say we want a linear a little linearly I can't even pronounce that linearly interpolate to our target vector which would be our direction multiplied by our speed so we want to go to our direction multiply it by our speed but we want to do it at a rate that is our acceleration multiplied by the Delta which is the time taken between frames so that just gives us a frame independent way of moving there so if we save this and we come over to our world we press play we're gonna select our world scene you'll notice now that if you press W you go forward if you press s you go backwards a you left Divac right and you can move in diagonals as well and you'll notice that there is a nice sort of smooth movement going on here you're not instantly jerking forward and then jerk into a stop when you let go there is sort of a little tiny gradual acceleration and deceleration which is great but you'll notice that we can't move around at the moment we're only locked to this one sort of direction so we're going to fix that now by enabling mouse movement to do that we are going to define another function here we're going to say func underscore input and the input takes end event and here what we basically want to say is you want to we're only interested in whether or not the mouse is currently moved so to do that we're going to say if event is inputs Mouse or so input event Mouse motion so what we want to say is if this event is the player moving them then we want to respond to that now all I want to do here is we want to say head well we've got a reference to it here so we want to say head dark rotates on the y-axis and we want to say degrees to radius and we want to take our events dots relative dot X now I know it says rotate Y here and we're saying relative to X here but that is because if we move the mouse left and right which is the x axis for the mouse we actually want to rotate our head around the y axis now you'll see why in a moment we want to multiply that Delta sorry that's relative X by some form of sensitivity now I'm just going to put not 0.3 here but actually what I'm going to do is I'm going to sport a new variable here called mouse sensitivity sensitivity equals log pin 3 let's place that in there now if I save this and if I run that you'll see now that if I move the mouse left and right we're rotating left and right but it's actually inversed so if I close that I absolutely want to say negative relative X you press play again and now you'll see that if I move my mouse right we turn right and if I move it left we turn left and you'll also notice that when we do our directions now it's actually going in the direction that we're looking which means we can walk around this entire platform which is great but we can't currently move up and down so we'll fix that now as well what we want to say here is we want to say camera 2 dot rotates on the x axis there to read - event dot relative dot y so if the mouse is moved up and down then we want to rotate the camera on the x-axis again we want to multiply that by the mouse sensitivity we saved that and now if we press play you'll notice that we can look down we can look up we can look left we can look right and everything appears to be working correctly but there's an issue here if you notice we can move beyond sort of vertically down we can sort of look back on ourselves which is not great because then everything that comes in bird and obviously this is not natural for a first person controller so we're gonna fix that now by closing this and to do that what we're gonna do is we're gonna need to keep track of the angle that our head or the camera is currently looking at so I'm gonna create a new variable here called camera X rotation I'm gonna start that off at zero now what we want to do here is we don't want to rotate our camera if it's gonna push us beyond those boundaries of basically 90 degrees either side so what we're gonna say is we're going to save our camera or sari bar let's just call it X Delta so the difference in X we're gonna say that is events got relative dot Y multiplied by our mouse sensitivity so basically this portion here and we can change that there to your s Delta what we want to do is we want to say if our camera X rotation plus the X Delta so if our current rotation plus whatever we're just about to move it by is greater than or equal to oh sorry greater than minus the 90 so we're gonna clamp this to negative 90 degrees and positive 90 degrees which is directly vertically up and down so if the change is going to be within those boundaries of 90 degrees then that's fine and we also want to check that it's the other way as well so if X Delta is less than 90 degrees then that's fine we can rotate our camera and we also want to say camera X rotation plus equals the X Delta so just to explain that again we're gonna say how far do we want the mass to move how far of an angle do we want to move by is this gonna push us outside of that negative 90 and positive 90 boundary if it isn't then that's great we can basically say rotate the camera and then we're going to increase our local camera X rotation variable by how much we changed it by just so that we can keep track and not go over that negative 90 and 90 boundary will press play and you'll notice now that if I look down I can't get past that 90 degrees and if I look up we also can't get past about 90 degrees there which is great so now we have full control of our camera with the mouse we can go left we can go right we can go up to 90 degrees we can go down to 90 degrees we can move forward we can move backwards if we move left we can move right and you'll also notice that if I look perfectly down and move forward we go at the exact same speed as if we looked forward and move forward and that's great because it means that our code down here which is using the head basis is working fine now if I change this here to camera okay global transform basis now you'll see an issue here everything appears to be working okay except for the fact that we would start looking down and things go a bit awry you look down even further and we're going super slow the velocity starts to go a little bit weird and all of a sudden were flying off the earth so that's not great so we change that back to head the final thing in all of this is we can just walk straight off here and hope nothing happens there's no gravity and we also didn't implement the jump so we're gonna do that now I'm just gonna make this code ever so slightly smaller so I can see a bit more of what's going on now to implement gravity is really really simple I can basically say where I'm assigning my velocity here all I need to do is say velocity dot Y now we're going to say plus equals our gravity we're gonna save that press play well you see what's happened there we've actually got the inverted gravity so what we're gonna do to close that we want to say negative so minus equals gravity press play and now you can see they just press play again there you can see that we drop we land on the platform and if I move off the edge and turn around you'll see there goes the platform we've fallen off the edge brilliant final thing to do is implement jumping again really quite simple we want to say if input dot is action just pressed jump then we want to see our velocity velocity dot y equals a so a plus equals our jump power save that press play press the spacebar and you'll see there we can now jump it's quite smooth and we fall back down to the ground and go off the edge here jump you'll notice there's an issue here though we can keep tapping space and oh I can infinitely jump so final final tweak here is that as part of this move and slide if we go to the documentation for this you can see that basically except a flaw normal vector now what that allows us to do is if we specify that floor normal vector we get access to a couple of really really handy functions I'll show you that in a second so we're gonna pass in this floor normal vector to do that we're gonna say vector three dot up and now what it means is we have access to this variable called is on floor so we say and is on floor so if we just press the jump key and we're currently on the floor then we want to allow the player to jump so we press play the press space we can jump keep clapping space and we can only jump after the player has hit the floor again if we go off to the side here when we jump off you'll notice that we can no longer jump back up or constantly falling there's one final thing that we can do and that is to lock the mouse to the window so that we're not getting this strange issue where you know the mouse is unlocked from the game window we can move off and all of a sudden the game does not receive an input anymore to do that really quite simple we can say at the top of our script here funk underscore ready and we want to say input dot set mouse mode input mouse mode captured save that we can also in our process here which we don't currently have and create one funk on the score process Delta we can say if input dot is action just pressed and we can say you i underscore cancel which is the escape key by default then we can say input upset Mouse mode Mouse mode visible and that's just gonna mean where we press the Escape key it's going to unlock the mouse again it's a press play you notice that our mouse cursor has gone from the screen and now we can move as much as we want with our mouse and it will never escape the window boundaries and for press the Escape key the mouse appears again and we in exit the game like that and that's the basics of a first-person character controller here let me just zoom out of the script here just to show you that actually it's really not that much code at all let's go into a normal-size fun here so we have our extend from kinematic body which just means that our player is a kinematic body so we're going to control its physics through code we're exploring a few variables here our speed which is 10 acceleration of 5 gravity of naught point nine eight jump power of thirty and a mouse sensitivity of null point three again you can tweak all of these by coming into the player node here clicking on player and you'll see on the right hand side that we can change all of these variables so you can tweak these to your heart's content make your character you know faster slower reduce the effects of gravity reverse the effects of gravity make them jump less make them not be able to jump at all you can tweak all of that with these variables here we're getting access to the head and the camera node within our hierarchy here we're creating a velocity vector that is constantly being updated dependent on our input we're keeping track of the cameras X rotation so that we don't go outside of the 90 degrees boundaries we're capturing our mouse input to stop the mouse exit in the window and our input function we're checking for any mouse movement we're rotating the head on the y axis based on how far left and right you're moving the mouse and for the camera looking up and down we're taking the mouse's Y axis which is up and down moving the mouse up and down we're locking it to that 90 degrees positive and negative and we rotating the cameras x axis there by whatever that is and then we're also making sure to keep track of the cameras x rotation in our function process here this is simply just to be able to show the mouse again when we press the Escape key and in the physics process here we are getting the current direction of our head object we're taking the movement keys and we are applying a direction to that so we get the direction that our heads currently looking in and based on whether or not best forward backwards left or right we're taking the appropriate heads translations for that we're normalizing the vector to make sure that if you pressed forward and left forward and back or a combination of keys it's not come in a larger vector so we're not being able to move faster diagonally and things like that we're Lin linearly I still can't say that word linearly interpolate in our velocity based on how far how far and how fast we want to move by our acceleration variable which just gives us that nice smooth in and out motion when we start and stop we're applying some gravity we're checking if the user can jump on if they've press the jump key and if so or applying some jump power there and then finally we are assigning the value of the movement slide function to our velocity that basically just means we want to move and slide by the velocity that we currently have and if we collided with something then it's going to give us back in modified velocity so it's gonna you know stop us from going into a wall so we assign the variable we start assigned the value of that moving side function back to velocity this final piece here this vector three dot up is basically saying the ground normal is the up vector so check for collisions in that direction and if we hit one then that's gonna give us access to the is on floor it's also gonna give us access to a bunch of other things as well but currently for now we just really care about this is on the floor and that is it that is part one of this FPS tutorial series we now have a first-person character controller that can move around it can collide with the ground we can jump and it's affected by gravity and we can also set various variables to modify how that character controller moves and things like the mouse sensitivity in the next tutorial we'll look at adding some ray casts into the player so that we can start doing some ray cast physics there for firing weapons things like that so I'll see you guys in the next video hope you enjoyed this one if you did leave a like down below leave a comment and get stuck with anything or you think I missed something I could leave a comment down below make sure to hit that subscribe button if you're not already subscribed I'll see you guys in the next video [Music]
Info
Channel: Code with Tom
Views: 123,164
Rating: undefined out of 5
Keywords: godot, fps in godot, fps godot, fps godot tutorial, fps character controller, fps character controller godot, character controller, character controller godot, godot character controller, godot camera controlls, godot fps camera, godot fps character controller, fps tutorial godot, fps tutorial, make a first person shooter in godot, make an fps in godot, make a fps in godot, how to make an fps in godot, how to make an fps game in godot, godot fps, godot fps tutorial
Id: UV-bhtb3734
Channel Id: undefined
Length: 33min 29sec (2009 seconds)
Published: Wed Aug 07 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.