The DEFINITIVE FPS Tutorial for Godot 4.X (FULL COURSE)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi there today we're working on creating a full FPS weapon manager from a basic 3D scene all the way up to a fully customizable weapon system that will allow you to add as many weapons as you like all the hit scan and projectile weapons you can possibly think of we'll even add a melee attack at the end there too then you can even go on to make a full FPS game like I am I have a prototype here which is kind of like traveling between Dimensions I guess like that one level in Titanfall I think it's very early days this is the first part in an incredibly long tutorial series that I'm doing that will allow you to make a full FPS weapon manager which will be everything from what we're doing today all the way up until adding the juice and all the good stuff that makes it look like a legit FPS game that you might find in Steam I thought I would edit Together part one for newcomers to make the experience a little bit better there are a couple of jumps between the subjects because I did not film this all in one go if this is helpful for you please like And subscribe it really helps the channel out keep an eye out for that second part in a few months time where we start to add some juice to this project let's get started if you haven't created a project already just start one up so let's just jump into it I'm going to open up mine it's going to look a bit different because I've already created the world but I don't have an FPS controller in here so let's start the first thing we need to do is create a character body 3D they've changed the name on me I find it hard to find it um we just need a collision shape 3D as well and a camera and I'm going to go ahead and just make sure that's just a child of the main character body 3D and I'm just going to rename this to main camera give this a collision shape it could be anything you want but capsule is typical I like to just change the shape to a typical height rather than two meters and let's just bring this up so it's in the scene and the other thing I like to do is to raise the camera up so it would be at some kind of height level all right let's just push this guy back a bit so we're going to add a script just like that and the magic inkidot for is this template I don't know if they had them in guitar 3. maybe in the later ones I'm not too sure but these templates are magic so I'm going to click create and right away you've got pretty much everything you need if you run this game you guys probably already know this could go for it's been out for a while now we've got everything we need for movement and jumping we just don't have that Mouse movement so I'm going to show you guys how to put that in today so the very first thing that we want to do is get access to that main camera node now I'm going to access as a unique name because this is very basic and I'm sort of just assuming that we're gonna probably change things as this project gets more complicated so I'm going to call this main camera get node brackets string percentage and then main camera okay that's done okay we need two variables to make this work we're going to need to create a variable called camera rotation and this is just going to be a vector 2 and I'm just going to initialize it as zero zero okay and then we also need a variable called mouse sensitivity I don't know if I'm spilling that right feel free to look it up and correct me in the comments uh it is zero zero point one it's a small number because we're working in radians so you know we don't don't need much to do a full circle I think it's just around three so we just want to make that number way smaller you can always expose the second later as your project grows so that your users can edit it and make it either more or less sensitive depending on their Mouse so then I'm just going to add a ready function here we're not going to do much with this once again keeping it simple so we're going to go input dot set Mouse mode and we're just going to turn it Mouse mode captured so that'll just make so the mouse doesn't show on the screen as we work through this okay and the rest is all in the input function okay so the rest of this is happening in the input function I'm just going to add in a quick little check to see if we press the Escape key uh and basically expose the mouse if we do that just makes it easier to debug we can always make this more complicated as time goes on I like to keep saying and Okay so we've got that there okay this is where the magic happens we've got if event is input event Mouse motion we're going to create a variable and we're going to call it mouse event we're going to set it equal to event dot relative multiplied by mouse sensitivity which is what we set up there and then we're going to call a function called camera look and we're going to pass in that event okay so let's create this function camera look and I'm just going to call the variable movement and it's a vector 2. Okay so what we do here is essentially we add our movement to the camera rotation variable so this would be plus equals movement okay then there's two functions we need to call transform dot basis equals basis and Main camera dot transform dot basis equals basis this is what makes it possible and a small transformed wrong that's okay and then there's two other functions we need to call which is really the magic rotate object local and first we always rotate in y so Vector three this is what this expects you have to tell it what Vector you want to rotate so this is Vector 3010 there are other ways to Define that variable this is just what I like to do and it's negative camera rotation dot X and that's that I make a note here just in case you're playing around with this and you forget first rotate 6y then you want to rotate the main camera instead of the kinematic body rotate actually we might just copy because I can barely see my keyboard ready to object local and it's Vector 3 again zero oh sorry one zero zero so we're doing the X rotation next and we'll call negative camera rotation Dot why and we'll go Bend rotate X okay so the other thing we might also want to do is just clamp the rotation in the y axis so I'm going to call camera rotation dot y equals clamp camera rotation dot y negative 1.5 comma 1.2 because we are working in radians again so it's not going to be degrees you could convert these if you wanted to but it's easier just to directly key them in here okay so this is it looks like I forgot a comma there that's okay let's go again okay and now we're working perfectly now the one thing you'll notice is that no matter where I turn my mouse I'm always going forward I'm pressing y uh W I should say right now I'm always moving forward now to me this is pure magic because back in goodo 3.5 this was a little bit more complement complicated to implement but if you look down in this automatic script they've got transform basis times Vector 3 input directions and this is what makes it work it's why I'm rotating the kinematic body here and not the main camera now if you rotate the character it'll actually get that direction automatically just on the basis of how this is set up so it's super easy I don't know how long we've been recording for this has been it says 15 minutes on my screen but you know by the time I cut this up it's going to be even shorter um so that is all you need to do This is complicated to say the least why do we need to do transform basis equals basis we're basically resetting the basis every time that we do a rotation all these kind of things they're very confusing if you need to understand more or if you want to know how rotation really works you can come to the docs and read about using 3D transforms as a whole thing this is how I had to do it when I was working it out you know last year or the year before in Godot three um and here is basically the snippet that they give you for an FPS star controller which is pretty similar to what I've given you here except for the rotation for the main camera in the Y hey guys Isaac from the future here I just um I noticed that I missed explaining this function in my tutorial and I thought it was worth coming back and explaining um just sort of what we're doing here we're taking the input event Mouse motion so that's just a number on your screen event.relative so if you printed that out it would just essentially be a coordinate that relates to the direction that your mouse is moving at any given time and we can basically use this information we pass it onto the camera look and we add that to the camera rotation and that just accumulates indefinitely obviously we clamp the why because we don't want to be able to spin around forever but if we are turning on the y-axis then we want to be able to just spin forever and then we come down to the rotate object local now first we're going to do it in the Y but where you might notice that we're using camera rotation.x so if you think about that with your mouse you're just moving it left ways across the screen and that's actually the x-axis for your screen but we want to spin on the Y if you imagine like a pin going through your character's head why is the one that goes at the top and we're just turning that on its head and then next we're going to rotate in the X and we're going to use the Y so that's actually the same principle when we push upwards on our screen then that's actually the y-axis on our screen but it's the x-axis for our character if you imagine just got your 3D gimbal X goes through the character and we're rotating that so that's your up and down and that's sort of just a slight overview of how that works and I thought that might be a bit nicer than just skipping that all together first thing that I'm actually going to do is just add an environment to the scene because it looks pretty boring in the last tutorial so I'm going to click these three little dots and just click add environment to scene um it's just an overcast looking kind of environment nothing too special but it will just make things look a little bit nicer while we're here okay so the next thing I want to do is just click this character body 3D and Save branch as seen I'm going to save that in the tutorial folder and I'm just going to call it something like FPS character probably okay so now I've done that I'm going to open that scene and we're going to reset the transform since we set this up in another scene but things are a bit wonky here so I'll just click the character and come down to transform just click this little round refresh looking button and there we go okay so I'm going to rename this as well something like FPS character the same as the scene name nice and easy and I'll just come back over into the world and I'll probably delete this because I don't know it doesn't rename it for you and I don't like that so just drop this in and I'll just make it back on the tour roughly where it was make sure it's in the scene okay now we can jump back over here and start workings okay so the first thing I want to do is just split the view into so that we can start setting up our animations um I'm going to come down to this bottom one and I'm going to click preview on the camera so that when we're doing our animations we can see what we're doing I'm going to add a node here we want to look for a node 3D just a plain old node 3D and I'm just going to rename that to weapons underscore manager We'll add another child to that it'll be another node 3D and I'll probably just call this FPS underscore rig this is where we'll put the actual weapon models and animate them so I've got some models from Kenny he's got all the good stuff so I'll link his website down below if you need some you can just drag some in it doesn't really matter for this demonstration I'll look for a pistol and sort of like an automatic rifle as well and one other one just for good measure as well this one will do all right so they're just sitting right in the middle of our scene so we'll just sort of Select them all and just push them down to the feet where they're at a view of the camera and now we need to add an animation player so I'll hit add note again and click on animation player so Blaster n activate is the first one I'm going to key in the position they're at now as the starting position of the activate and I'm going to make them all invisible as well and toggle that visibility on as I start to key in this animation and I'll just bring that up to where I think it should be and key that in cool I'll make it a bit shorter books are all right sometimes you're just going to play around with these till you get something that you like I want it to be a bit quicker but I noticed that it was spinning around like crazy so I just had to fiddle around with the exact point and I kind of like this spin interview so I ended up putting that back in after I fixed it so the key thing to remember here is that your starting frames for the deactivate should be the same as the ending frames for the activate animation so just key them in and then I'll just push everything back to where it was as long as it's out of sight and not visible on the model then you should be good we don't want to draw in a shadow when it's not active so just make sure to click that visibility off as it descends and we'll keep that in just check out your animations as you go just make sure you're happy with them okay so on to the next shoot probably the most important animation that you're gonna do to just make sure you pay attention to everything I think it's best as if the gun moves backwards first and then rotates upwards just looks a little bit more believable so I'll just key these in things will start to look pretty good and you really don't need as much time as you think you do even for a longer shoot animation 0.2 seconds is quite a long time and the other key thing to remember is I'm going to be using the animation player as a way of regulating our fire rate other people will do this differently and that's fine but make sure that you're setting your track length to be the same as the ending point of your animation you don't want any lingering time unless of course you do but just make sure that you're cognizant of the fact that the track time which is up in the top right hand corner is the same as what you want the fire rate to be I feel like it's mandatory in every single indie game where there's no actual rig there's just floating guns you have to spin the weapon in order to reload if you don't do this then you're not a true Indie FPS developer so that's what we'll do here okay so the next one is the out of ammo this is what's going to play When the gun runs out of ammo and they can't reload anymore we're just going to make it Rock back and forth uh just nice and simple so they can see that it's actually not firing I'm not going to put any sound in this I think in a previous tutorial for guitar 3.5 they added sound in particle effects we're not going that in depth so I'm just going to make this shake just so it's nice and Visually clear that we're not pre-loading okay so those are the five animations I want for each of my guns I'm just going to blast through now and set this up on the next two weapons I'm going to smooth this up so you don't have to watch me and I'll um see you when we are setting up the resource to manage all of this okay so that's all set up now I'm gonna close off all these folders so it's a little bit more readable and I will create a resource so I'm going to right click here and I'm going to add a script so I'm going to come down to new and script we're not going to add this to any nodes so that's how we're going to have to do it well I'm going to call this one weapon underscore resource and where it says extends node I'm going to delete that and replace it with resource uh and class underscore name so that we can find it easy I'm going to call mine weapons resource and I'm spelling it wrong so I'm going to come back here and correct that okay so let's add a couple of variables in fact a resource is generally just a lot of export variables and it can hold functions but ours are just going to be variables so uh the first one is obviously the weapon name as a string and the list of the five animations that we set up so I'm just going to call them the name of the animation underscore a Nim feel free to either copy that or do your own thing I don't really feel like writing animation out it's a lot of letters so reload underscore Nim and these are all strings by the way don't do the export here not change make sure that you try to make these as close to what you are actually named for animations as possible otherwise things can get a little bit confusing when you do have a lot of animations going obviously there are Arguments for using different ways of keeping track of all this data you could use Json file you could use a CSV file depends on how many weapons are in your game and the number of different actions that are available so we're keeping this simple with the resource it's nice and easy to set up that way the other set of variables that we need are obviously the ammo the current ammo is the amount that you can shoot the reserve ammo is the amount that you can reload from and I like to call it a magazine this is the amount that you can reload when you press the reload button the maximum amount you can and the max demo is the maximum amount that you can have in reserve Okay so and I'll also just add an auto fire sample as well Auto underscore file as a Boolean okay those are all the variables that we need right now we're going to add to this as we go along but this will do for now I'm also going to come down and create a folder called weapon resources and in that folder I'm just going to right click new resource come down and look for weapon resource in the list weapon resource so you'll see I've got an old one there that's because I've been working on this a couple times okay so I'm just going to name these the exact same as the actual weapon models just that I know what they are nice and easy to keep track of and you'll see we've got our first setup here we've all got these variables up here I'm just going to type them in the name of the weapon Blaster and I'll copy that and I'll just come down now the most important thing is when you're putting in these animations make sure that they absolutely match the name of the animation I almost put another score in there I don't need it there's a space so they have to match exactly your animations if you're having trouble with this later on and the animations aren't playing it could be because there's a naming there's a name wrong you'll get an error in the debugger but it won't actually crash the game so double check that if you're having problems and then just set up your weapon for the ammo that you want making sure that I've got all my animations checked and so yeah just you know whatever weapon you're making you know set the current ammo the reserve ammo the magazine I said before that's the maximum amount you can reload and the maximum is the amount that you can hold in reserve the maximum amount you can hold and Reserve so those are the variable names that I'm using hopefully that makes sense I'm going to go through and create the rest of these resources I'll speed through this section uh so you guys don't have to watch me just make these okay now that we have them we can start actually setting up our weapon manager this is where the magic happens all right so we'll add a script to the weapons manager it can be called weapons manager that's fine it extends node 3D that is absolutely fine as well okay so we need a few variables to make this work the first thing we want to do is get our animation player so I'll right click access to Unique name on animation player and I'll hit that at onreadyivar animation underscore player and I'll write get underscore node and quotation marks and then just drag the node over to that and the next variable we need is the current weapon this is the variable that we're making all the calls on and the next variable will be the weapon stack which is just going to be an array of all the weapons that we currently have available to us in the game so if you pick up a weapon it gets put in the stack Okay so we've got a weapon indicator that's just going to be a variable to keep track of the array next we've got next weapon which will be a string that we hold when we're changing weapons right so now we've got weapon list which is going to be a dictionary that we can use to keep track of all the weapons available in the entire game even if we're not holding them and we're going to have an export variable as well which will be the resources I'm just going to name mine underscore weapon resources and it's going to be an array and this is the trick square brackets and then type weapon resource in there and it'll just allow us to drag those weapon resources into the array which is nice and convenient and then export variable start weapons which is just going to be an array of all the weapons that are available at the start of the game or when you load it up okay so here we can start setting it up I'll add three items to the array and just drag these resources over you can just drop them in doesn't really matter the order okay and then we'll come back up and I'll click on that again and I'll add two starting weapons I won't do all three because I'll save one to show you how to pick up a weapon in a later tutorial but right now I want to show you guys how to change weapons so uh we'll start with that I'll add in Blaster D and Blaster N I think okay so just make sure that everything's lined up and you're happy with it and we'll start setting up the rest of the script all right so we're going to need a couple of functions I'm going to type these out now first we want to initialize and then we're going to need an enter and I'm just going to write pass and we'll explain these in a second next we're going to need a change underscore weapon which will be the main one to change weapons and and exit as well and that'll be when we're exiting the weapon and I think I'll just put change weapon at the bottom of this script okay we're going to need a ready as well and we're just going to call initialize it'll be the first thing you call it's how we enter in to our state machine because that's essentially what this is a state machine which controls the current weapon state that we're in Okay so um the exit is going to be what we call before we change weapons to sort of validate that we're not in the middle of something else or whatever it is anything that you need to validate and enter is going to be what we call when we enter into the next weapon so we can you know uh play the right animation we can reset some variables if we need to update the ammo in the HUD or whatever it is all right so for our initialize uh we are going to want to pass in the starting weapons and obviously it's going to error out onto the ready that's going to be an array we'll pass in the export variable start weapons and we can get started so the first thing that we want to do is actually create our dictionary list of all the weapons that are in the game so to quickly explain the weapon resources array that we have set up above isn't really going to be used except to build this dictionary we could just have a dictionary and skip the array altogether but we want to Loop through for weapon in weapon resources weapon list and then we'll go brackets weapon dot weapon underscore name and we'll set that equal to the weapon okay and that'll create our dictionary so that as we're going through this we can refer to it okay the next thing we want to do is just Loop through our start weapon so 4i and start weapons weapon underscore stack dot pushback I so we're just going to push all the start weapons into our array so our weapon stack is just going to be a string reference to each weapon that we can you know call up with that dictionary alrighty so we want to set the current weapon equal to the weapons list square brackets weapon stack put it back is zero so that'll just be the first weapon in the stack this is going to be the very first weapon that we pull up and then I'm going to call enter okay so there's not a lot for us to do right now when we call enter um all I can really think to do is just play that first animation so I'm going to call the animation player dot q and I'm just going to pass in current weapon dot activate NM and once again just a reminder to make sure that you've got the variable name right and you've also got the animation name right because I found with this way of referring to things it's not going to you know pre-fill in the variables or anything like that so it's not going to tell you it's wrong until you run the game so I'm going to run the game here and I can tell that I've got it right because the weapon has shown up and is playing okay let's move on and we actually in order to change weapons we're going to need to set up some inputs so I'm going to come up to the project settings and I'm going to add some actions here so we're going to call it weapon underscore up and we're going to add that and I'll weapon underscore down and I'm going to make these up and down on my keyboard just because my mouse is a little bit broken at the moment um okay so and I'm also going to add shoot and reload I'm going to set them to to left Mouse button and I'll come back up here and I'll add reload as well and I'll set that to R okay so now that we've got that we can add the input function to our script so it'll come up below the ready and I'll just enter down a bit and I'll type Funk underscore input event and we can do a check if event dot is action pressed weapon up and we'll just pull up our weapon indicator and we'll increment that I'm going to use the Min function so I'll choose between the smaller of the two weapon indicator plus one or the weapon stack dot size minus one so we don't want to go greater than the length of the array that's why I'm doing it this way and then I'll just call exit and I'll need to pass in the weapon stack square brackets weapon indicator okay and we're going to get a bit of an error here because exit doesn't have a variable too many arguments so make sure to come down here where it says Exit and just add underscore next weapon and we'll say that that's a string so we don't make any mistakes okay so I'm gonna add the exact same thing for weapon down so if event dot is action pressed weapon down I'm going to set weapon indicator and this time I'm going to use max so it's either going to be weapon indicator minus one or zero so we can't go below zero and then I'll call exit again and I'll pass in the exact same thing so I'm just going to copy this above and paste that in okay so now in our exit we can start working on this so I'll just delete the pass and I'll check if next weapon is not equal to current weapon dot weapon underscore name we want to make sure that we're not changing into the same weapon if animation player dot get current animation is not equal to current weapon dot deactivate you can run any other checks here this is what the exit function is for any kind of check that you want to make sure that you can actually change weapons so I'm going to check that the animation player isn't already playing the current weapon.deactivate and I'll play if that's all true I'll play the deactivate animation and I'll set the next weapon equal to the underscore next weapon which is what we passed into the function okay so how do we actually change weapons well we're going to use a signal from our animation player I find this is a good way to just control the rhythm of things and make sure that we're not spamming animations so animation finished is the name of the signal that we want to connect it's the second one down here so just double click that and then click on weapons manager and it's going to have a variable a Nim name so we want to take that variable and we want to check if it is equal to current weapon.jactivate a Nim so I'm just going to type this out now if a Nim name is equal to current weapon dot deactivate underscore Nim then oh but now okay so semicolon or colon uh change weapon and we're going to pass in a string I'm just going to type this in here weapon name have a letter string and in change weapon will pass in next weapon of course you could easily access that from the from change weapon but I just feel like this is a little bit safer now in theory we've done all our verification already so we know we can change into this weapon so change weapon can just be nice and simple I'm going to remove the pass here and current weapon is equal to weapon list square bracket weapon underscore name and that'll be it and obviously we'll clear out next weapon so that's blank some don't have any problems there and we'll call the enter function and we'll go around to the next one now that we've got that all set up we can run and do a test and as you can see when I press the one or two button I swap weapons now I shouldn't be able to swap weapons when I spam the two button if I'm trying to continuously go up it should just call up this same exact uh variable for weapon indicator and then obviously we're the same so it wouldn't work so okay so the first thing that we want to do is we're going to add some functions we're going to add function shoot and I'll just put a pass here and we're going to add function reload and I will put a pass there as well if you remember from our last tutorial we set up the inputs for these so we want if event is action pressed shoot we're going to shoot and if event dot is action pressed reload we're going to reload so if you haven't got those inputs you just go project project settings and under the input map just type shoot in there and hit add and I'm going to put that under the left Mouse button then I'll add the reload so just press add and hit that little plus button and I'm going to put mine to R okay so I'm just gonna put in these animations so I'm going to call the animationplayer.play and I'm going to pass in the current weapon dot shoot underscore Nim if you guys remember we've got these Resources with the animation stored there as variables so my variable is shoot and then if you don't have that just pass in whatever animation you want to play same exact function below there animation.play current weapon Dot reload and we'll hit play there and you can see immediately that the gun is playing that shoot animation and when you press R it is reloading which is exactly what we want so everything's working if it's not working check your animation variables I am going to set up a HUD so that we can you know keep track of what we're doing so I'm going to create a bunch of signals here signal one is weapon changed signal 2 is update the ammo and signal 3 is update the weapon stack I'm going to need to create a canvas layer here I'm going to drop that up below the parent node We'll add a couple of V boxes and but right below that we'll add age boxes and then we'll need two labels now that first label is just going to be the name of the particular field we're keeping track of so I'm not going to worry about renaming it but the second one here I am going to rename to current weapon and in that top label there I'll just type the text current weapon I'll duplicate that yeah let's rename this field to be ammo with a colon and then a space and then rename this actual label here below it with nothing in it to current ammo same thing again here let's retype the text in to be weapon stack and rename that label below it to be weapon stack and we'll create a new script on the canvas layer in the tutorial folder that's fine I'm going to call mine HUD and we're going to add all three of these nodes so at onreadyivar we've got current weapon current weapon label equals and I'm just going to drag that in you'll see you'll see the nude show up on this so I didn't notice this when I was doing it so I'm gonna have to fix that later we've got already VAR current weapon current ammo label and drag that across again I have the same problem with the new just ignore that deleted if it happens to you too and at onreadyvar current weapon stack and drag that node in as well okay so now let's connect up those three signals that we created we'll double click those and click the canvas layer okay so now we have all three signals here we are going to type some variables here we want the weapon name on weapons manager weapon changed and the function we're going to call is current weaponlabel dot set underscore text and we'll just pass in the weapon name okay so for the update weapon stack we're going to do something a little bit different we will pass in the weapon stack and we will type current weapon stack dot set text and we'll actually pass in nothing so that it gets cleared out and for I in weapon stack because it's going to be an array will be current weaponstack dot text plus equals and then we'll put in a new line and we'll add in I which will just be the name of the weapon and for the update ammo I'm going to do current ammo label Dot set text and I've got some brackets here Str is the function to change an integer to a string I'm going to pass in am I almost forgot that and that's going to be an array as well so I'll type ammo square brackets zero I'll add a slash and then I'll do plus Str ammo square brackets one so that will be our current ammo and our Reserve ammo and make sure you get your brackets right here can be a bit confusing when you're adding all these functions okay so we'll come back over to the weapon stack and we need to actually emit these signals so on initialize we want to update the weapon stack and we need to pass the weapon stack to the HUD and when we enter we are going to emit the signal weapon changed with the current weapon.weapon underscore name and we'll also need to update the ammo because we've changed weapons and that will need to be an array current weapon.current ammo comma current weapon dot Reserve ammo okay so here they are these two variables in my resource if you're not using these resources then you'll just need to pass in whatever variable you're using obviously this is going to crash because of those new functions that appeared when I started dragging these in I'm just going to remove them delete them out and rerun the game and there we go we can see it says Blaster D ammo 30 of 60 and the weapon stack which is the two weapons we have in our possession Blaster D and Blaster n and when I change the IMO is updated and the weapon name is updated okay so now we can start setting up the math for the shoot and reload we're going to come to the shoot function and we'll just add our first condition and type if current weapon dot current ammo is not equal to zero colon and then we'll drop down and we're actually going to add a second condition after this we could of course do this in one but I prefer or I feel like it's more readable to have it as two in this instance you guys can do whatever you like I'm going to type if not animation player is playing so we don't want to shoot when the animation player is already playing in other words we can't interrupt an internet animation to shoot so this will also enforce the fire rate set by the animation and then I'll have my animation player dot play and we'll also need to reduce our ammo so we'll have current weapon dot current ammo minus equals one and we'll emit the signal update ammo and I'm just going to come back up to the enter function and just copy that in because it is quite long alrighty so let's hit that play and you can see that now our ammo is reducing and our animation player is playing when we reach zero nothing happens the other thing we might want to set up is autofire come to the signal for the animation player animation finished and I'm going to type if an M name is equal to current weapon don't shoot a Nim and current weapon.autofire so you'll remember in our resources we have an auto fire variable make sure that's equal to true and then we're going to check if input dot is action pressed and that's shoot and then if that's true we're also we're going to play the shoot animation as the animation finishes if the autofire is set to True we'll run the function again so as you can see that's working as I hold down the fire button that animation for the Blaster D is playing on repeat okay so now what do we do if we run out of ammo we need to reload so I'm going to type else reload and I'll come down to reload okay right now we're just playing the animation so we need to do a few more things let's have a look we've got Reserve ammo we've got magazine and those are the two variables that I'm going to be playing with in my resource so I'm going to check if current weapon dot current ammo is equal to current weapon and Dot magazine that is to say that we don't need any ammo I'm just going to return out of this nothing's going to happen if you have full ammo and then I'm going to check that if the animation player is not playing I don't want to do this if we're in the middle of something I can't interrupt to reload and that's mostly a design Choice doesn't have to be that way and then I'm also going to have another condition after this and it's going to be if current weapon dot Reserve ammo is not equal to zero we can't reload if we don't have any ammo then I will reload okay so that's all the conditions that we need okay so this is how we're going to do it we're going to type VAR reload amount is equal to and we'll use the Min again I'm going to make this little white axis it's going to be pretty long I type Min and this can take any number of variables so we're going to type all of them here so it's going to be current weapon dot magazine minus current weapon Dot current ammo so think of that as if we have a magazine of 10 and we currently have three in our current ammo the number there would be seven which is the amount of ammo we need to fill up our current ammo to our magazine level okay the next one is going to be the current weapon dot magazine which would be in my example before 10 and the third one will be current weapon dot Reserve ammo so it's going to be the smaller of these three numbers in most circumstances it's either going to be the lesser of those three so if you don't have enough ammo to top your current ammo up to full then you're going to just take the reserve ammo amount if you are at zero then you know current weapon dot magazine minus currentweven dot current ammo might be the same as current weapon dot magazine now that I think about it so you could probably just do the two either way it's always going to take the lesser of those three situations anyway okay so what we want to do with this is we're going to type current weapon dot current ammo and I'm going to go equals current weapon dot current ammo I would like this to be written out here just so it's clear what I'm doing current weapon dot current ammo plus reload amount and current weapon.reserve ammo equals current weapon dot Reserve ammo minus reload amount okay and lastly we want to emit that signal for update ammo and the else condition will be else we will want to play the current weapon dot out of ammo animation so that's the animation I have stored in my out of Animation variable in my resource okay so let's test this out I'm just going to empty the clip on this one and it should reload 30 and my Reserve animal is 30 and I'm just going to do a couple of different tests to make sure we're happy with the number that's always coming out so 25 I need five yep okay I need 10 yep okay that makes sense and I'll reduce it all the way down to 10 I should go up to 20 and I do and now I don't have any ammo what happens then the out of Animation animation plays and same when I get to the end I'll test this one out too just to make sure and it looks like it's reloading normally okay so that is how you set up the reload the shoot and reload animations and all the math that goes along with tracking the ammo uh and the next one we're going to be looking at the hit scan so we're going to actually start to be able to shoot our gun I guess you would say I'm going to be able to deal damage um one last thing that I wanted to do before I left this one was just add a site because we don't have one so you don't really know where you're shooting so I'm going to hit that plus and add a texture rack to the canvas layer and I'm just going to call that main site and I've got something in the models under HUD assets called Crosshair one I am going to click the little anchor up the top when I have the main site selected and select a full rect and drag that texture over to the texture slot on this texture racked you'll notice that it's very stretched what we want to do is change the stretch mode to keep centered and just make sure that anchor is selected and now you'll see when I run it is in the center okay so that is how you set up the shoot and reload in Godot that's just the animation and a you know a quick and dirty little HUD to keep track of it all finger dough for there's something called a physics Ray query parameter 3D I think that's the right term and you can use that to create a raycast from wherever you want to wherever you want and what we are going to do is we're going to raycast from the center of the camera out to a determined range and if that Ray intersects with something we are going to do another raycast from the barrel of our weapon to that object this is an extra step just to give us a little bit more accuracy so that if there's something in between the barrel like a box you're hiding behind some kind of object you can't just you know peek out of it and shoot you could of course just raycast directly from the center of the camera and get pretty similar effects of course and that is not what we want to achieve here so we're going to do two Recaps and let's get into it so the very first thing that we need to add is a marker 3D it could be also a node 3D that's fine too I'm going to call this a bullet underscore point and the trick here is with the animations we're going to move that bullet point to be right at the barrel end of the gun so I'm just going to manipulate that into the right position for all my weapons and just key that frame in on my animation player so you'll see I've put that there and I hit the key button on my blast to deactivate so when the gun's activated that marker moved in into position and for the deactivate I also I'll hit the reset and kid in this is not super necessary but I just I think it's just a little bit better that way just in case there's any issues I'll come down to Blaster I and I'll do the exact same thing I'm going to speed through this but yeah for every single one of your weapons you want to move this bullet point in front of the barrel where you where the bullet would come out of essentially and we're going to use this for both our head skins and projectiles okay so after you've set up your animations right click the bullet point and select access is your unique name we'll come into our weapons manager script and we'll type on radio our bullet underscore Point equals get node brackets quotation marks and then then the percentage sign and then bullet point uh the reason I do it this way is just in case you want to move things around after you're done makes it really easy okay so we'll come into our weapons resources script and we're going to add a couple of variables first thing we want is an export flag so let's export underscore flags and we'll do one as hit scan and the other as projectile and we'll call it type so this is a really cool thing it'll give us an enumerator that we can use to decide what kind of gun we're shooting the next export variable is weapon range and that'll just be an integer it's pretty straightforward what that'll do and then we'll have X4 VAR damage as an integer as well and so we'll come and set these up I'll make this one here Blaster d a headscan weapon and the same with Blaster I and I'll give them all 2000 Range for now uh we'll come back to our weapon script and we'll create an enumerator it'll be between three we'll do null hit scan and projectile and I think you can probably see where I'm going with this okay so in our shoot function we're going to type match current weapon DOT type and we'll have null just in case it's not been selected I'm just going to put a print here and say something like weapon type not chosen and then hit scan and we'll put pass for now and then we'll also put projectile and we'll do the exact same thing we'll just pass there the first thing we need to do before we actually start doing a hit scan is we're going to need to get array cast from our camera so I'm going to create a function called get camera Collision and we'll start working on this we're going to just type pass so that I can set up the rest of the function and shoot so I'll type VAR camera Collision equals get camera Collision and so for the camera Collision we need to get access to our camera so we can just go far camera equals get viewport get camera 3D and it's going to return the active 3D camera which is going to be the one that we're using in most cases and then we also need to know the size of the viewport so we can project the raycast from the center so we'll get viewport dot get size is the function we're going to use and we're going to have Ray origin equals camera dot project Ray origin and it's going to be a screen point which will be our viewport divided by two so that'll be the center okay and the other one will need to be Ray end and this will be Ray origin glass camera projector normal and it'll be the viewport divided by two which will be the center again multiplied by the current weapon dot weapon underscore range so that's how far we're going to project our raycast so we'll have the next variable which will be a new intersection and that'll be equal to physics Ray query parameter 3D Dot create and we'll take a from Vector which will be our rate origin a two Vector which will be our rate end this is new and good o4 I'll just make some space down below and make this a bit wider so that's a new function we need to call when we're raycasting so the next thing we need to do is just get a variable for the intersection and that will be equal to getworld3d.directspacestate dot intersect Ray and this now takes a physics rayquery parameter 3D so I'll pass in our new intersection and then what we'll do after that is if not intersection dot is empty and we'll get the Collision point it'll be equal to intersection dot position so that'll be the world point of the actual collision and we'll return that else we'll just return the ray in this is not important for the head scan but it will be important for the projectile so keep that in mind so no matter what we're returning a vector 3 and it's either going to be the point that we hit with our camera or just the end point okay so we can come back up to our shoot and now that we've got that point we can start working on our head scan so we've got the function hit scan collision and I'll just type pause in there it's actually going to take a variable which will be the Collision point from the camera Collision function bullet underscore direction is equal to Collision Point minus bullet point dot get Global transform dot origin and Dot normalized and so that'll give us the direction that the this new Vector should be traveling and we'll type our new intersection this will be pretty similar to the one above and that'll be equal to the same as before physics Ray query parameter 3D Dot create and the from point will be the bullet point dot get Global transform dot origin and the two point will be the Collision point plus the bullet Direction times two now you give it a little bit of extra the multiplication of two is pretty much to just push it a little bit further than what you would need because what I found is if you don't do that this head scan Collision doesn't always register a hit okay so we'll come down with VAR bullet underscore collision and we'll get well 3D dot directspacestate dot intersect Ray which takes a physics rayquery parameter 3D and we'll pass in that new intersection and now we'll know if we've actually heard something say we'll go if bullet Collision print hit scan damage and so we'll just print that out we know we can deal damage at that point so I'll create a function called Hit scan damage and we'll just set it to pass at the moment and we'll set this function up call that function under if both Collision just so that it's more complete this is the exact structure we want okay I'm going to toggle out of this and we'll come back to the world go back to 3D we'll bring the editor back and I figure that the Box will be the best thing to work on so let's interact with that so I'm going to add a group so if you come over to node where signals are and just click the little icon that says groups click manage groups and type Target in this box here and add select the physics object and add and then press OK and let's add a script under tutorial I'll create a new folder called World underscore objects and I'll call the script physics Target and under here I'm just going to say bar health we'll just give it like five and then we'll create a function called Hit underscore successful yes try to spell that right hit successful and we'll pass in the damage and then we'll just go Health minus equals damage this is just a simple one and then we'll check the health if it's less than or equal to zero then we'll keyframe nice and simple we'll also print the health as we go just so that we can keep track of make sure that's working okay we'll come back over to the FPS character and under here where we've got our head scan we'll pass in the collider which is one of the objects returned from intersect Ray so bulletcollision dot Collider so we'll type if collider is in group and we'll just type Target and the collider dot has method and we'll type that method out before it was hit underscore successful it's important to make sure that's correct otherwise this won't work it's also important to make sure that you do this just in case you don't have that function on the object you're hitting otherwise your game will crash um and we'll just type collider dot hit successful and we'll pass in the current weapon dot damage cool okay so everything should go to plan we just need to make sure that we come up to this match in the shoot and actually call that hit scan Collision function and pass in the camera Collision after that we should be good to go just once check over this yep I think we're ready let's run the game okay oh we gotta crash oh yeah okay so health is uh int and I've been writing too much JavaScript so I just need to type Str F Health okay and then you can see it's gone and that's working so that's how you set up a hip scan weapon awesome and it's not interacting with anything else okay so that's pretty cool but we can't always see where we're shooting so it'd be nice to do that so let's come back over to our project and we'll just create a new scene and we'll make it a Sprite 3D this is just going to be a simple bullet point bullet we'll call it a bullet underscore debug and under harder assets I've got a Crosshair that'll do just fine x marks display if you know what I mean and I'll just make it red I'm also going to come over to the flags and for billboard I'm just going to put wide Billboards so that's always facing the camera and I'll save that under weapon resources not really much to it I will create a script and also I'll add a timer and I'll put the timer just one second's fine connect signal timeout to the script and once that timer times out I'll queue free all right cool and I will add that scene as a variable here I'll type VAR debug underscore bullet and I'll preload and I'll drag that scene over debug bullet just drop that in there like so and I'm actually going to take those out of the weapon resource folder because that's where we keep all the uh okay cool I've moved those just to make it a little bit Anita in my project so I'll just have to reset that preload so every time you move this file you're gonna have to re relink that up and drag that back over so it says tutorial bullet debug okay so now we need to instantiate that probably if there's a collision I'll type R hit underscore indicator equals equals debug bullet Dot instantiate I'll type VAR World equals get tree dot get root and I'll just add the child hit indicator and I'll set the transform so hit indicator.globaltranslate and it'll just go bullet collision.position so that'll show up at the position of the Collision there you can see it and they're not disappearing I suspect that's because I forgot to set that to auto start and they'll start disappearing so now you'll always be able to see where that head scan is going that'll just help as you're building your game out you just replace that with a decal when you're ready and you'll notice where it's showing up in the tree I I don't know if I'm a huge fan of dropping it in the root maybe we could move it to the World um it probably doesn't matter that much but I'll come back over to the FPS character and where we're instantiating that where it says get tree dot get root I'll just get child and I'll just type zero there which will be the first node which is going to be the scene that you're in you know the level in most cases depends if your game's more complex but if your game's more complex I suspect you don't need this tutorial so and now you'll see it just shows up in the world um probably not that important but I just thought it might be important to point out that you know to think about these things when you're just instantiating stuff okay that's it we've done it hit scan weapons we'll do projectiles next and now we've set up our camera Collision we've got our head scan done let's come in and set up the projectile we just need to create a function but first let's jump into the weapon resource and create some variables because if we're doing a projectile we need to spawn something so I'm just going to move this export flag down and below this we're going to create a new variable at export bar and we're just going to call it projectile to load and that's going to be a packed scene so this will be the scene that we instantiate when we create a projectile weapon next we're going to create the projectile velocity this will be how fast the projectile goes if you're creating perhaps a rocket launcher you want it to go a little slower but if it's a bullet maybe it needs to go a little quicker okay I'm gonna choose one of my weapons I'm feeling Blaster n I'll come in with Blaster n and I'll change it to a projectile so make sure at least one of your weapons is marked as projectile so now we've got hit scan on our assault rifle but on our other weapon there's nothing happening so let's come in and set that up let's create first a projectile velocity I'll just choose 100 to begin with and we need to create a projectile so I'm going to use one of Kenny's foam bullets probably this one here phone bullet a so I'm going to create a new scene and I'm going to click other node and I'm going to grab a rigidbody 3D and I'm going to rename it to Bullet and I'm going to drag that model in and make local and then just get rid of the all the other nodes and keep the mesh I'll need to reset the transform on that so I'll just do that quickly and I'll just rotate it so that it's horizontal on the z-axis that's pretty important for a bullet I'll save that scene under our tutorial folder now I'm just going to bring in the gun model just so I can see you know how this is going to look in comparison if I need to make any changes to it and I think I am going to make it a little bit bigger so we can look it is the right size but I think it could be bigger so I'm gonna so I'm going to make it a little bit bigger I'm going to delete that gun and reset the transforms now I'm going to play around with the material you guys don't need to do this but I think because it's a laser you know it's going to be emissive and so I'm just going to set up an emission make it super bright just because it looks cool nothing really no other reason okay you can choose multiply but it doesn't really look that good so add is what you want to keep for the operator and we need to create a rigid body now I'm going to create a capsule shape and I'm just going to obviously rotate it and we're going to need to make it uh substantially smaller the trick with rigid bodies uh turn off snapping here is that you want them to be a little bit bigger than the projectile that you're actually shooting because I don't really know with Godot 4 if the physics is worse in Godot 3.5 you couldn't really use projectile weapons for like Fast shooting weapons you could really only use them for like rocket launchers and things like that because the physics engine could not detect the collisions 100 of the time and you have to you know do a lot of like trickery to get it to work but at least in my testing with Godot 4 it seems to be significantly more reliable with the new physics engine so I'm going to go ahead and set this up and you shouldn't really have any issues but if you are having problems it could just be engine related just keep that in mind I guess I'm going to select continuous CD on the rigid body and I'm going to set the number of contacts to 10 and select contact monitor this will allow it to detect collisions I'm going to reduce the mass to point one and I'm going to create a script okay so the first variable is obviously the damage um we're just going to set that up as an integer and it's going to be zero but we'll work on that I'll explain that in a second and we'll connect the signal up body entered to this script and we'll go if body dot is in group brackets Target this is a group we set up in our previous tutorial on hit scans and the body has method brackets hit successful so those two things are required here so if you don't have a group set it up now and you'll need a method on the thing you're trying to shoot called Hit successful and we'll call that function if both of those are true and we'll pass in the damage and we'll cue free and then we're going to queue free regardless you could just put that on the outside of the if statement as well I'll also create a timer just in case we don't hit anything and this goes flying off into nowhere we'll just delete it after a certain amount of time okay that should be all we need we can close up these folders make things a bit neater we can jump back over into our blaster resource and we're going to drag that projectile to load into that resource there so that we have that on file we can come back over to the weapons manager now and we can start setting up our projectile method so we've got our camera Collision this is an important function if you don't have this you definitely need it um we are I'm going to be returning the Collision point or the end of the ray so we're going to always have a place to send our projectile so that's why we need to return the Right End just in case you shoot into nowhere so under projectile I'm going to create a function called launch projectile and I'll pass in the camera Collision I'll create this function down here function launch projectile and I'll it will take a variable called point the first variable that we need is the direction and that is going to be the point minus the bullet point and get Global transform dot origin and we're going to normalize it this would be pretty familiar if you've done the hit scan next we're going to need to instantiate the projectile so I'll create a variable called projectile and I'll say current weapon.projectile to load Dot instantiate and I've just realized that I've made a spelling error so I'll come up and fix that next we are going to need to instantiate this bullet so just make sure that the bullet is set as top level for this because we're going to instantiate it under the bullet point which is a part of the kinematic body so under bullet point dot ADD child we're going to add the projectile and the projectile dot damage we will set to current weapon dot damage and then projectile set linear velocity and that'll be the direction multiplied by the current weapon.projectile velocity so just make sure that the bullet is set as top level for this so that's super important we also need to set up the collisions layers I haven't explained these yet but one thing I've noticed is that with Godot 4 the physics bodies do need to be on a separate layer so they weren't working for me when I originally set this scene up and so now I've created a physics layer called objects on layer three and layer four is the weapons so make sure you set your projectile to have the same Collision layers as well we're going to put it on the third layer and we're going to have it mask layer 3 and layer one so it's going to interact with anything on the world layer and keep in mind with your enemies if they are on a separate physics layer to make sure to select that mask here for your projectile so here's the box it is on layer three and it's masking one two and three so it can interact with anything on those three layers let's run the game here we'll swap over to the weapon that is a projectile and you can see it is spawning those projectiles and shooting them and then we'll shoot the box and you can see it rolled it's definitely hitting it and you can see below in the console that the target health is being reduced so that is working how we've expected it to which is really amazing it is just that easy okay guys it's Isaac from the future here to interrupt this projectile tutorial um I filmed a slight bug in the code I don't know if anyone would have picked up on it or even noticed to be honest because it's just something that you that can happen um but you might not depending on how you've set things up so you won't see it actually in the video but I did notice that when I was playing around with like a big projectile that you're shooting and you're shooting it rapidly something that happens I'll play this here I've made a couple of changes to this project it's been a long time since I recorded that original um but here's the gun and this is a projectile so it's quite a bit bigger and this has been changed to automatic so if I hold this down Watch What Happens look at these last two they start going off in a completely different direction now you might wonder why maybe you've already worked it out but it is basically the raycast from the center of the camera interacting with the actual projector rather than going through that and hitting the thing behind it so that will change the trajectory of the projectile because the the direction that we send it would be just based on that reduced distance right so the Bullet is much closer to the player than the wall is over there and so it's just going to go in a completely different direction and it won't line up with the ridicule in the center of the screen so it's going to be pretty noticeable you can tell it veers off like that which is pretty weird so I'm going to quickly show you guys how to fix that I'll jump back over into the project things are going to look a little bit different but you just have to bear with me um we have got our camera Collision and then we've also got our launch projectile so the flow of the code is essentially if I come back up to shoot you can see that I'm getting the camera Collision which is we're shooting array cast from the camera to wherever if it's hitting a wall it's coming back it's not anything it's just coming back with the file this point away and then we're passing that to the launch projectile and we're throwing that from the bullet points that's the like the muzzle of the gun is where that projectile comes out and it goes towards that end point wherever it's collided with and generally that's meant to be at where the center of the camera is so that's why it hits that ridicule but obviously if it's hitting the uh the bullet that's like not where we want it to go and so it's not going to line up and it's going to look weird so what we need to do is we need to add an exclusion to this physics Ray query parameter 3D and it's got a exclude and we can set exclude and we can pass the value it takes an rid so we need two things right we need to get the rid from the bullet which is not that complicated what we can do is we can set up an array um I'll do it underneath this enumerator here so I'll go over Collision underscore exclusion and I'll set this equal to just like a blank array you know that's not what I want there we go and I'll come back down to the launch projectile and what I will do is after we've added the child actually after we've instantiated really we can do it we can get the projectile we'll create a variable called VAR projectile underscore rid which will be equal to projectile dot get RIT this is just a built-in function for any Collision object um and then we will just go Collision explosion dot push front doesn't really matter um projectile our idea I actually think pushback is faster uh we're not going to store that many so now that we've got that being added to an array what we can do is we can come back up to the physics rate query parameter 3D and right after we create it we can just write new intersection dot um set exclude I think that was set exclude and it takes an array and we'll pass in that Collision exclusion and now that won't happen anymore so let's run the game switch to our gun and you can see that it's going straight ahead perfectly anytime now we've got a new problem the new problem is we're creating an array of rids and it's ever growing and I've stress tested this and you can get to about 5 000 before the gang will crash so we need to remove these as they are removed from the scene so we need to right after we have created the projectile and we've added it to this exclusion array we need to also hook up the tree exited signal of the bullet to the weapon manager this is the bullet node and under signals we've got tree exited so this is emitted after the node exits the tree and is no longer active Okay so like I said we need to hook up that tree exited signal so we'll also need to set a funk and we'll go remove underscore exclusion and this will take a projectile underscore rid and then um all we'll do for this I'll write this code down we'll go to Collision exclusion dot erase and then we'll pass in that projectile rid and I'll also spell that right put an alien or three like balance okay and just set that up like that so that's what we need for the exclusion now we just need to link that up with a signal now signals have changed a lot in Godot for um and one thing I was learning as I was doing this is that you can just uh call directly a signal so it needs to look like this so we can go um projectile dot tree underscore exited Dot connect and then brackets and then it just needs to be remove exclusion dot bind and then in this I can pass the projectile rid but I think it should be projectile dot get RIT so you can see off to the right here I'm creating that and you can see it grows as as I move further back um it's kind of hard I wonder if I just like send these out it's probably the best way to do it because they Spire after 10 seconds and they'll just delete themselves so you can see it grow up to 21. and as they delete themselves they should get reduced and you can see them going down like so and so that in my opinion is the best way to solve this issue that I showed you before where it's not going directly to the center um what we need to do just to recap is to get the projectiles rid and add that to an exclusion list for our physics Ray query parameter up here in the camera Collision um you add that to the exclusion of that and it won't actually the raycast from that won't detect the bullets which is exactly what we want but also we need to remove those from that array as time goes on because uh an irrational that gets so big before the game crashes as I've discovered um might be obvious to some people I don't know surprise me um and yeah so you just you you hook up the signal like this projectile.tree exited dot connect remove exclusion.bot and projectile.get Rit it messes with the head a bit this new signal thing but anyway that's how you do it if we run the game as it is you can see our head scan weapons don't do anything but our projectiles certainly do okay so how do we go about fixing this well if we jump into our box we can see that we've got a simple hit successful function that takes the damage and applies it to the box if it reaches zero then we call Q3 and it disappears from the scene the function that is controlling that at the moment in the hit scan branch of our weapon system is a function called Hit scan damage that gets called after a collision is detected by our head scan Collision function and right now we're just passing in the collider and we're checking that if it's in a group called Target and it's got the function called Hit successful we're going to call that function and pass in the damage so not a lot to go off but we can use some of the information from our Collision to work out the direction it should be moving so we need to pass in a couple of extra parameters and we'll name them here we'll call One Direction and the other we'll call position okay and I'll just come back up to where we're calling that function and I'll write bullet Direction we've already got that at the very start of this function we've got bullet Direction equals the Collision Point minus the bullet point.globaltransform.origin normalized so that is the direction of our head scan so that's essentially where the bullet is coming from if there was a bullet and the next thing we need is position now we can get this from the bullet Collision bulletcollision dot position this is a field that's returned from the getworld 3D dot directspacestate dot intersect Ray function it's something that is returned when that collides with something and it's the world position we'll jump into that function here and you can see that is the intersection point so that is where that position is in the world space and we can use that to determine the position of our Target now if we come back into here passing in both of those and what we need to do as well where we're passing in collider.hit successful we also want to pass in the direction and the position all right now we just need to jump back over into the box and update the hit successful function here here's a little trick for you I'm going to write underscore Direction colon equals vector3 dot zero and what that will do is actually make these parameters optional so that we can still use it with our rigid body projectiles that we're firing and we can reuse this function on other targets that might not need this information and the next one that we need to call is obviously position and we'll do the exact same thing underscore position colon equals Vector 3.0 okay so we'll do a quick run of the game here and just to show you that we haven't changed anything we're passing in those functions and our shooting in this game hasn't changed at all so everything is still working those are all optional parameters our projectile is just passing in the damage and then is going to be zero so we can come down here and we'll need to create a new variable called Hit underscore position and this will be a little bit of math here to work out the position of the actual hit and it'll be equal to underscore position minus get Global transform dot origin and we'll come down at the bottom of this function and we'll say if underscore direction is not equal to Vector 3.0 so we're just going to only run this if the if there is information being passed in otherwise we're not going to do this and we'll call the function apply impulse and this will do exactly what it says on the tin really it's going to apply an Impulse which is a force at the position and so our impulse is going to be or at least the way I like to do it so that it sort of scales with the power of the weapon we're going to call Direction and we're going to multiply that by damage now the reason that the impulse is going to be in the direction is because we want that impulse to be in the direction of the bullet so essentially that's why it is direction for the impulse am I multiplying that by damage to sort of give it a little bit more oomph depending on the weapon or whatever it is and then the next is going to be the position which we calculated at hit position so I'll pass that in and that's all we need to do we can run the game okay so you can see now that the box is reacting to the hit scan weapon and it's disappeared might add some health while we play around with this just so it's a little bit easier okay you can see me lay into this it doesn't matter where I shoot it it seems to react in a sensible way which is exactly what we want and you can see if I shoot it with the projector weapon obviously there's a lot more force behind that but this is something you can tweak you can change the mass of the bullet to sort of give it less force and so we can jump back into our project and do that so that it feels similar depending on the gun it's just going to depend on what you're trying to do and how you want things to react but you know that's the function you need to do I'm not sure if it's 100 physically accurate but it's good enough and it's easy enough to implement right and since we're you know shooting this rigid body I thought it was a good time to show you so we can come back to the bullet and we can reduce that Mass from 0.1 kg to 0.01 so it's a very light bullet and we can rerun that and then okay that feels pretty comparable I would say to what the head skin done is a little bit more but I don't think people would really notice that much so now you can shoot rigid bodies with both weapons and they react the same which is pretty cool now while we're here I think we should just add in a static body so I like this particular mesh called Target B and I'll come back into the project and I'll create a new Scene by clicking on this plus I'll press other node and I'll search for static body 3D and I'll drag that model into the scene I'm going to right click and make local get rid of all these extra nodes and delete them and then I'll click on the target I'm going to be a little bit lazy here and just go mesh single convex Collision assembling this isn't the most efficient way to create a collision shape but it certainly is easy now save this here in the tutorial folder now just call it something like Target I'll reset the position because everything is a little bit off so I'll just change that make sure it's on zero and I'll rename this static body to be something like Target okay so we'll create a script next and we'll save it in the tutorial folder and we'll call it something like static underscore Target and we'll create that and we can pretty much just copy the code from our rigid body I'll just copy this first bit we don't need as much because obviously it's not going to react to the direction of position but we do need it because it's getting passed in from the player so we'll bring that over copy it and I'll just enter down here and I'll paste this in and right below this I'm just going to write pass for a second and I'll create a variable called Health like before except this time it's just going to have one and under hit success it'll pretty much be what we started with with the Box we are going to subtract the health say health minus equals damage and if health is less than or equal to zero then we will keyframe nice and simple that's all we need but we do need to pass in those two optional variables just to keep our player character happy if we don't do that this will crash so I'll add a note to the scene and I'll just call it static targets and I'll navigate to that folder and I'll just add that to the scene okay I'm going to drag it over to this wall over here just so that we have something to shoot at okay it's nice in position on the wall I'll raise it up a little bit and I'll just duplicate that a few times so that we've got something to shoot at I might skip this section because it's uh kind of boring okay and before I forget we do need to add this static body to our group called Target so I'll open that scene again and I'll come over to the node tab on the right hand side where it says inspector node history I'll click node and I'll click groups here and I'll click manage groups I'll type Target add click the static body click add click OK and that's all we need to do just save that scene make sure it's the same as the one for the Box you can have multiple groups if you want and you could be calling different functions on those as well that's totally fine if you want to do it this way I'm just running them both in the same group and having the exact same function be called all right so we have a look at these and you can see that they're getting deleted successfully right so that's how you add in physics reactions it's how I like to do my static bodies as well just a nice simple way of dealing with targets having a single function that's being called and the two variables that aren't required all the time be optional okay so if we want to be able to pick up our three weapons then we need to create rigid bodies for all three of them so I'll create a new scene here and I'm just going to navigate to where the models are and I'll click other node and it's going to be a rigid body so I'll search for that and select it I'll rename this to the name of the weapon that I'm creating so for this one it's going to be Blaster M I'll drag that model in I'll make it local and I'll just delete these empties like you've seen me do a bunch of times before I'll also reset the transform on this let's come down transform just reset that so it's in the center and the easiest thing to do to create a collision shape is just click this button here where it says mesh I'm going to go with single convex Collision it's a pretty good in between shape and as you can see I've got a collision shape that pretty closely conforms to the shape of the weapon and I'll save this I'll create a new folder and I'll call it spawnable weapons and I'll hit save on that scene there okay so I'm going to do the same thing for the other two weapons I'll Spade through this okay so I've got my three rigid bodies all set up and now we can add a script to this so I hit this little script button and I'll actually call the script something like weapon pickup because we're going to use this in all three and I'll type export VAR weapon name and that is going to mirror exactly the name of the weapon on the resource so we'll just make that an export variable so we don't need to name it here and the next one will be the current ammo so this would be the ammo that sits on the weapon when you pick it up or drop it and the third variable will be Reserve ammo as well you could have one variable for ammo but I think it's just a little bit easier to have too to be honest but it's it's really just a design option at this point so we'll drag that script onto all three of these and we'll also name these weapons so just make sure that they're the same as your resource you come back over to this if I click on the weapon manager and I've got all three of these weapon name blaster uh this is lowercase and then capital so I needed to just make sure that they're exactly the same otherwise this what I'm going to do is not going to work um and you want to make the current ammo and the reserve ammo something reasonable it's really up to you how you want it to look this is going to start to change a lot when you program the ability to drop these weapons because it'll need to be whatever the ammo is at that time and so I'm just checking to make sure that these three weapons that I'm going to create have got um just the Standard current ammo and Reserve ammo that I've set up on the resource so that they're exactly the same but they can really be anything you want okay so now that that's done we'll need to also just double check physics layers so if you don't remember we've got a set of physics layers that we've set up we've got World Player object and weapons now layer 4 for us is going to be where we put the weapons so I'll come down to Collision object 3D and I'll select layer 4 and I'll unselect layer one and I'll leave one masked and I'll mask for as well for good measure and I'll also mask three for objects just in case you drop a weapon onto an object and you want it to interact so do the same with all three weapons you could also mask the player as well like if you wanted to walk through the weapons and you wanted them to move around and interact like that but uh in my sort of testing I found that that wasn't a very nice experience for the player especially if you're trying to pick up weapons and the Collision shape is moving things around okay so now that that's done we'll come back over to the FPS character and we'll click the little plus button and we'll add an area 3D node to the FPS character and we'll also need to add a collision shape but first I'll rename that to pick up detection and I'll add a collision shape 3D to that I'm just going to make this a box and I'm going to make it sort of I'll bring it up to be the same size as the player so you can't pick things up below the ground realistically this is just going to be something that you decide you know what works best for your game I'm going to make this a little bit wider on both axises just so that there's plenty of room so that the player doesn't have any problems picking up weapons don't have to get too close to them okay all right so of course we need to also set up the Collision on the area so I'll click the pick up detection node and I'll come to the collision and I'll unselect world and unselect the mask and we just want to mask player four so that way it'll detect things on layer four which is where our weapons will be I'll connect the signal so I'll click node and I'll click signal body entered and I'll double click on the weapon manager node okay so I'll just remove some space here and on this we are going to need to set up a few things so we know the variable is going to be weapon name so I'm going to print that out just to show you guys make sure that everything we've set up so far is working just absolutely make sure that this variable is the same I'm not adding any kind of checks here so the assumption is that it definitely exists on the object we're going to detect it's not the safest but it will work if we do things properly I'll jump back over to the main scene that we're working on and I'll add a new node here and I'm just going to call it weapons and I'll drag those three spawnable weapons that we created into that node I'll select them all I just bring them up so that they're inside the sort of play area that I've created here and I'll just move them apart from each other so that they're there on their own I'll give them a little bit of space so we don't run over to at the same time now just run this game and we'll see that as we walk over the top of them well actually you can't see because this the game's the way so I'll just Tab out of that you can see Blaster eye and as I walk over these they print out the name so just make sure that everything's working up to this point um and you know everything looks good nothing's crashing okay so now that we can detect our weapons we can come back over to the weapon manager and we can start adding some logic here so first thing I want to do is create a variable called weaponin stack I'm going to make that equal to weaponstack dot find and I'll just type in there body dot weapon name what this will do is just first check that we don't already have the weapon in our possession so this will return a negative one if it's not in this stack if you guys don't remember what the stack is it is just a list of weapons that the player currently has in their possession so if it's not in that it is going to return to negative 1 and that will tell us that we need to pick up the weapon okay so the other thing we need to remember is exactly how our state machine works so we need to eventually call the exit function and pass in a string to the next weapon now there the way that these rigid bodies are set up is that they have a string reference to the weapon so obviously this is fairly early stages we don't have the ability to drop we don't have the ability to pick up ammo from that from weapons on the ground so we'll call exit which will just handle everything for us so I thought if weapon in stack is equal to negative one then we need to pick up the weapon and I'll come down here and the first thing we need to do is actually add that weapon to our weapon stack so I'll type weaponstack.pushfront and I'll push that value body dot weapon name okay so now that the weapon is in the stack we're able to switch to it and we'll also be able to switch back to it if we switch off it we need to zero out the ammo in the resource resources are exclusive you generally don't have multiple copies of them so the resources are always there it's just we're controlling whether or not we have access to them with the weapon stack and so what we need to do when we pick up a weapon is actually override the ammo and the reserve ammo with the values from the gun on the ground so that's why the gun on the ground has those values and so what's that that's what we'll do here so we'll type weapon list and we'll do square brackets and I'll just paste in body dot weapon name because it's a little bit faster and I'll type dot current ammo and I'll set that equal to the body dot current ammo okay I'll just copy that because it's a little bit easier and I'll paste that down and I'll just change current ammo to reserve ammo and I'll do the same thing for the body.current ammo I'll change that to body.reserve ammo with lowercase this time okay so we're going to override those values and we're going to also emit the signal update weapon stack and we'll pass in the weapon stack and then finally we want to type exit body dot weapon name and we should be good to go last thing we need to do is of course delete the rigid body because we've picked it up okay so let's run that and see how we go so the only weapon that we can pick up is this one on the left here I'll walk over to it and it looks like it's picked it up okay and these ones here obviously don't get picked up because they already exist and I'm not updating the weapon indicator which is what controls our position in the array called weapon stack and so when you pick up a weapon and then you switch it won't always be the weapon that you're expecting so if we switch to the second weapon the stack would pick it up the next time we switch it's going to be there so you would expect to go back to Blaster n but you actually ended up on Blaster I I think it's called so we can fix that um we're not going to fully fix it until we start to drop weapons as well so we've got just a regular int controlling our position in the weapon stack to be honest I think this can be improved and we might do that next episode when we fully fleshed out how this works so one option that we have is that we can make the weapon indicator zero so that will always just count up from there and because that's when we pushed it to the front it's going to work pretty much off the bat this is a really simple solution but depends on how many weapons you've got in the game that might be really annoying for the player so instead what we can do is we can type insert and we'll needbody.weapon name and a variant which will just be weapon indicator and we can delete that and that's actually rather away so I'm just going to swap that out this will be our final solution weaponstack dot insert brackets weapon indicator comma body dot weapon name so what we're going to do here is just insert the weapon at the position that we're at in the weapon indicator right now and that'll sort of you know if we're on the second weapon we're going to put it at the third position and it just feels a little bit more natural rather than resetting the entire weapon stack and like I said we'll fix this up at the end of the drop tutorial so don't worry too much about this so I run this just to show you how it looks so we'll switch to blaster in and you can see now that it shows up in between the two and so when you switch up it's Blaster n and when you switch down is where you expect it to be so I think this is the best mission um there are currently No Limits to how many weapons you can pick up in this game and we're not going to change that um but yeah so I think it's worth the best definitely comment down below if you've got a bad way of doing it because I sort of wrap my brain over this for a couple months and so in our current state we've got a lot of things up and running and we're almost done but we can pick up weapons however we can't drop them and you know in some games you might not want to drop them but um I'm going to show you guys how to do it if you need to I'm going to add it into this FPS weapon manager which is for fun and we're going to fix up a few things along the way so the first thing we need to do is add an input so I'll come up to the project settings and I'll click project settings and then I'll come across to the input map and I'll type in drop and I'll click add here and I'm going to make this the letter G pretty sure that's a common input um and I'll come to the FPS weapon manager script and I'm going to create a new function right below our pickup function and I'll just call it drop and it's going to take a variable and it's just going to be the name of the weapon that we're going to drop and that's going to be a string and then I'll just type pass in here it'll come right back up to our input function here and I'll type if event dot is action pressed drop and I'll just call that function drop and I'll pass in the current weapon dot name just make sure to check that variable that is the same as the resource variable weapon name so I've got this wrong here I'm going to type weapon underscore name that's the variable I need to pass in we haven't looked at the weapon resource in a while so I might forget that just double check it yours might be different in here the first variable we are going to need is a reference to that in our weapon stack so I'm going to type VAR weapon underscore ref equals weaponstack dot find name comma zero because we're going to start from the very start the ray if that returns negative one then this is already a problem and we're not going to process anything but generally it's going to return something greater than that so I'll type weaponstack dot popat wrapping ref which will be the weapons position in the weapon stack so what that will effectively do is just remove the weapon from the weapon stack so we can no longer access it and we're going to emit the signal update weapon stack you'll have to bear with me I'm doing it the old-fashioned way in a lot of these videos I hadn't actually worked out it was updated I've got a video out on that that I put up a few weeks ago if you want to watch so we'll go on to the next step here I'll type weapon dropped now we're actually going to need to spawn a rigid body at this point but how do we know which rigid body to spawn we're going to need to add another variable to our weapon resource so let's pull those up I'll come over to one of these and you can see we don't have anything we've got a projectile to load which is the same thing it is just a rigid body if you are loading a projectile so we'll come over to the weapon resource script wherever you've saved that and we'll just add another variable here we'll type at export VAR and I'm going to call mine weapon underscore drop and it's going to be another pack scene and fortunately we've already created these in our series when we created them to be able to pick them up so we can spawn the exact same ones in fact we need to otherwise we won't be able to pick them up and I'll just drag these into the corresponding weapons and that's it I don't know why that has a box on it anyway um okay so we can come back into here and we've already typed weapon list square brackets name and so now we can just call that variable that would create dot weapon underscore drop and then we'll need to call instantiate so one thing that we need to remember to do is actually transfer the current ammo and the reserve ammo onto this dropped weapon they have default starting values but at this point we're going to want to override them so I'll type weapon drop dot current ammo and weapon dropped dot Reserve ammo and we'll just transfer that so weapon list square brackets name current ammo and weaponless square brackets name Reserve ammo the other thing we need to do before we get into the scene is actually set up its position otherwise it's just going to spawn at the zero point of the world so I'll type weapon drop.set Global transform and I'm going to set that to just be the bullet point which is like at the end of the muzzle of any weapon so it's just going to be sort of in front of the player and I'll just set bullet point dot get Global transform and that'll be all we need for that and now we can add this rigid body to the scene so I'll get access to the world so I'll type VAR world and I'll go get and I'll type gettree dot get root dot get child zero and that'll just be uh in our case the world node and so now we type world.ad child and we can pass in weapon drops and so now our weapon will actually appear in the world okay so now that we've done that we can actually switch to that weapon I think that's probably the best way to go about once you pick up a weapon you want to switch to it uh so we can play the deactivate animation and we just need to call exit and I'll just call that on weapon stack zero I forgot but if you've remembered the animation for deactivation actually happens at the exit function so I don't need to call that in this so I'll remove that and I'll just call exit at weapon stack zero and let's run the game and see how we go um okay so I dropped the weapon I switched to the starting weapon and it instantly picks it back up now now for kenoid you might realize that the weapon is falling directly into the pickup detection node that we created in the last episode so we're gonna need to do some things to make sure that doesn't happen um there's a sneaky little bit of code that we can slip in on the rigid body and I'll just come over to one of them they all use the same script so I'll just uh set up a Boolean variable called pickup ready and I'll set that to false and I'll just set up a ready function here and I'll type await gettree dot create timer and I'll just make it two seconds and I'll type timeout and then right below this I'll type pickup ready is true and so that'll give us a two second window that will allow the weapon to jump to the ground and it won't activate in the pickup detection however we do need to go over to our FPS weapon manager and just make sure that when it a body is detected in our weapon manager that we actually check that its pickup is ready so I'll come back to that weapon pick up detection function and type if body dot pickup ready and I'll just tab in all of our code so unless that's true we're not going to pick up the weapon and so that should just get us by and just like that the weapon falls to the ground and it's visible okay so we're cracking along now you might think we're done but we're pretty far from it there's a few extra things that we need to do um and you could probably think for a little second um with the code that I've written so far what happens if I try to drop the next weapon we can drop any weapon that we've got and we'll go back to weapon in stack zero which is this pistol here but what happens if we try to drop that what's gonna happen then so let's run the game and have a look okay so I've dropped that first weapon and I'm trying to drop the second weapon you can't really hear it but it says invalid get index 0 on array so there's nothing to drop so there's a couple of things we need to do to make sure that this continues to roll smoothly the first thing um it which is totally optional but I think it's good to have is an a variable on our weapon to say that it can't even be dropped so this is a design choice you don't need to have this it's just the first thing that I think of when you know somewhere some games have weapons that can't be dropped pistols knives stuff like that so I'm going to set up a variable here what can be dropped on our weapon resource if you're setting that up you'll need a ticket on all of the weapons unless you don't want it to be dropped so I'm going to leave it unticked on Blaster n so it can't be dropped and in the drop I just need to add that to the start of the function so I can say if only to get access to it since we only have the weapon string so if weapon list underscore name dot can be dropped and then I can just tab in from that make it so all of these can be checked the other thing that I want to do is just make sure that another rule we can also have here is weaponstack dot size is equal is not equal to one and so we can't drop our final weapon that's another option as well and now all of that won't happen so now we can't drop we can drop this first weapon no problems but this second weapon no matter what you do you can't get rid of it and so that somewhat solves a problem the game won't crash but we'll always go back to that pistol no matter which weapon we have and there's a couple of other issues like this one here that you can see where we've picked up the weapon but it's not showing up and there's an invalid index on the weapon stack and you might start to realize that we've got a bit of an issue with this weapon stack because the way that we're referencing it is um not the best practice and it needs to be fixed otherwise so you can see I've got weapon indicator plus one because I want to be at the next step now weapon indicator when we pick it up but we don't have two weapons so there's no effort to go in that case you can remove that that's probably the first step but we're still going to have issues um and so I think we can fix this problem all together okay so let's fix this weapon stack so we've got to come right back up to the start of the code this is one of the first things we've written so don't worry if you don't remember what this all does um I forget sometimes too so this was this weapon indicator variable is what controls our weapon stack when we want to switch weapons we increment that weapon indicator which is just an INT and then we feed that to the weapons stack and we pass it into the exit function so we're essentially just you know counting up up to a certain point and counting down to a certain point which is okay but then you need to track that position every time you're changing the weapon outside of the weapon change mode so when you pick up a weapon when you drop the weapon and anything else in between you never know you might want to add something in the future and you'll need to update the weapon stack and know where it is and at least in this particular instance there's situations where you could add that weapon anywhere in the stack you don't know where you are um and so we are going to set up a way to do this better I think so everything here is going to be aired out and we can pretty much delete this weapon indicator line here and I'm going to type VAR get ref this is just the variable either side alone you can call it something different if you want and I'm going to make that equal to the weapon stack dot find and I'm going to look for the current weapon weapon name and so like I'll find the current weapon that we have in the stack and it will return that number and so now all I need to do is increment that by one or reduce it by one so it will say get ref equals min and it'll just be get ref plus one comma and we'll just make it it can't be any greater than the weapon stack dot size minus one not dissimilar from the previous card that we had and we can do the exact same thing for weapon down I'll copy this variable get ref and we'll call it up again and this time get ref will be equal to the max of get ref minus one or zero so we can't go past zero otherwise we will error out or we'll actually to be honest we end up at the start which to be honest could be something you want to do but like we don't want to do that I'm not going to do that so we won't go past zero and we'll pass that in and so now we'll be able to get to the next weapon in the stack without having to have a another variable to track that which means we don't need to worry where we are in the stack when we pick up a weapon and when we drop a weapon okay obviously when we pick up we were using the weapon indicator but we can do the exact same thing that we did with the weapon up and weapon down inputs here we can create a variable called getref and we can just call up the weapon stack and we can go find weapon.name in this case it's going to be the current weapon I can call up the weaponstack dot find current weapon dot weapon name same as before I could have copied it it's the exact same code every time and so now we're just going to add that and we're going to insert it at that point and so now it's just going to increment it'll be the next weapon in the stack when you pick up a weapon if you're in the middle of the stack it's okay so that's where it's going to go and so now we come to drop and we can do that here as well we've actually got the weapon ref up here but I'm gonna do it again just because that's what I've decided to do you know it's it could work either way so I'm going to just type get ref weapon stack current weapon I'll copy it from where we pick up a weapon because it's the exact same and then all we need to do is get ref equals Max the exact same is when we drop a weapon is when we go down so it's essentially the same process it it you do it so frequently that you might actually want to set up a function for it to be honest um it's something that you could seriously consider at that point where it shows up that many times in the code so it's not the best practice but it was just something that I thought needed to be done um and it really does solve this problem so now we can drop any weapon we want we can pick up any weapon we want we don't have to worry too much about it it's going to work every time okay so that I can pick up that weapon I can drop this weapon I can and the weapon stack isn't affected by that and it just feels really nice and you can shoot the weapon that's really cool I love that awesome we can do a lot of different things with our FPS weapon manager uh we can pick up and drop weapons but right now we are missing a pretty major feature and that is the ability to pick up the ammo from the weapons and also just pick up ammo from ammo clips and things like that that you might want to put in the world realistically after we do this you can just attach this ammo script to almost anything and you'd be able to pick up ammo from it so let's get into it okay so let's jump into our FPS weapon manager we've got a lot going on right now but we are going to be changing some of the code on our pickup detection so right now when we walk over a weapon we are checking if the weapon can be picked up and then if it's not in the weapon stack we add it to the weapon stack and change to that weapon so these weapons all have ammo what we can also do is check to see if those weapons if they are in the stack to see if we can take the ammo from them so we'll just need to add an else statement right below this because we say if weapon stack is negative one which means it's not in the stack we pick it up but we can just say else pass and I'll just write add ammo we'll add our function at the bottom of the script so I'll scroll down to the bottom of the script and we'll create a function here and we'll call it add ammo and it's going to take a weapon reference which will just be the string or we call that weapon and it'll also take the ammo and we'll create a variable here and we'll just call it underscore weapon and we'll make that equal to the weapon list and we'll use that string reference to get access to the resource and now we are going to figure out how much ammo we need we'll call the variable required and we'll make it equal to weapon dot max ammo and we'll subtract the weapon Reserve ammo so that'll tell us the difference between how much ammo you have and the maximum amount you can carry which is how much we need the next we will calculate the remaining which will be the max so we'll use the function Max here ammo minus required with it being a minimum of zero obviously we won't we don't want to get into the negatives here if we are using all the ammo then remaining is going to be zero okay and then finally we can say weapon dot Reserve ammo plus equals to Min and so that we're going to add this to our Reserve ammo make sure you add that plus before the equal sign min ammo or required so in the case where the required amount of ammo is less than the total ammo that is available to be picked up we want to only add the required amount we don't want to add any more than that I'm just going to come up to the reload function and take the signal that we emit there and I'll just paste that in still using that old way you can watch my video on the new way to do signals in godot4 and then finally we will return remaining I'm just going to add a return value as an INT on this function just so that we know that if we mess with it in the future that it definitely needs to return an hint for this to work but that's totally optional in the dough you don't need to do that some people do it on all their functions I tend to do it on just functions that I know definitely need to return something and sometimes I forget to okay so after this else statement well we actually want to do this add ammo I'm going to create variable code remaining again and I'm going to make it equal to add ammo brackets body dot weapon name and the next part which is the ammo is going to be the sum of both body dot current ammo plus body dot Reserve ammo and then I'm going to say if remaining is equal to zero then we can remove the weapon from the game so we've picked up all the ammo it's of no value just delete it and then finally we can say body dot current ammo equals to zero and body dot Reserve ammo equal to remaining and so this is the simple way I guess you could say to do it you take all the ammo and you just slap it onto the reserve ammo for the weapon on the ground uh this will work pretty well I'll go into the remote just so we can see the math happening in real time so let's have a look at Blaster n so as you can see I'll walk over and you can you can instantly see that the reserve ammo is just set to 20. it's not a big deal but it is something that we might look at changing later on um okay so now let's take a look at these reloads here things look like they're mathematically working out we can pick that up it's got 19 ammo and reload it we can shoot it a bit uh we got 10 and we pick up 10. and if we pick that one back up we only have 10 left and we can swap them back and forth and we can see that everything is working pretty much as we expected it I'm not a huge fan of just sending all the ammo back to zero it's not a big deal but I think we will change it but you know that's it that's how you add ammo if that's all you're looking to do we're done but there's more that can be done so stick around okay so let's fix up this current Ammon and Reserve ammo it's going to be Min remaining okay so we get access to the weapon list body weapon name dot magazine so it's either going to be whatever's left or the maximum of the magazine and then we just make the reserve ammo equal to a greater of uh remaining minus body dot current ammo or zero and that'll actually do the opposite we're going to put all of it in current ammo and the rest will just be sitting in reserve ammo and personally I think this is a better design choice but ultimately these kind of things are really just up to interpretation how you want your game to feel I think it's way cooler if you pick up a weapon you can shoot it straight away but you maybe you want to like maybe you feel like it's more realistic if you have to reload it first you know there's a bunch of different things maybe you try to make like a more difficult game Dark souls-esque FPS and you want it to be you know so that you have to do a bunch of stuff before you can even use a weapon like you would have to in real life you can't just pick up I mean sometimes you can't pick up a weapon and start shooting I don't know I've never shot a car before a little fact anyway we're rambling here so that's done so let's get into it right now we have the ability to pick up ammo from weapons but what if we wanted to just have an ammo clip or that's on the ground that we can pick up or anything like that maybe you want to have a box full of ammo but I'm going to make it on this clip here I'm going to copy I'm going to save a copy of one of these rigid body seeds because we're going to basically just Harvest all the code here so I'm going to save the scene as and call it Blaster and clip at the end so that it's the clip for the Blaster n and I'm going to probably delete this model and the Collision shape and I'll just add in the clip and I'll make it local and take away all the nodes and stuff just so I've got the mesh there I'll move that to the center of the scene and create a simplified mesh by that little menu in the middle there and the one thing that we need to add to this script so that it can work with both these clips and the weapons is an export enumerator and this is going to be a weapon type and it's either going to be a weapon or it's going to be ammo and this will be called pickup type and it's going to be a string and I'm going to make it equal to weapon that doesn't need to be a string so I'll just change that to a string and so what this will do is it'll make all of our old rigid bodies weapons and I can change this one to an ammo and the rest will all stay the same so this will all work with them you could create an entirely new script but I think it's just easier so that we can make it work with everything we've already written just sort of just change this script so I can work with both so we've got this enumerator we can bring this uh this clip into the scene I'll make a new node here in our world and I'll call it ammo just so that we can organize all of it I'll drag that Blaster and clip in make it a child of that node and I'll just move this to the back so it's a little bit out of the way I'll turn it on the side so it looks nice and pretty and uh then we just need to change the code a little bit so let's come down into the pickup detection and right now we're seeing if the weapon is in stack but now we also want to make sure that the body that we're walking over is also of type weapons so we'll go body dot pickup type is equal to weapon we're not even going to check if it's ammo all right which is cool and I'm gonna put a print out there so we can see it as we walk over okay so we need to see that as as we walk over and a weapon it still works and we see the printout weapon so now we can switch to our Blaster n let's empty this clip a bit so that we need more ammo and walk over this and look at that we just get 10 straight out of it okay so we're back in our project so we'll jump over to our FPS character now I've already made the animations for these so but I'll show you how they're put together so you guys can get a better idea of how to do this um so it's mostly just playing around with the position and rotation and what I think works best is that you instantly transition to the Striking pose so 0.2 seconds or 0.1 second even so you're instantly in that position and then you linger for like 0.2 seconds there's a little bit of movement but there's not a lot and then you eventually return to that position and this one does a flip so you put that all together it looks like this where there's that long pause in the uh in the melee animation um and I'll show you on a couple of others okay so in the rifle let's have a look at the at the melee strike here we go from this position instantly into this we linger there's a little bit of return I actually think follow through is better than returning this so I'm not 100 on that one but you get the idea you linger you instantly transition you have a little bit of lingering and then you return so I think that looks really good we will get to setting up the code for this I'll just call the reset on that okay so we'll jump over to the FPS manager but before we write any code we need to come to the project settings that we need to add a new action I'm just going to call it capital m e l e e that's how you spell melee I have to remember I'm really bad at spelling so you have to apologize for get stuff wrong I'm going to make it the F key and that will be the key that we use to do a Millie strike so we can come back into the script and in the input event we'll need to add a new event so we can come right below this and we can go if event dot is action pressed and melee and we can just write a pass because we don't have a function to call yet um so I'll come I want it to be probably after reload I feel like it reads pretty good then it's all right Funk and I'll just call it melee again it doesn't take any variables it's nice and simple okay and I'll just type pass and I'll come back up before we forget um and I'll just write here and I'll call that function if action press melee okay so let's get into writing the melee function uh this one's going to be a little bit different from the others because we're going to allow this to interrupt other actions so uh we're going to need to refactor a couple of functions particularly reload and we're also going to refund refactor the uh the camera collision and the head scan damage because we need to modify them to accept this function and use the rate casting functions to detect what's in front of us but before we write anything in the function we are going to need to add those animations to our weapon resource so I'm going to open up the weapon resource which is right here I'm going to add the animation to the animation variables which is this top set here so I'm going to type out export VAR m e melee a Nim and it's going to be a string and the other thing that we want to do is under damage we're going to also add export for melee can't spell underscore damage and so that will be the damage it does okay so in the weapon manager we're just going to come into each of these and the naming conventions are the same so we can go Blaster I all right really foreign spell it right um hit save I've forgotten to do the damage so I'll do that for both of those I'm gonna make like I'm gonna make it the same as uh just one we'll do for now we'll go blast at n melee and nearly damage one okay and I might change that to be uh if you guys this one's all messed up uh that's okay we'll just leave it as is okay so now we've got the animations we can start writing that function so we can come back up in here and uh we're going to allow this one to interrupt other functions so we need to write a different line that we normally start with so normally we're checking to make sure that the animation player isn't even running but in this case we only want to make sure that the current animation isn't already the melee animation so we can't interrupt a melee hit but we can interrupt pretty much everything else and if that's a problem we can always change that later animation player dot get current animation and we're going to make sure that it's not equal to current weapon Dot mainly underscore name just make sure that this variable name is the same as variable name in your weapon resource okay and underneath this we are going to say animationplayer.play and it's going to be the current weapon.amillion in so if you want you can just copy this and paste it in there okay so let's first make sure that this is running the way that we expect it to so we can see that I can shoot and it will just instantly play um one thing that you'll notice straight away is that we can basically short now reload Time by interrupting the reload we're going to fix that in a second um but other than that it's working how we expected it to so let's fix that reload thing before we go any further so the reload is right above us now what we're doing with the reload is we're essentially uh we're checking if it's not an animation playing and then we're just reloading instantly before the animation is finished so we can uh just probably copy this variable we can come up to the on animation finished signal that is being triggered by animation player and we can add another check here we can say if a Nim underscore name is equal to current weapon.reload and M and then we'll just put a password and written the function I'm going to move or refactor this part of the code to be a new function and so we'll call that function down here we'll quote we'll call it a calculate underscore reload and we'll essentially just copy all of this and we'll paste it there and I'll just remove some of those uh indentations you can press shift tab to do that and then where this all is I can delete that and call actually we don't even need to call the function we just delete it all okay and then we will call that function when the animation is finished not as soon as we press the button and so that will prevent us from being able to interrupt the reload so we'll run that again I'll just reduce some ammo and now until I let that finish it doesn't matter what I do I have to let it run um maybe you don't want the um melee animation to be able to interrupt the reload it's really up to you if you want to do it this way or if you want to just make it so the merely can't interrupt the reload uh your call otherwise let's continue so what we need to do right now is we need to do a raycast from our melee strike to the object in front of us to see if it can be damaged uh we've got a function which is right below this called get camera Collision that we're going to need to refactor a little bit in order to work with melee and also work with our head skin weapons and also work with our weapons so right now the range is just currently being called in the get camera Collision function what we want to do is probably just cut that out and replace it with a another variable we'll just call it underscore weapon underscore range all lower case and we'll just put that in the function here weapon underscore range and now it'll also error out at the shoot location because that's where we need to be supplying that variable now so we can paste that back in currentweapon.com dot weapon range and now when we do our melee strike we can also use that function and use a shorter range so I'm going to go back to the weapon resource and I'm going to add that variable and I'm also going to add the melee damage as well so under weapon range I'm going to create another variable I'm going to call Expert VAR really single L range I'm going to make it a float this time and I'm also going to make it equal to like 1.5 as a default value because like that's generally good enough if you wanted to be longer perhaps for like a bigger weapon or something you can increase it um and the export and we'll call this melee underscore damage and this can be an INT and I'll just I want to give this default value I'm going to come back to our weapons and we'll just see they've got the weapon melee range and I'll just make this one perhaps I couldn't give it a default value of one okay now we come back there we can actually write our function here we can come in and we can go VAR camera Collision is equal to get camera collision and we'll call current weapon Dot [Applause] Dot melee underscore range so now that we can do that we still need to change our camera Collision a little bit further as you can see right now we're just returning the position of that intersection which is uh not quite what we want that position is important but we also want to know what the actual object is that we collided with now we're doing this again in hitscan Collision but we don't want to use that function because it's using the bullet point which is not something that we wanted to use in the melee section so we just need the object we've got it already it's actually being returned from this function here the get camera Collision so what we actually want to change this to is to return an array of both the intersection object and its position so what I'm going to do is I'm going to change this to be an array so bar Collision is actually going to be an array uh we'll go square brackets and it's going to be the collider I'll put that first intersection.collider and intersection.position okay so now we're returning that it's not happy I need a comma don't forget the comma okay so now we are returning two objects for the Right End we're going to need to return a null at the start because we still need to return an array we don't want to confuse ourselves and I'm going to change this to an array as a return object and then in the shoe we're going to need to change things here rather than sending the camera Collision we just need to send a position like before so that's the second object in in the array that's number one and same with this it just needs the camera Collision position run a little test to see if that works everything is functioning as normal that's what we want still doing damage everything like that so that is positive just make sure everything's working when you do these rear factors so this now returns an object and we can type if camera Collision square brackets zero and now we can calculate the direction so we can type VAR Direction is equal to we'll do double brackets here camera Collision and this will just be the position so square brackets one minus and I'm going to call the owner dot Global transform underscore transform dot origin the reason for that is just for whatever reason I found that that was working better than using the weapon manager as the object for the global transform dot origin um and we'll just type Dot normalized so that's our Direction and then we can just pass in head scan damage now we're going to need to refactor that because that takes a collider a direction and a position um so we know what the collider is we can call camera Collision square brackets zero the direction is the variable we just created and the position is camera Collision One all right but we have another problem here hit scan damage is using the current weapon.damage we want to replace that with another variable I will type weapon underscore underscore weapon underscore damage it's going to get upset so we'll type that up here it should be happy and we'll see this have an issue here and so all we need to do to fix this is just call current weapon the damage once again just making sure the variable name is the same and then up here for merely we can call current weapon dot melee damage stop meleeing damage that's not a function close brackets okay and so now we've separated the damage from Hit scan damage we can call that in a separate location like in the melee function and so now we can apply the merely damage when we detect a hit and so if we run the game now things we just test that out make sure it's working it looks like it is now we can run over to this box it's always a good indicator of whether or not things are working we can come here and we've got a little bit of an error what have we got index uh I made a spelling mistake it's a very common error of mine origin origin let's try that again just walk straight out of the box this time and you can see it's working properly sorry about that error and so now things look great we have got it interacting we can walk over to one of these targets to confirm that it's working and so now we've got melee damage how cool is that and everything seems to be working as normal uh one major floor of the way I'm doing things here that I've thought about a lot and eventually decided this was the better way to go mostly just for the purposes of what we're doing here is that we are just using array cast for this so um if I'm this much off it's not going to detect a hit because I'm raycasting to the center of the screen which might not feel very good to the player so just feel that out and if you're not happy with it you probably need to replace it with an area 2D around a wider range or you need to cost more raise so there's a couple of options there but right now this is what we're going to do just for like an easy one my assumption is my reasoning for doing that this way is that because I'm assuming if you're performing a melee attack chances are the object you're trying to hit is very close to the screen so it's highly likely that it's going to be covering the center of the screen obviously that's not always the case and so there's going to be a couple of Miss hits when you're not quite there and if you're out of range just a little bit so that's obviously a range problem and this is like the problem with the raycast being just from the center so maybe you need to do more raycast if you find that's a problem let me know I can probably do an updated video where we add a area to where we add an area 3D to detect what's in front of us instead or we could refactor the get camera Collision to perform a more raycasts if we want that's an option too but other than that that's how you do it we are going to be finally adding a control rig to this FPS manager I'm going to be doing this with a rig but it's mostly for demonstration purposes it's incredibly simple to do and it's easy to add at any time in your project so I recommend that you think about adding a control rig when you're further along in your project but I'm going to show you now so that you have this for reference or you can follow along as well because the entire point of this weapon manager is to make sure that when you get to this stage of your project you can add a rig without changing anything or without needing to update animation references that have been baked into your code and the first thing we're going to do is just open up the FPS character scene first thing we should really do is just save this scene as a separate one so I'm going to save it as FPS character with rig and I'm also going to update the kinematic body node's name and then finally we're going to delete the FPS rig that we have currently and I'm also going to remove all the resources and the starting weapons just so that we're back to a base zero if you had nothing and we're going to start from scratch I've got a rig that I created last year it's not perfect as you can see when I open it up it's still a full body we're going to have to deal with that I'll make this available for download but it's not really finished so keep that in mind so the first thing I'm going to do is just drag this into my scene here and I will drag it just into the root scene so that it doesn't get too much transforms put on it I'm just going to reset the transform and then I'm going to drag it as a child of the FPS rig I'm going to make it local I didn't properly prepare this rig so it's got a lot of control nodes and I'm just going to remove those because we don't need them that's from blender the other thing is I've separated out the mesh so that we can remove everything except the arms because that's all we need from this mesh so I'm just going to go and I'm going to select all these other meshes that we don't need and I'm going to move them so if you've got your own rig you won't need to do this all right so with everything left over we've got this we can start to work on actually positioning this rig so you want to click on the camera and click preview when you come back down to our rig and I'm going to just lower it a bit so that it sits a bit better in the frame I'm going to check another animation just to see how it looks with the pistol I think it's a little bit too low so I'm going to bring it up a little bit and also the rifle and I think I'm happy with its position so once I'm happy with that I can move on to the next stage and we'll need to connect the animation player to the weapon manager so we've got an on ready VAR animation player here I want to make this a little bit easier for your future rigs that you want to put in or any other work that you want to do so I'm just going to remove that line and we're going to create a new variable with the exact same name but it's going to be an export variable and we're going to make it equal to an animation player and so now you can just drag and drop whatever animation play you want okay so now that that's done we can drag that over into the animation player under the weapon manager so the next thing that we need to do after that is we need to set up the resources for the three weapons that we have we've got a rifle we've got a pistol and we've got an AK-47 so I'm just going to come down to where I've got my weapon resources you can see my file manager is a bit of a mess so we're not going to worry about that I'm going to create a new folder and just call it something like I'm going to call it something like rig weapon resources okay and I'm going to create a new resource and I'm going to create a weapon resource and I'm just going to name this first one one and then I'm going to duplicate that and rename actually on that I call this AK-47 because I know the names of these resources already um I'll create another one I'll call it pistol and the one that I called one I'll just rename to Rifle okay cool awesome so let's go through and set these up we need to make sure these animations match exactly the variables in the weapon resource so come back up the weapon name we're just going to call it rifle for the rifle and um all these animations so they're rifle underscore activate for me and it's all pretty consistent with the variable naming so I'm just going to go through so for the animations you want to play just make sure that they're the same as the animation in the animation player I'm going to go through and add some ammo here it's pretty basic stuff 30 60 it's going to be an auto fire it's going to have a 2000 Range damage of one and it's gonna be hit scan I don't have a weapon to drop yet so I'm going to leave can be dropped unchecked for now okay I'm gonna head to the next weapon it's going to be a pistol this might take you a little bit longer if you don't know the names of your animations I'm pretty familiar with this rig so I'm just going to go through and name these I don't have an out of ammo animation for all of these I'm going to leave it blank it's not advisable to not have like to leave an animation playing for this weapon rig the behavior won't be as expected so if you do have like a placeholder animation that's helpful too I don't so we're just going to roll with that okay last one is AK-47 and copy that down and just name all these animations as well and we'll give them some ammo and Reserve ammo to start with make it Auto fire 2000 Range probably a bit long for an AK-47 but we'll roll the hit scan and then we can go next now we need to come back up to the weapon manager and add these resources to the weapon manager so under the size we can create three new resources and we can drag and drop these resources into this array and for the start weapon I'll make all three starting weapons and so I'll just type their names in here pistol rifle and AK-47 all right so things should work as normal I just want to show you here just we'll run it just to make it sure it starts and there's no problems we'll delete that FPS controller and we'll drag in the new one okay so let's run the game and make sure things are working so far it looks okay we can spawn in and we can shoot and it looks like the head scans are working and doing damage to the box but we can't change weapons yet and that's because we haven't set up the signal I want to introduce a new way to connect that signal because if you're changing the rig often if you're prototyping you're going to be setting up that connection quite frequently so I'm going to come down to the on animation player animation finished and I'm just going to rename that function to make it a little bit shorter I'm going to call it on animation finished and I'm going to copy that function name and I'm going to come up to the ready function and I'm going to type animation player dot animation finished and then I'm going to say dot connect and then I'm going to paste that callable in on animation finished and now that signal will be connected up at runtime and we should be able to switch weapons here no problems and automatic firing will work as expected you can see there rifle is a bit of a laser Okay cool so we're rolling things are looking pretty good we're not quite done yet though because we need to add the ability to drop weapons and pick up weapons so we're going to need to create a couple of rigid bodies for the weapon drop I'm going to create a new scene with a rigid body and I'm going to drag those models in that I've got for these weapons so the first one is the pistol I'll make local and remove the parent node so I've just got the mesh and I'll click the mesh and click this button that says mesh and create a simplified trimex Collision body I'll rename this rigid body to pistol and we will drag that script in I'm having a bit of trouble finding it so maybe if you know what it is just type weapon pickup the weapon name will be pistol current memo will be nine the reserve armor will be nine these can be any values you want these are just what I'm picking and the pickup type is obviously weapon okay so we can save that scene I'm going to create a new folder under the FPS arms folder and I'm going to save that there cool okay so we need to create two more of these for the rifle and the AK-47 so I drag that rifle in you can see the rifle is gigantic because I haven't treated it yet do the same as before I'll drag that model in I'll remove the parent node so I've just got the mesh and I will change the scale of this and once again I'll click that mesh button and click create simplified Collision vertex and I'll do the next one as well while I'm at it I'll drag in the AK-47 make it make it local create a simplified Collision convex mesh and change this to AK-47 and also make sure to rename the nodes okay so I'll type pick weapon pickup and drag that script into the rigid body and I'll name it Rifle 30 30 that's fine I save that and then same with the AK-47 I'll drag that script on I'll call it AK-47 I'll just give it 20 current 20 reserve and obviously it's a pickup type weapon again so we'll save that as well and so now we can come back to the FPS weapon manager and in those resources we can add those rigid bodies as the weapon to spawn on drop okay so we'll drag it for the pistol make sure you get the right one not a project to load and also remember as you're doing this to make sure that you check can be dropped so that you can actually drop the weapon and for the AK-47 I'll do the same I'll drop that onto weapon drop and check can be dropped okay so we should be able to drop these uh don't forget as well to set up the Collision layer So Right Now the default is obviously the world these need to be set up as layer four in our project for weapons and they need to mask the world all right so I forgot that on the pistol I'll come back over and I'll do that for the AK-47 as well four and one as the mask and we should be able to run the game so now we've done that we can drop the weapon we can pick up the weapon and things are looking pretty good okay so the next bit of fine tuning that we need to do is the bullet point which we set up as the place to do a raycast for the hit scan weapons and also to spawn the weapons so you would have noticed that those weapons sort of like came out of the face of the camera because that's where the bullet point is right now so I'm going to add that animation to the animation player you will see a warning that says that it changes to the imported tracks will not be saved that pretty much means what it says on the tin you can't make changes to the imported tracks but you can add tracks to things that weren't important so we can add this bullet point to these animations and it should just work perfectly so don't worry too much about that error I'm just going to come in and move that bullet point to the front of each weapon and key that in could be a little bit tedious working in 3D space so I recommend using the perspective shifter just keyboards one three and seven okay so now that's there I can come back I always like to key it to zero zero on the reset so that it sort of goes back to zero in the case of not having a weapon or better just be in the center okay so I'll do that for the pistol I'll come down to the rifle and I'll also key it in there make sure it's in the right position doesn't have to be perfect as long as it's in a general spot that is going to make sense for the player last thing you want to do is make the raycast go from a place where you're not expecting it to and ruin the player experience okay so now when we drop the weapon it should drop out in front of them and our raycast will be a lot more efficient or a lot more accurate I should say okay that's great so let's add those rigid bodies to the scene as well so that we can pick them up we'll come into the world I've got the weapon node already I'm going to drag all three of those rigid bodies into the world and I'm just going to move these around in this scene so that they're positioned just to make sure we're going to test out that these are working normally okay so let's run the game here you can see the the rifle's a little bit smaller than the AK-47 we'll have to work on that we can shoot okay we reduce the ammo down here I'm gonna empty all my ammo here and I'm going to walk over that rifle to make sure that it works as expected so it's got 60 I believe and I pick up 60 no problems okay guys that's all for now we have finally created a full FPS manager massive props if you made it all the way to the end of this video all that's left now is the juice which I'll be covering in the next few months if you found this helpful then I certainly appreciate a like And subscribe if you want to support me further you can do so on the patreon where you'll get access to early videos and any other goodies that I put out like assets and courses anyway that's all for this part one I'm taking a bit of a break and I will return with part two soon I'm Isaac from Shaft games and I'll see you next time
Info
Channel: Chaff Games
Views: 26,777
Rating: undefined out of 5
Keywords: godot, godot game engine, devlog, making a game, godot devlog, godot4, godot 3d, godot fps, godot fps weapon, godot fps tutorial, godot 4 fps controller, godot 4 weapon manager, godot 4 fps character controller, godot 4 fps tutorial, godot engine, godot tutorial, game engine, Godot, Godot tutorial, Godot 3d, how to make games, game dev, how to program, first person shooter, fps, hitscan, unity, godot fps controller, godot pistol, godot gun tutorial, Chaff Games
Id: ZaEzjnoIy3M
Channel Id: undefined
Length: 161min 45sec (9705 seconds)
Published: Fri Oct 06 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.