Godot 4 - Online Multiplayer FPS From Scratch

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey in this video I'm going to show you how to make a simple networked FPS game with Godot 4 and blender 3. I'll walk through it one step at a time so check the timestamps in the description if you're only interested in certain parts this project uses something called universal plug and play which should work for most people out of the box but you may need to check your router settings at some point to make sure that UPnP is enabled I'm no networking Pro this was just the simplest starting point to online multiplayer I could find and I had a lot of fun making little projects like this so if that sounds interesting to you let's get started okay I've got a brand new blender file open here and I'm going to make an environment for the game really quickly so ax to delete everything then shift a mesh plane s tend to scale that up tab into edit mode control e extrude edges right click to keep them in place and then S2 to bring those out gz to just to give them a little bit of height there and then e right click to extrude those edges in place s 1.5 to extrude those out and then easy for enter just so that there are some walls so the players can't walk off the edge of the world okay tie back into object mode then go down to this menu here give it a new material this is coming to play later and then let's give this environment a couple more objects just so that it's not so boring so shift a mesh cylinder then I'll go down here I'm going to give it a radius of 1.5 and a depth of four then gz two to bring it up to ground level actually I'm going to hit shift tab to turn snapping on so that simplifies moving things a little bit numpad 7 to go to the top view here I'm going to move this one up to the the middle of this corner so G and just drag it right there shift d and I'm also going to put one up in this corner and then gz drag it up so that's actually on the ground there and now we're also going to add some platforms here so you could maybe you know jump on this pillar here so shift a mesh Cube okay gz to bring that up there and then sx5 I'll go to the top view again drag it over just so it's perfectly in the ramp just like that shift e to duplicate it are C90 G then drag it over to this side okay perfect now I'm going to click all of these and I'm going to duplicate it so that it's on all edges or all of the corners I should say I'll go up here select 3D cursor and then shift d r z 90 and then do that two more times Shifty RZ 90. okay perfect so now hit a to select everything and then shift click make sure that this plane object the the floor is the last selected one the active selected object then control J to join all of them together tab into object mode you can just press a to select everything and we want to select everything except for the plane vertices so I'm going to go over to one of those vertices here and then hit shift L to deselect all of the linked geometry there and then in this material tab hit this plus button to add a second one new material two and then hit assign so then let's just check here so material one select yep it's all of the ground vertices there the material two select it's everything else okay that's perfect that's exactly what we want we're going to apply prototype textures to these objects in the engine and having them separated in these two materials will just simplify that process okay so the last things that we're going to do is add Dash col to this so that it automatically has Collision on import to the engine and then I am going to select it Ctrl a apply all transforms and then I'll just save this as environment.blend and we are done all right I've got another new blender window open here we're going to model a pistol for the players to use as a weapon so I'll click the light shift click the camera delete those we're going to start with the standard Cube here click the Cube S shift z.5 s 0.1 to shrink that down period of the numpad to zoom in tab into edit mode and we're going to extrude the barrel down the positive y-axis I'll press K to go to the knife tool and then shift clip these edges to put those vertices in the middle enter three for face select click the top one e point two and then I'll click this bottom face here gy drag that back a little bit two for Edge select click the bottom edge of the barrel gz drag that up a little bit tab back into object mode go to the wrench add modifier let's add a bevel modifier to it I'm going to turn it up to like point one five okay and then I'm just going to apply it like that and it's a little wide so SX let's scale that in a little bit okay perfect tab back into edit mode three for Facebook click this back face I also scale it into about here two for Edge select click this bottom edge of the new face and then G twice to lock it to the edges that it's attached to right now drag it up to about there three for face select click the face e extrude it out to about there again Edge select mode bottom Edge GG drag it up about halfway and then we've got a hammer for our pistol there okay and then three for face select I'll click the end of the barrel here shift s cursor to selected and then shift a cylinder and then this is way too big so I'll make the radius 0.05 and the depth of 0.05 as well RX 90s let's scale this way down okay and then it's out a little farther than I'd like so s y all right and then three for face select click that end face of the cylinder e right click to extrude in place and then s let's scale that face in and then X delete only faces and we've got everything modeled now we just need to take care of the materials and because this is the starter Cube it already started with one material so let's just call this one uh pistol black in the viewport I'll press Z and go to material preview and then for the base color here I'll drag this down not all the way but pretty close to Black and then specular I'll drag down to maybe around 0.1 then I'm going to add one more material here and I'll call this one pistol gray and the base color for this one I'm gonna I'll make this like two thirds of the way down like that and we're going to apply the tip of the barrel and the hammer to have this uh this gray so I'll go into edit mode with the tab and then I'll press L over that cylinder geometry to select all that and then with face select mode on I'll shift-click all these faces and then with all that selected make sure you've got pistol gray selected there and then hit assign and there we go control a apply all transforms when you're in object mode and then Ctrl s and I'll save this as pistol.blend and we're done all right I've got a new Godot 4 project open up here and we're going to start by importing some assets including the environment and Pistol models that we just made and we're going to import them as blend files but in order to do that we're going to have to go up to this editor menu here go to editor settings and then in filter settings here you can search blender go to this import Tab and this blender 3 path is going to have to be set to the directory where your blender.exe is so here you can see that this blender Foundation folder is where my blender version is install by default so in blender 3.3 this is what I'm currently using this is where the blender.exe is so you're going to need this directory listed here and if that's giving you problems you could also just export your models as gltf like I do in my previous videos so if this isn't working just go ahead and follow that process in my previous videos but I've got this set so I'll continue so I'm going to take these blend files select them and just drag them in here and then Godot is going to import them okay and then I'm also going to import some things from the asset Library I'm going to import some textures and some particles both of which are made by Kenny so the Prototype textures and the particle pack here so I'll click the Prototype textures click download and then I'll just install all of it okay and then I'll do the same exact thing with the particle pack download and I'll just install all of it okay and we're good to go now that we've got everything imported let's go ahead and set up a basic environment scene so right click environment.blend new inherited scene click this plain mesh instance and then over here in the inspector surface material override surface zero is going to correspond to the floor and the walls and surface one is going to correspond to that second material that we made the one for all of these extra objects that we added so for surface material zero new standard material 3D go into that Albedo and then in our add-ons folder any prototype textures I'm going to give it a dark texture and I'll use texture underscore zero nine I'll drag that into the texture field there and then in uv1 Click try planer that just makes it so that the texture is projected on and it looks a lot cleaner and then for one new standard material 3D same exact thing go into Albedo and then here I'll go with an orange one instead texture underscore 10. and uv1 triplaner okay I'll save that environment.tscn and then let's put this together in a basic World scene so other node I'll just make it a root a normal node call it World Ctrl shift a add environment.tscn and then I'll click these dots up here add environment to scene add sun to scene and we are looking good Ctrl s to save that as world.tscn now that we've got this environment set up let's set up a player scene so we can actually move around it so I'll hit this plus button other node character body 3D I'll call it player control a add a mesh instance 3D and then I'm also going to add a collision shape 3D for the mesh instance I'll give it a capsule mesh and the Collision shape I'll make a capsule shape I'll shift-click both of these hold Ctrl drag that up one unit just that the bottom of the capsule is at the root position then on the player control a I'm going to add a camera 3D and then I'll drag the camera up till it's right about there on the capsule then I'll click the player node add a script to make sure you've got this template checked for basic movement I'll create that currently the movement is mapped to the arrow keys but I want to use wasd instead so I'm going to add some new actions project project settings go to input map add new actions up down left right I'm also going to add a quit action up W down s left a and then right I'll map to D and quit I'm going to map to escape okay and then here I'm just going to remove all of these UI underscores and then this will be mapped to wasd instead okay I'll save this scene and then I'm going to go back to the world scene here click the root node Ctrl shift a and that player scene hit play select current okay so now I can move the play around but we need to lock the cursor and make it so that when we move the cursor the player rotates along with the camera so I'm going to close this out also when we lock the cursor it does become a little bit of a nuisance to close the game so on the world scene here I'm going to add a script and then I'll add a unhandled input function and if input that is action just pressed quit get tree quit so now I can just press escape and quit whenever I want so I'll save that go back to the player script let's lock the cursor so up top here I'll add a func underscore ready function input.mouse mode equals input.muz mode captured let's take a look okay so now the mouse is captured and if I hit Escape I can close out now we just need to handle the rotations up top I'm going to get a reference to the camera at onready VAR camera equals camera 3D and then under this ready function I'll add another unhandled input function if event is input event Mouse motion and when the cursor moves from left to right we're going to rotate the player on the y-axis so rotate y negative event dot relative dot X and then I'll multiply that by .005 and then I'll copy this and on the line below camera Dot and paste that when the cursor moves up and down we're going to rotate the camera on the x-axis so I'll change this rotate y to rotate X and then the relative X to relative Y and we just need to lock this number to a certain range otherwise the character's camera could like somersault forward infinitely so under that camera dot rotation dot x equals and I'll copy this clamp and paste that and then comma negative pi over 2 pi over 2. all right so I'll save that and now we can move around and the player can look up and down everything works as expected the movement isn't great and there's a lot of things that you could do to this controller to make the movement better but that would be a little bit out of the scope of this video so we're just going to tweak a couple numbers and and call it there so I'll hit escape and I'm just going to change the speed 10 the jump velocity to 10 as well and then I'll set the gravity to 20. and for our purposes this movement is going to work just fine we can move around a little bit more quickly and jump up around the environment a little bit okay so that's a wrap for the character movement next up we're going to give the player our pistol mesh as well as some animations so I'm going to go back to the 3D tab over here click camera 3D Ctrl shift a give it a pistol.blend as a child and then in that transform position I'll set to 0.5 minus 0.25 minus 0.5 I'm going to click view up here at the top of the viewport select two viewports alt and then I'm going to open this bottom panel here as well and I'll click camera 3D click preview on the right and then I'm going to adjust this until I can see the full yellow outline here so this is what the player is going to see from the camera I'll click a pistol over here Center in on that zoom in there and now let's make some animations player control a add an animation player node here animation new let's make an idle animation and let's make it three seconds long so I'll click pistol and then I'll key position create a reset track same with rotation okay then I'll go halfway over here and I'm going to rotate it forward in the x-axis a little bit and move it down on the y-axis just a tad then I'll key position and rotation again I'll select all of those and then over here I'll right click on easing and set that to ease in out click this to set this to looping and I'll make this autoplay as well let's see what this looks like all right that looks pretty good so I'll stop I'll go to reset and then animation new call this one move one second is fine I'll set the snapping to point two five and then add zero seconds here I'm going to key the position no need to create a reset track at 0.5 I'll do the same thing and then at 0.25 I'm just going to move it a little bit to the left and a little up I'll key that position and then 0.75 a little bit to the right a little up and I'll key that and then so at 0 and 0.5 I'll shift-click both of those I'll right click and I'll ease out on both of those and then the other two shift click them and I'll ease in on those I'll also set this to looping and that looks good to me so I'll stop that again go to reset animation new one more animation here I'll call this one let's get rid of that one not shot I want to call it shoot and I'll make this one 0.4 seconds and I'm going to key the position and rotation here at the end of the animation and then I'll go to the front and for this one I'm going to pull it back on the x-axis a decent amount and I'll pull it up a little bit and then I'll key position and rotation and I'll select both of those and I'm going to ease out and this one doesn't need to Loop and that looks pretty good to me so I'll save that and we're done with our animations so we've got our animation set up now we just need to add some logic in the player script so that those animations play Under the right circumstances I'm going to start by clicking the animation player node and then in playback options I'm going to set the default blend time to .05 this is just going to make it so that when we swap between these animations they automatically blend for a little bit and it's going to look a little bit smoother okay so now let's go into the player script I'll close this panel here go up top let's get a reference to the animation player at on ready bar anim player equals animation player so if the player is moving and they're on the floor we're going to play the move animation otherwise let's play the idle animation I'm going to put that logic right here above move and slide so if input dur is not equal to vector2.0 and is on floor anim player dot play Move whoops move and then if that's not the case else anim player dot play idol so let's take a look at that okay so we start with idle animation when we move it swaps to that when we jump it goes back to idle okay perfect so now we just need to add shooting so we're going to start by adding an action input for that so project settings input map add new action shoot down here I'll map it to Mouse buttons left Mouse button okay and let's detect this input in unhandled input right here so if input is action just pressed shoot and we're going to use the animation length of shoot as the cooldown for shooting so we need to check to make sure that that animation isn't already playing so and nmplayer.current animation is not equal to shoot and this is a little bit long so I'm going to add a backslash here and tab that over so here it will be we'll make a function called Play Shoot effects and then let's make that function down here so Funk Play Shoot effects and then anim player dot stop whenever I'm doing important animations like this I typically will stop the animation player first it can be a little finicky sometimes so Adam player dot play shoot and currently moving idle will uh over override this in the physics process function so we just need to check to make sure that this isn't playing before we swap to these so up here I'm going to add if anim player dot current animation is equal to shoot I'll pass and then I'll change this to else if and so with that okay we're good with idle and move and then if I shoot the shoot animation plays nothing's overridden by it okay everything's looking good and all we need to do is add a muzzle flash okay so let's add that muzzle flash so I'm gonna go back to the 3D view here back to one viewport and close this panel here I'll click pistol control a at a GPU particles 3D here let's call it muzzle flash and then let's have it positioned right in front of the gun barrel like this try to center it okay then over here I'll set the amount to 1 for drawing make sure you've got local chords checked process material new particle process material and then in gravity set that to zero draw passes pass one let's make a new plane mesh and have it be 0.5 by 0.5 meters set the orientation to face Z and then a new standard material 3D okay and then I'm going to save this currently in Godot 4 beta 12 there are some known bugs with GPU particles 3D and spatial materials that will cause the engine to crash and I'm sure that these will be fixed soon but one workaround that I've found is I'm just going to close the scene and then reopen it and then I'll keep going here so I'll go back to that material and billboard I'll set the mode to particle billboard and then in Albedo the texture that we're going to apply here is star underscore zero six from the Kenny particle pack so I'll drag this in and then I'll apply this yellow white color to it and then transparency I'll set to Alpha shading unshaded vertex color uses Albedo because we're going to be using the color ramp from the particles material okay and then we'll go over the particles material right here and so color ramp right here color color ramp gradient let's go here I'm going to add a point right here pretty close to the left side and I'll set it to White and then the ones on the ends I will set the alpha down to zero okay and then I'm also going to go into angle and set the minimum to 45 degrees just because I like that orientation more then the last thing I'm going to go to time and set the lifetime to 0.25 and I'll set it to one shot okay and now in the player script let's just get a reference to the particles so add unready VAR muzzle flash equals camera yep so that node path all the way to muzzle flash and then down in the play Shoot effects muzzleflash dot restart kind of a similar thing to the animation player here when I'm playing something over and over again and it's a one shot I just find that using restart helps to keep it from stuttering and that muzzle flash dot emitting equals true and let's take a look okay and then we've got our muzzle flash effect all right so it's time to start thinking about some of the multiplayer aspects of this project and we're going to start by making a main menu so that players can choose to either host or join an instance of the game and then later when we start wiring that up I'll explain a little bit about how the logic of that all works so I'm going to go back to the world scene over here and I'm going to start by deleting this player node here that was just there for testing purposes we're going to instance them in later in a different way and then I'm going to go to the 2D view close this panel and then on the world node I'll click that and Ctrl a add a canvas layer and to that I'm going to add a panel container and I'm going to name that main menu and then I'll give that a margin container and I'll give the margin container a vbox container and then in there everything everything else is just going to be in the vbox container I'm going to give it a label I'll also give it a button and I'm going to call that post button and then I'll duplicate that Ctrl D and I'll call this next one join button and then last but not least Ctrl a I'm going to add a line edit down there and I'll call the line edit address entry okay and now let's add some text here for the label I'll say main menu and then I'm going to set both of these to Center alignment host button for the text I'll put host join button text is going to be join and then address for the placeholder text I'll put enter address to join here and then I'll also align that Center okay now let's go to the main menu and click this and select full rect for the anchors margin container theme overrides constants give all of these 15 so it's got some space around the edges and then V box container theme overrides constants give it 15 separations so there's some space between them and then for the main menu click uh hold alt and then click one of these orange buttons here on the corner and then just drag it in so it's nice and centered that looks good to me let's make sure everything looks good yep you can click these type stuff in here all right uh let's wire up these buttons and get some references to this so host button click that and then go to the Press signal here double click that connect same thing with the joy button with pressed connect and I'm going to remove spaces here because I only put one line between my functions and up here I'm going to get references to main menu and address entry so at onreadyvar main menu equals and you can actually just drag this in right over here okay and at onreadyivar address entry equals address entry okay and we are ready to start wiring some of this up then okay so let's say the player clicks the host button well the first thing we're going to want to do is we're going to want to hide the main menu with main menu dot hide and then we're going to have to create a server and that server is going to have to live on an open port so I'm going to go const Port equals 9999 typically any port over 1024 should be open so this will probably work fine for you then I'll go VAR e net here equals e net multiplayer peer dot new and then I'll create the server down here with enetpear.create server now I'll pass in that port number then I'll go multiplayer dot multiplayer peer equals that enet pier and so now once this runs the server should be up and running we just need to spawn in a player for the host so let's get a reference to the player scene here cons Capital player equals whoops that equals preload and then I'll drag in the player scene here okay so now let's make a function down here so that we can actually spawn them Funk add player here ID bar player equals player dot instantiate player.name equals string peer ID this is going to be used for Authority purposes later and then add child player okay so now you just call it from up here so add player and then we can get the peer ID for the host by going multiplayer dot get unique ID okay so let's play this the the first time that you run this it's probably at least if you're on Windows that's what it does for me it's probably going to ask you if you want to give this application access to your private public networks and make sure that you give it access to public networks if you want to be able to play this online with friends later but we can see that it's working just fine right now so let's set up the client now as well and I'm going to do that by copying these three lines right here so I'll paste that and we're going to change create server here to create client and then we need to pass it an address and because we're just testing things locally for now we can just hard code this to localhost and then we'll pass in the port right there and we don't want to call add player on the join button we only want to spawn players from the server so how do we spawn a player when the client joins well we can wire up a signal here on the server by going multiplayer.pear connected dot connect and we'll connect it to add player so peer connected is a signal that's going to emit on the server every time a client connects to it so it's going to connect to adplayer it's going to pass in the new peer ID and it'll spawn one every single time the client connects so let's go to debug run multiple instances and we're going to run two instances now so let's see so up here I'll host and then down here I'll join and so what happened here is two players spawned you can kind of see the animations going together but they are colliding infinitely and it's propelling them upwards so the way that I'm going to solve this is I'm just going to make it so that players don't Collide and I'm going to change the player layer here to 2 then I'll remove the one and let's try this again so host and I'll actually move over here and then join and there we go so two are connected however the host the server is controlling both of them right now so we're going to have to fix that okay so a second player connects when the client joins the server but currently they only spawn in the server and they're both being controlled by the server so there's a couple things we have to change here but the first thing that I'm going to fix is I'm going to spawn the players in both instances so I'm going to go to the world scene I'll click World control a and I'll add a multiplayer spawner node then I'll go to spawn path and we're instancing the players as a child of this world node here so I'm going to select this as the spawn path then I'll go to auto spawn list add element click this folder icon then I'll select player.tscn because this is what we're spawning and this is what we need spawned in all the clients so I'll open that there save and then let's try this again so I'll host here and I'll move over here then I'll join and then we can see that the client connects as well and you can't see it because you can only see one player but they're actually both spawned here they're just both in the same exact spot because the authority hasn't been set yet so currently we're just controlling both players and it's still the same thing in this instance as well so the next thing we'll do is we'll fix that in order to make it so that the server and the client can only control their corresponding players we need to set up the authority and connect it to their corresponding peer IDs and since we set the player name to the peer IDs this is going to be pretty easy I'll go back into the player script over here and then I'll make a function above ready called func underscore enter tree and then here I'll go set multiplayer Authority string name to end because this has to be an integer and name actually isn't stored as a string and then we're going to have to check for this Authority in ready unhandled input and physics process so starting with ready we'll do if not is multiplayer Authority so if it's not the authority return don't execute this code so we're going to add one more line here and that is we want to make sure that the camera is current for the correct player character so here we're going to say camera dot current equals true so that will make that the case and then we'll just copy this line and we'll just drop it in the first line of unhandled input and physics process as well and then I'll save and then let's take a look so over here I'll host okay and then I'll join here and there we go I'm only controlling one character over here and then on the server it's the same case but they're not synchronized and that's the next thing that we have to fix so just like with the world scene and the multiplayer spawner node godot4 introduces a really simple way to synchronize things between scenes and I'll add it here I'll click player control a and it's going to be the multiplayer synchronizer node so all we have to do is add the properties that we want to sync in here so the ones that I'm going to sync are player position oops player rotation and Camera rotation just so we can see that pistol move up and down okay and that's it it should work just like that so I'll host here again and I'll join a client here and boom up and down left right see moving let's check the other one yeah it works Cure Magic all right so we've got some stuff synchronized now but one thing that we don't is actually the shooting animation you'll see I'm shooting in one game instance and the corresponding player isn't shooting in the other and that's just because the play Shoot effects function is only being called locally so how do we call it in the remote instance well what we have to do is we have to add this annotation here called RPC but if we call this as an RPC function it's only going to be called on the remote instance so we also need to add something here called call local so that it's called in both and then in order to call this as an RPC function instead of calling the function like this we call it by writing the function name and then writing RPC just like that so now if I start this up I am shooting in both and you can see that in the remote version of the player the animation the idle animation doesn't start up afterwards so how do we do that well what we're going to do is we're going to set up a signal from the animation player so I'll go to animation finished connect that up to the player and then here I'll just check if random name equals shoot so after the shoot animation finishes anim player dot play title and let's just take a look at that okay and you can see the idle animation resumes on the remote player as well Okay so we've got the necessary pistol animation set up now but we don't have any shooting taking place in the sense that we're damaging any players or anything like that so let's set that up now and the first thing I'm going to do is I'm going to give the player an Aiming indicator with clicking the camera and Ctrl a at a text direct down here I'm going to search for a circle I'm going to use Circle 5 from the Kenny particle pack I'll drag that into the texture field over here I'll click the anchor presets here go to full rect stretch mode I'll use keep aspect centered layout transform right click size copy value pivot offset I'll paste that value and then I'll divide both of those values by two and then for the scale I'll set this to 0.03 and then this is going to work just fine as our aiming indicator so now let's give the player a raycast so they can detect enemy players when they shoot so I'll click camera 3D control a raycast 3D over here set the Collision mask to two because this is the layer that we set the players to and then Target position I'll set y to zero and Z2 minus 50 so it goes nice and far in front of the player and then I'll go go into the player script and let's get a reference to the raycast here at onreadybar gray cast equals then I'll just drag it in right here and let's set up a health variable as well our health equals three so I'll say that after the player gets hit three times let's respawn them so here when we're shooting let's check to see if we're hitting a player so if raycast that is colliding then let's get a reference to the hit player VAR hit player equals raycast dot get Collider okay and now what you might think to do is hit player DOT health minus equals one but this won't work because this is lowering the health of the local Adobe Player and what we want to do is we want to lower the health of the remote enemy player the one that has the authority for it so we're going to make an RPC function for it down here so down here Funk receive damage I'll say health it's minus equal 1 at if health is less than or equal to zero we'll just do a very simple sort of respawn here by setting the health back to three and the position equal to Vector 3 dot zero so because we're going to be using this as an RPC function we have to put the RPC right here and we're going to have to put another thing in here and that is any peer because we are calling received damage from the player that is dealing the damage and that would mean that we're calling it from the player that doesn't have the authority so here you'll notice that play Shoot effects play Shoot effects you're calling it on the player that you have the authority over but here you're calling it on a player that you don't so we need to add this otherwise you wouldn't be able to call it on enemy players so up here I'll replace this with hitplayer DOT receive damage and we're not actually going to use our PC here we're going to use RPC ID instead because let's say that we had four players playing together our PC would call it on all three of the remote players and we only want to call it on the one that has the authority so we'll say RPC ID and then we'll pass in here hit player dot get multiplayer Authority and then let's take a look so host and I'll move forward a little bit join then if I hit them three times two three they are respond okay so the players have a health value but we don't actually have a way of telling what our current health is so what we're going to do is we're going to add a health bar and we're also going to move the aim indicator here to a heads-up display in the world scene so I'm going to right click this text direct I'll cut and I'll save the scene then I'll go back to the world scene canvaslayer control a at a control node and I'll call it HUD and then I'll go over here full rect go to Mouse change the filter to ignore then I'll right click HUD and I'll paste our text direct there and I'm also going to go Ctrl a add a progress bar I'll call it health bar I'll make this full rect as well then I'll hold alt and drag one of these Corners in to make it a thin rectangle drag and hold shift bring it up there uncheck show percentage max value all set to three same thing with value also set to three okay and then I'm going to go down to theme overrides Styles fill style box flat I'll change this to a bright green color and for the background style box flat I'll change it to a bright red color okay now let's get reference to some of these in the world script so at on ready VAR HUD equals and I'll drag the HUD path in here and at on ready bar health bar equals and I'll trade the health bar in and we're going to take the HUD here and we're going to close this eye here we're going to make it Invisible by default and then we're going to show it when the player joins so in both of these we'll just go hud.show right after we hide the main menu hot nutshell okay and so for updating the health bar we're gonna have to emit a signal from the player so I'll go back to the player script over here and then up top I'll Define the signal so all the way up here signal Health changed then we'll pass in a health value there and we'll admit this every time the player receives damage so healthchange dot Emit and we'll just pass in the health value there and for connecting it we'll go back to the world script here for the server we'll connect it in the add player function here so if player dot is multiplayer Authority then we'll say player.health changed dot connect and we'll connect it to a function that we haven't made yet but we're going to call this function update health bar all right so I'll copy that let's make that function quick so func update health bar it'll receive a health value parameter and then we'll just go healthbar.value equals health value and that's all we need to do and for connecting the players in the clients we're actually going to use the signal from the multiplayer spawner so I'll go to multiplayer spawner node and then connect this spawn signal to world and then I'll copy this logic right here that we just made for the server paste it in here and then I'll just change player to node and we don't even need to check to see if it's a player because the player seems the only thing we're using the multiplayer spawner for so it should work so let's take a look host and that'll join here and it's updating just fine okay what about for the client all right it works for both we could keep adding features and fixes to this all day but the only other thing that I'm going to address right now is that when a client disconnects you can see that they still stay spawned on the server and they would stay spawned on other clients as well so how do we take care of that well it's pretty simple I'm just going to go back to the world scene and we're going to handle it to a similar way in this host button pressed function here with this peer connected signal well guess what there is a multiplayer dot peer disconnected signal so we're going to connect that to a function called remove player so I'll copy this and then I'll go under the add player function here Funk remove player this one also passes in a peer ID so I'll say VAR player equals get node or null string up here ID because the players are named after their corresponding peer IDs and then I'll check if player so if this is not null then player Dot Q free and this should just work yep you can see it's cleared on the server and the multiplayer spawner I believe handles just clearing that on the clients as well all right so how do we actually connect with our friends over the Internet to play this game together well at the bottom of the world script I'm gonna make some room here and I'm going to make a function Funk UPnP setup by our UPnP equals upnp.new and first we're going to discover our UPnP device so I'll make this here your UPnP device should be your router with UPnP enabled it's a setting in your router settings and for me it was disabled by default I think it's enabled by default on most but it's probably something that you want to double check either way and we're going to be throwing some errors in this function here if anything goes wrong so the first thing that we're going to check is make sure that this discovery is successful if not we're going to print an error code and I'll show an example of this failing later and what you might do there anyway moving on we're going to check next that it's a valid Gateway using these functions here and if it's invalid then we'll just print an error that it's an invalid Gateway and then after that assuming this stuff all works we need to create the port mapping that does the automatic port forwarding this is the nice thing about UPnP and if that Port mapping doesn't work we want to make sure that we print an error here as well but if this all works this means that UPnP should be set up and people should be able to connect to the host so if that does work then we're just going to print a success message here and this is going to also print the external facing IP that people should be able to type in in that join address field and then join the game so let's take a look at this well first we actually need to set this function up in the host button pressed so after the players added I'll do UPnP setup right here okay so let's start this up and then I'll click host and this probably takes a second to set up okay so it actually failed so I don't have UPnP enabled on my router right now and you can see here that Discovery failed error 27 and so if I go over to the Godot documentation I can go to the UPnP page here and then I can go down and I can see all of these error codes down here so if I go down to 27 this one says UPnP result no devices so it wasn't able to find my device and so for me that's because the settings not enabled but let me enable it and then let's see what happens okay so now I've got UPnP enabled on my router so let's try hosting this again should go a little bit quicker this time and there you go you can see that it actually joined properly this time and I didn't actually print my full address I'm just printing a random digit because I don't want to display my external facing IP address to the internet but this is this is working so if you removed this it would print the entire join address and then you could hand that off to your friends and speaking of which we are just going to go back up here to this uh create client up here and we're going to now remove the hard-coded localhost here and we're going to change this to address entry dot text so that now people will enter the IP address here click join and they'll actually be able to join it over the Internet so now we just have to export this okay so now we need to export the project so I'll come up here to project export and I'll add and I'm on windows so I'm going to export to Windows desktop if you don't have any export templates downloaded yet this menu should greet you with a message that you don't have any and it should lead you right to a place where you can easily download them but anyway I already got mine downloaded so here I'm going to go here and I'll set the export path to I'm going to create a folder called exports I'll save that and here I'm going to export debug only export project then I'll call it FPS prototype.exe export with debug checked we want to make sure that we're exporting with debug here because currently the the console log is important the host receives error messages and their external facing address through the console so we want to export with debug so I'll save that and it exported okay so I've got my export directory here and I'll typically just highlight everything here and send it to a compressed folder just like that and then I'll share this folder with my friends and then whoever's hosting you're probably going to want to open it with this console here so that this way your external address will get printed here when you set up the host or it'll print an error if something goes wrong but otherwise you just need to afford that address along to anybody who wants to join they can paste it right in here click join and you're good to go thanks for watching and hopefully you learned something if you enjoyed the video feel free to subscribe to the channel or follow me on Twitter it's always appreciated thanks again and more big tutorials to come in the future
Info
Channel: DevLogLogan
Views: 204,947
Rating: undefined out of 5
Keywords:
Id: n8D3vEx7NAE
Channel Id: undefined
Length: 45min 39sec (2739 seconds)
Published: Sun Jan 22 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.