How To Make A 3rd Person Controller With Full Gamepad Support | Godot 3.3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys in this video i'm going to be showing you how to create this third person controller here that supports movement in all directions friction and acceleration and slope movement as you see here it also has a variable jump and it even supports joy pads and controllers for consoles such as the xbox nintendo so if you want to know how to do this make sure you watch till the end of the video where i will also have a special announcement so make sure you stay till the end anyway with that said let's jump right into this video so to get started we are in a new scene here and we're going to add a kinematic body then we're going to go ahead and rename this kinematic body to player then with the player selected i'm going to go ahead and actually add a mesh instance as a child of it i'm gonna actually select that mesh instance and rename it to skin then i'm gonna go over to the inspector on the mesh empty and then we're gonna do new capsule shape we're gonna click on the mesh once more and give it a radius of 0.5 and a mid height of 2. then i'm gonna simply rotate it along the x-axis by 90 degrees to make it stand upward and then i'm just going to move it so that the it's flush with the floor anyway that looks good to me so now with that i'm gonna go ahead and actually select the player once more and i'm gonna go ahead and add another mesh instance in this case we're gonna go to the inspector mash new cube mesh and i'm going to move this into place where i want it to be and i'm going to actually click on mesh here and then give it an x of 0.2 a y size of 0.2 and a z size of 2. that looks fine to me i'm going to move it into place and this is going to be used to tell what direction my player is facing so we're going to be facing the negative z direction in this case anyway with the skin selected i'm actually going to apply a material so i'm going to go over to the inspector and then in the mesh properties there should be an option for material you can click empty new spatial material click on the material once more go and click albedo and then you can select the color in this case i'm going to give it a blue color now i'm going to do the exact same thing with the other mesh instance so i'm going to click on the mesh make sure that i open up the properties click material empty new spatial material albedo and select the color in this case i'm choosing orange and now i have this platypus harry the platypus capsule bean so anyway we're going to select the player and we're going to add a collision shape as a child of it so that we don't get that area anymore we're going to go into the inspector shaped empty new capsule shape and then we're going to click on it and then give it a radius of 0.5 and a height of 2 we're going to leave the margin and then in the viewport so we're just simply going to rotate on the x by 90 degrees and move it into place so that it actually covers my mesh instance or my player body and that looks fine to me so let's actually proceed so select the player and now what i'm gonna go ahead and add is very important so we're gonna add a spring arm and we're gonna actually move it into place where roughly where the head would be for our player and this looks about all right to me yeah that looks fine so now i'm gonna actually go over to the inspector and then i actually want to set up a spring length for this so in this case i'm going to give it a spring length 6 which should actually work fine for this and now we will see this line up here here which is basically a raycast that our spring arm makes use of anyway we're going gonna add a camera as a child of the spring arm and we're actually going to move this camera in a little bit but basically let me explain how the spring arm works so the spring arm has this raycast that checks for collision so if this line here collides with anything it will actually move the camera automatically to just before the collision point so if i have a collision right here the camera will be moved right here before the collision and so that the camera doesn't click doesn't clip uh you know into the wall essentially and this is built into godot so if i actually save my scene here and run it you will see that the camera is actually automatically moved to the end of the raycast from the spring arm and this is done automatically or it will be moved to the point of the collision or just before the collision anyway i'm gonna preview the camera and i'm gonna actually do control two so i can actually have two viewports here and i'm gonna move the camera here to roughly the view that i want now you don't have to do this i'm just doing this so that i have a better idea of what my end view is going to be since the camera is automatically moved by the spring arm towards the end of the spring arm raycast essentially like i said before and then i'm just rotating the spring arm and the x-axis uh to just get a view of the top of the player roughly and i think this view will work fine so let me just check it out and yeah this view will work just fine you can change it a little bit if you want on your end anyway with that done that actually is the basic setup of our player now we can actually add a script so we're gonna add a script called player and we're gonna make it be empty [Music] now to get started in the script we want to start by adding a bunch of export variables so in this case we're going to start by doing export var max speed and we're going to set it to a default of 10 then we're going to do export var and then gravity and we're going to use something like negative 40 and then export var let's see we're going to do the acceleration next which is equal to 70 and these values i pretty much just got through trial and error you can adjust it to however you want them so we're going to do export var friction is equal to 60 expert var air friction and this is going to be something lower than my normal friction so we're gonna have two frictions one for the ground and one for the air so in the the case of the air we're gonna give it a value of 10 which is much lower than the friction for the ground anyway we're going to do x var jump impulse is equal to 20 and we're just moving our gravity just to be directly above the jump input since it makes a little bit more sense anyway we're going to do another export var for the mouse sensitivity which is going to be set by default 2.1 and an expert var controller sensitivity for our controllers so in this case it's going to be set to a default of three and the reason we're doing export vars is so that we can easily access them from the inspector here so we can adjust them if we want while testing the game out anyway let's actually go back to our script here and actually define a couple more variables that we need so it's going to be var velocity is equal to vector 3.0 and then we're going to do var snap vector is equal to vector 3.0 as well then we're actually going to be using that snap vector and a little bit and well in the future here in this video to support slope movement anyway we're going to do function ready and inside that function we're going to do input that set mouse mode is going to then inside the parentheses be input that mouse mode captured and basically this is going to set our mouse mode to be captured so if we launch the game right now you will see that we don't actually see our mouse because it's being captured now we actually need a way to toggle between captured and visible so that we can actually close our game so to do this we're gonna actually do this in a funk under unhandled input so in this unhandled input function we're gonna do if event is action pressed and i actually haven't set these actions up so i'm gonna go to project project settings input map and start defining a bunch of actions that we're going to be using for the game here so we're going to actually start by defining a click action so in the action field just type in click and then you can click on the plus sign to add a key here so in this case it's going to be the mouse button and in this case it's going to be the left button you can change it if you want anyway we're going to define another action in this case we're going to call it toggle mouse captured and this is what we're going to be using as the key to toggle our mouse mode essentially and in this case we're giving it a key of escape and while i'm at it they need to find all the other actions that we're going to need as well so in this case let's start by defining our input actions so move forward and then we're gonna do move right and then move let's do a move back that's what we're gonna call it and then move left should be the last one we need now uh that's for the input now we need a couple more as such as for the jumping so action jump and then we need some for the controller support as well so in this case we're going to call this actions for the controller look up look underscore right look underscore down and look underscore left like so and now i can actually start adding the keys for this so click on the plus button for move forward this case is going to be the w key and i'm also going to add a joy axis to it and in this case it's going to be the left stick up since we're moving forward and then do the exact same thing for the other action so move right it's going to be d and it's going to be a axis of left right so left stick right and then move back is going to be s and then a joy pad axis of left stick down and then move left is going to be a and left stick left then for the jump we're going to use the space key and we're also going to use a joy button in this case you can set it to whatever button you want i think i'm going to actually set it to be the xbox b button so that's what i'm going to go with so click and edit then for the look up we're only doing this for the controller so all we need is a joy access so in this case it's going to be the right stick up for the lookup do you look right it's going to be the right stick right and then the look down is going to be the right stick down or yep like so and then the look left is going to be right stick left and that should actually do it for all the actions that we need for this specific controller so back in the script inside the is actually pressed we're gonna check for the click action that we set up and then if this is the case then and let me actually make sure that i actually called it click and it is so if this is the case we're gonna do input dot set underscore mouse mode and then we're gonna set it to the input mouse mode captured then we're gonna do another if statement so if event is action pressed and then this time it's going to be the toggled mouse captured if this is the case then we're going to do another if statement so if input dot git mouse mode is equal to the input that mouse mode captured meaning that our current mouse mode is set to be captured if this is the case then we actually want to set the mouse mode to be visible so to do this inside that if statement we're just going to do input dot set mouse mode to input mouse mode visible to actually show our mouse and then we're going to do else input and we're just going to actually copy this line here so we did ctrl d to duplicate the line so else it's going to be input that set mouse mode to input mouse mode captured so that basically toggles the mode of our mouse essentially so if we press the escape key it will essentially toggle between visible and captured also if we click on our screen it will also set the mouse mode to capture it as you can see here so that's done for that functionality that's all we need so now we're gonna move on to the other functionality so we're gonna do func physics process delta and then we're gonna start by doing var input vector is equal to get input vector which is a function that we're actually gonna define right here so func get input vector and then what we're going to do inside this function is we're just going to do var input underscore vector is equal to vector 3.0 then input underscore vector dot x is equal to input that get action strength and in this case is going to be move right minus the input that get action strength move left and then i'm just doing ctrl d to duplicate this line and instead of x it's going to be z and then instead of move right it's going to be move back and instead of the move left it's going to be move forward now this uh this logic here is dependent on your players or your character's orientation so based on the orientation of your player it's gonna be different so in this case we're facing the negative z direction to go forward so that's why we defined it this way now if we actually wanted our player to be facing the positive z direction so like this here so if we're facing this direction then we would actually modify this code to be the opposite so it would actually be the move left minus the move right the move forward minus the move back so this just depends on the orientation of your player anyway i'm just going to do ctrl c to undo that and then go back to the script so now i just want to return the input vector that normalized if input vector that length is greater than one else we're to just return the normal input vector and the reason we're doing this is because that normalize essentially tries to return a value of 0 or 1 meaning that if we're not pushing the analog stick on our controller all the way it will just by default try to be a value of one so we don't actually want to do this for our controller that's why we did it like that anyway let's actually do another function which in this case is going to be the get direction and for now we're just going to do pass we're going to make use of this function a little bit later anyway with that function now there we're going to do another function and in this case it's going to be the function to apply our movement so function apply movement and it's going to take an input vector for now and inside the function we're going to do velocity and actually it's going to be velocity.x i think so it should be velocity.x is equal to the input underscore vector dot x times my speed and in this case i think i called it max speed yes i did so just duplicate that line and change the x to dot z that should actually apply our movement already so to make sure you actually call that function inside the physics process so apply movement and then pass the input vector to it and we should actually be able to move now but we need to add this line as well so velocity is equal to move and slide velocity and then our up direction so in this case it's the vector3 dot up and you can control click on move inside to read up on it and then the vector3.up essentially returns the vector that's 0 1 0 like this so if you control click on it as you see it returns a vector to 0 1 0 like i just said anyway if we test this out and we won't actually be able to see if we run the local scene since our players on the void so i actually went ahead and i already created a test level that we can test our controller in so let's go ahead and instance in our player and this test level that i made like so and then let's just click play and as you can see we can actually move our player around now but we can't actually move the camera around so let's actually add the functionality to be able to rotate our view so to do this we're actually going to go into the function unhandled input and we're going to start by doing another if statement so in this case it's going to be if event is event or if event is input event mouse motion and input dot get mouse mode is equal to input mouse mode captured so i'm just going to control copy this line and paste it if this is the case then i'm going to go ahead and do rotate underscore y and then dig to red and inside the dig to red i'm going to do minus event dot relative dot x times my mouse sensitivity and then i'm going to actually go up here and define a unready var so on ready var spring arm is equal to dollar sign spring arm to select my spring arm then inside the if statement we were just writing we're gonna do spring underscore arm dot rotate underscore x dig two red minus event dot relative and in this is going to be dot y times my mouse sensitivity so it should actually already be working so this line right here basically handles the horizontal movement and the spring arm line handles the vertical movement and as you can see it's already actually working but there's a slight issue where as you will see here in a little bit if we actually move and rotate our view we are still actually not moving in the direction we're facing when we press forward so that's an issue and another issue is we can actually rotate our camera like so so we actually need to limit our camera vertical movement so to do the vertical movement and limit it we can do this line of code here which is spring underscore arm that rotation dot x is equal to clamp and then what is the value we're clamping we're clamping the spring underscore arm.rotation.x and then the min value that it can be so it's going to be dig to red minus 75 and then the max value which is going to be dig to red 75. you can control click on clamp if you want to read up on it anyway if we test this out now that should fix the issue with the camera being able to rotate all the way around the player and it does now let's actually fix the movement here and that's where our get direction function is going to come into play so we're actually going to pass our input vector into this function and inside the actual function what we're going to do is we're going to do var direction is equal to input vector dot x times then in this case it's going to be the transform that basis dot x close parenthesis and then plus and then parenthesis input underscore vector z times transform.basis.z then we're simply returning the direction like so and make sure you actually call it in the physics process so we're going to call it right after the input vector so we're going to do var direction is equal to get direction and we're going to pass our input vector to it then inside the apply function we actually want to pass a couple more values to it in this case we're going to pass the direction and the delta values to it as well now let's go over to my apply movement function where i'm going to make sure that i'm actually passing these values so make sure that you pass the direction and the delta to it as well and we can actually get rid of this code now and now in this case we're going to actually do if direction is not equal to vector 3.0 if this is the case then we're going to do velocity dot x is equal to velocity that moves toward the direction times my speed and then then at a rate of acceleration times delta so this is basically adding the support for acceleration in our game and we want to make sure that we put that x at the end of this and it should actually be max speed not speed and then we can just duplicate the line and change the x with dot z so that should actually do it for this now so like i said it's moving our velocity.x and z towards the direction times max speed at a rate of acceleration times delta so if we actually test this out now we should actually be able to make it work now and it is actually working so when we press the w key it will actually move forward to the direction that we are facing and as you see there's still a couple issues for example uh we still don't have gravity in the game so let's actually go ahead and add the gravity so we don't have that issue anymore so funk apply gravity and then inside this function all we want to go ahead and do is velocity that y is equal to and actually is going to be plus equals the gravity times delta so make sure that you actually pass the delta value to this function then we're going to actually clamp the value that the velocity that y can be so that it doesn't increase forever essentially while we're falling so velocity.y is equal to clamp velocity.y which is the value we're clamping and then the main value it can be is the gravity and the max value it can be as jump impulse then make sure you actually call it in the physics process so apply gravity and pass delta to it so with that if we test the game out we should actually have gravity in our game now so let's test it out and as you saw we can actually fall now now there is another issue you probably can't tell but as the code is right now we can't actually stop our player so that's an issue that we need to address here let me just make sure that it is the issue i'm talking about and yeah we can't actually currently stop the player so to stop the player we actually have to apply friction to our player because currently we're not actually doing that so we're gonna do funk apply friction and inside this function we're gonna do if direction is equal to now i know i put not equals to the vector 3.0 but it should actually be direction it's equal to vector 3.0 i do fix this here later in the video so anyway inside that we want to do if is on four velocity is equal to velocity that move towards the veloci or vector 3.0 so we're moving towards a value of zero at a rate of friction times delta so we want to pass our direction to this function as well as our delta value so i actually want to make sure that i actually call this function in the physics process so apply friction and then press direction and delta and as we test it it's actually not working because like i said i kind of messed up where i actually set it to check if it's not equal to vector 3.0 when it should actually be if direction is equal to vector3.0 so here i'm just checking to see where the error is and i finally did notice it and made the change here so it like i said it should be if direction is equal to vector 3.0 now if we run the scene it actually is working so if you just want the very basis of a third person controller then this is pretty much all you need so i am going to add more functionality though so i'm going to start by actually adding different friction values for when we're on the floor and when we're on the air so i'm just control duplic we're control copying the lines of code above so the velocity.x is equal to the move towards direction times max speed and in this case it's going to be air friction times delta so make sure that you actually change the lines there to be like follows so anyway with that now done we're gonna do func jump and then if input that is action just pressed and we need to define our jump function because we can actually test our our air friction without being to jump so anyway back in the if statement we're writing if we're pressing the jump action we're doing velocity dot y is equal to jump impose then to actually add the variable jump all we have to do is if input that is actually just release jump and velocity that y is greater than my jump impulse divided by two if this is the case then the velocity the y is going to be equal to the jump impulse divided by 2 instead now let's actually make sure that we call the jump function up here in the physics process and now if we test the scene out it should actually be working and it is as you can see so there we go we have a jump in our game now which is fine and there's some weird clipping with the camera so we'll fix that here in a little bit but uh let's actually go to your player scene select the camera and make sure that the far is increased to a higher value in this case i use 200 you can change it to whatever value suits your game though and that fixes the clipping of the camera so now let's actually add the rest of the functionality that we need and let me actually test something here so actually let me actually show you so to currently the controller that we're using doesn't actually support slopes as you can see we're slowly sliding down the slope so to stop this from happening we need to change some code here and that is we want to go over to the move and slide function and instead of where we're calling move and slide instead of move and slide we're going to do move and slide with snap so the move and slide with snap actually takes a couple more parameters than the normal movement slide as you can see here it takes an up direction a stop on slope which is by default set to false max slides and so forth anyway we don't have to actually define each value but we do have to define a couple more so in this case we're passing the snap vector which we defined up here right after our velocity like so and then right after the vector3 dot up which is our up direction we're setting true for the stop on slope so now if we actually test the scene out we should actually stop on the slope and not slide down and as you can see it is actually already working now we still do want to do a couple more things to make sure that it's working as intended so what i'm going to be doing here is i'm actually going to go into my uh and actually i'm going to start by creating a new function so in this case it's going to be func update snap vector so in this function all we're going to do is snap underscore vector is equal to minus get underscore floor underscore normal if it's on floor else vector 3 that's down so now it should actually work as i intended so let me actually test it out and we aren't sliding down the slope and we shouldn't be able to jump as it is right now and it seems like there's something wrong since we can jump and we can actually jump uh quite a bit so uh there's a couple errors so let's actually fix those errors so first let's fix the jump error here and i think it's because i forgot to add a additional condition to the if statement as so before i actually do that let me actually make sure that i actually call the update snap vector up here and make sure that that's the issue first and it seems like that was actually the issue we just forgot to actually call the function and as you can see we can't actually jump anymore and that's because we can control click on the move and slide with snap as you will see here i will basically snap to the surface and you need to disable the snap in order to actually be able to jump and we do this by doing this in the jumping function so we want to do it snap vectors equal to vector 3.0 so that should actually allow us to jump now again but like i said we actually want to add another uh condition to the if statement that we forgot and that is n is on floor so now we shouldn't actually be able to jump without end and we should actually be able to jump and actually snap two slopes without sliding and as you can see it is actually a variable jump as you can see when i'm actually comparing it on the wall here so if i hold the button longer the higher i actually jump another thing like i said the reason we're using a spring arm is if we actually get close to a wall like this the camera will add automatically be moved to the collision points or just above the collision point so we don't actually clip through the wall now there is a little bit clipping but for the most part it works well enough anyway with that fixed let's actually go ahead and add support for our controller so we're going to add a new function called func apply controller rotation and inside this function we want to do var and let's call it um what am i going to call it let's call it something like axis vector is equal to vector two dot zero in this case we don't need a vector three and vector two is good enough anyway we're gonna do exit vector dot x is equal to input that get action strength and in this case it's going to be the look right minus the input that get action strength look left and then i'm duplicating that line with control d and then changing the dot x with that y they look right with look down and the look left with look up like so then what i want to do is an if statement so if input event joy pad motion if this is the case then i want to do rotate underscore y big to red and then minus axis vector dot x times controller sensitivity and then i'm duplicating that line and then i'm gonna do spring arm and it should actually be spring underscore arm that rotates underscore x dec 2 red minus x is the underscore vector dot y times the control sensitivity and in this line of code right here we actually have to move it and i'm actually going to show you why here in a little bit but make sure that we actually call this apply controller rotation function and the physics process now if i run the code here you will see the issue i was talking about where our camera movement isn't actually being limited in the vertical direction when we use the controller so to fix that we're simply going to move this one line of code here right after the apply controller rotation function call so now if we test it out the controller movement is actually working as intended and actually i think there's a slight error and let me check if it's in my code here and everything looks fine so i think it's in my input map so let me show make sure that i set my input map correctly and just as i fought i actually set up my move back action for the joystick wrong so it should actually be left stick down for a move back now if i actually test it out it should work as intended and it actually does seem to be perfectly working like i intended so now we have a character controller that you can jump in support slopes you can move with the controller or the mouse and everything is working as intended like i said now i'm just gonna check my project settings here and i'm actually gonna change the jump to be the uh a button on the xbox controller instead because with the b button it was feeling a little bit weird now we're gonna do one last thing which is we're gonna add a position 3d to our player you could also use a spatial and i'm just going to rename that to pivot and then i'm going to actually move the skin and the mesh instance as a child of the pivot and the reason we're doing this is it doesn't really make sense for our player and we were actually playing an animation to keep facing forward if we're moving to the right direction so in order to fix this issue we're gonna make use of this pivot so on the top of the script we're gonna do unready var pivot is equal to dollar sign pivot and then we're gonna scroll down here and then in our apply movement function we're just gonna add this line and this is the easiest way you can do it so the easiest way you can do it is just do pivot that look at global underscore transform that origin plus direction and then comma vector read that up and you can control click on look at to read up on what it does if you want anyway if we actually launch the game and test it out as you can see when we click to move left or right our character actually rotates in that direction now it is a bit clunky so in order to get a smoother movement we're actually going to finally make use of the input vector here and instead of the pivot that look at we're going to do pivot.rotation.y is equal to lerp underscore angle and in this case it's going to take the pivot that rotation dot y comma and then a tan 2 and then minus the input vector dot x comma minus input vector dot z like so and then comma and then it's going to be at the rates we're moving so it's going to be 25 times delta and you can click on lerp angle to read up on what it does as well if you want and it should actually be working now but i'm actually going to define another expert bar at the very top to actually you know handle this movement so we're going to call it expert var wrote underscore speed and by default we're going to set it to that 25 and instead of 25 down here we're just gonna do rota underscore speed times the delta and now as you can see the movement for the player rotating in the direction we're pressing the key in it's a lot smoother now you can actually adjust it from the inspector if you want or from the code i'm just going to change it to 30 in the code just to get it to be a little bit more smoother and as you can see our player controller is fully done now so we can go up slopes in that slide we can actually jump around move around it has support for controllers and so forth so everything seems to be working so with this we're actually done so i'm actually gonna be leaving a link to the github project for this particular project in the description and you can use it for whatever you want feel free now if you made it this far then you're absolutely amazing and actually have a special announcement so currently i'm working in an online multiplayer course for go that's where i'm actually going to be showing you how to make a game similar to mario 35 using go that's built in high level multiplayer api so if you're interested in this i'm actually going to release this on kickstarter so you can actually find a link in the description to the kickstarter page where you can follow the project if you're interested and i'm actually going to have more details about this in the near future probably later this week and the following week so look forward to that anyway with that said if you liked the video make sure you leave a like and consider subscribing and i'll see you guys in the next one
Info
Channel: rayuse rp
Views: 10,125
Rating: undefined out of 5
Keywords: Godot, Godot tutorial, gamedev, How to make games, godot 2d, godot 3d, godot 3.3, godot 4, blender, 3d modeling, hololive, anime, channel update, godot multiplayer, rayuse rp, devlog, how to make 3d game in godot, Channel Update Godot and More, godot dedicated server, indie games, intro to 3d in godot, godot 3d games, 3d movement in godot, 3rd person controller godot, 3d person controller, godot 3.3.1, How To Make A 3rd Person Controller With Full Gamepad Support | Godot 3.3
Id: dcCzKHTxflo
Channel Id: undefined
Length: 35min 52sec (2152 seconds)
Published: Tue Jun 29 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.