Basics Of Multiplayer In Godot 4!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys this is Mitch with finepoint CGI and today we're going to talk about how to do multiplayer with Godot so this video is going to run us through how to set up a basic peer-to-peer connection how to set up a basic character controller and that whole process we're going to set up spawning your players and passing information back and forth we're also going to talk about the node synchronize the multiplayer synchronizer node inside of Godot and we're going to talk about some best practices and ways to optimize your stuff by using tweening and finally we're going to run through and actually host our server on the web so that we can access it and play our game so that's what I have in store for you guys today so let's go ahead and get started okay so the first thing we need to do is we need to actually build out our scene now I have here a couple of assets that you guys can pull down if you would like so I have a main character I have a main tile set things like that and I have a Famas here as well now these come courtesy of the modern assault rifles pack I'll leave a link to this in the description below and the cyberpunk platform pack so you can actually come down here pull down this and pull down this and you will have everything that I have up to this point now if you don't want to go through the process of building all of this out that's totally fine I actually have in the description below the starter project for this so you can technically just skip to the next point in this video and it will uh I'll have everything set up and and we can go ahead and get our multiplayer going so the first thing we need to do is we need to create our player so we're going to create a 2d scene we're going to right click change its type and we're going to type character their body 2D we're going to double click on that type player we're going to right click add a child node add an animated Sprite to D I'm going to come over to my Animation Sprite frames click on new Sprite frames and then go ahead and click on it and then we need to actually set up our idle animation so I'll come into here I'll click on this guy right here and that will allow us to open up a file I'm going to pick my actual uh character sprite and I'm going to set my size to 32 by 32. I'm going to set my offset by one and that seems to be the one that I need to do for this but in your case it might be different for my idle animation it is right here so I am going to click and drag and hit add six frames now if I hit F if I zoom in here you can see here's my character now he's a little on the fuzzy side so I'm going to come down to my texture I'm going to change my filter to nearest and that's going to give me a nice crisp texture here now I need to add another animation for running around so I'm going to click add animation I'm going to click on this again I'm going to double click on main character I'm going to change this once again to 32 on 32 and I'm going to change the offset by 1 and I'm going to zoom in and find my run animation now technically I might be able to get away with just zero offset for this specific animation so I'm actually going to do that one and I'll take these guys right here I'm going to add them in and I'm just going to call it run if I hit play you'll see that we have a run animation now it's a little on the slow side so I'm going to change the fps to 10. that way it's a bit more Dynamic it's a bit quicker things like that and that should work pretty well for what we have now once we have this we have to add Collision to our player so we'll right click add any child node we'll add in a collision shape 2D we will click on this guy we're going to click on rectangular shape we're going to make it about the right size if we actually come into our default here and we take a look looks like our Collision shape can come up to here out to about here and I believe I'm probably going to have to go up to we check our run animation you'll see that we are going up and down so our Collision shape needs to go down just a tiny bit and that should work just fine now I run animation we might need to make some adjustments to it let me get rid of it real quick let me click on this reselect this guy 232 by 32 and don't do an offset this time and let's just grab these guys let's zoom in real quick see if that fits it seems like it's going to so I am going to take it like that we'll add in our frames and there we go that's a lot better but before we add our gun or do anything else I'm going to come in here and grab my animated Sprite and my Collision shape and I'm going to drag them up so that they're perfectly in line with the uh line right here and that's basically going to say that's the bottom of my character now we got to add in a gun and the ability to rotate our gun so we're going to right click our player and a child node We'll add in a node to D we're going to come in here I'm going to drag this guy up to about the center of my player I'm gonna double click on it and I'm gonna rename it gun rotation and I will grab my Famas I'm gonna drag it in like so I'm going to click on here change the texturing to nearest and then I'm going to change the size of it so that it actually matches up with my player so we'll make it about I don't know about this big give or take that might be too small that might be too large just kind of depends on how we feel so we'll say that that's good and I'm going to rotate my player I want him to face this direction so I'm going to come in here grab the Sprite and I'm going to click on offset flip H that'll flip my character and I'm going to take my Famas put it underneath my gun rotation and what that's going to do is it's going to allow me to rotate my guns you can see now my gun can rotate like this so that'll give me the ability to shoot around and things like that we'll have to come in and clean this up later now we're going to need a place for our bullet to spawn so we're going to right click our gun rotation at any child node we're going to add in a node to D and I'm going to drag that out to somewhere here ish so the Bullet is going to spawn directly out right here and we should be good to go now I wonder if I could get this Famas to go up just a tiny bit but it doesn't look like it's gonna play nicely because it's all within one pixel increments so that's totally fine that'll work so now once we have this I'm going to hit Ctrl s I'm going to name this as player.tscn so I have my little player here I'm going to come in and name this as bullet spawn and we should be pretty much good with setting up our player all we have to do now is just basically add in our code so we're going to right click our player attach a script and we're going to call it player.gd now this will give us all of our basic movement moving left moving right things like that so thankfully ninety percent of our stuff is already done for us and to test this let's go ahead and create a scene so we'll go to scene new scene we're going to go 2D scene and I'm going to right click add any child node I'll add in a Sprite to D I'm going to drag on the icon I'm going to change the size of it to not that and I'll make it nice and long and kind of small like that and I'll drag this guy down something like that and then I'm going to add Collision to it so I'm going to right click add an HL node we'll add in a collision shape I'm going to add in a rectangle shape and I'm going to grab this and just kind of snap it down to where our floor is now of course this is going to change when you actually build out your level but this is a good way to test your game out just a tiny bit so I'm going to hit Ctrl s test scene and I'm going to drag my player in like that now he's a little on the small side but that's okay that should be fine I'm going to control s and we'll hit play now you see our character just kind of falls through the world so what happened well you can't have a collision shape without having some kind of object underneath it right you need to have a static object a kinematic object or a rigid body or Collision shapes to matter so we're going to right click our node 2D we're going to add a child node We'll add in a static body 2D and we will put these guys underneath our static body 2D and that should hopefully work so we'll hit play you can see that our player now exists we can hit left and right and jump and they jump easy enough now technically the height that this player is jumping is a little bit too much and he's probably a little on the small side so what I'm going to do is I'm going to go into my player we'll click on our animated Sprite we're going to make it a little bit bigger so I'll just grab on to my size anchors here I'm going to drag this guy up so that he's about yay big and then I'm gonna do the same thing with my Collision shape we'll just make it nice and large to kind of match our player we'll grab our gun rotation we'll put it at the center of our player so I'll click on it like this and then I'm going to change my Famas put them about here make them much larger because it needs to be a lot larger to kind of match the player so we'll kind of do one of these numbers and then I'll grab my bullet spawn like so and put it out to the front of my gun now if we go back to our test scene hopefully that'll make him a lot easier to see so if we hit play that's a bit more realistic or a little bit better at least that should work just fine for now now we need to rotate that gun to match our Mouse position so we'll go in here we'll come down here and we'll say dollar sign gun rotation dot dot look at and then we need to actually get where our Mouse position is and the best way to do that is to get viewport dot get mouse position like that and now if we come into our test scene we hit play you'll see our gun now follows our actual Mouse perfect you can see there's a slight problem with the gun going down here like this so you might want to only allow them to shoot at like this angle maybe something like that but for the sake of this tutorial it's not that big of a deal so we'll go with that now to get our player to be able to shoot we actually need to set up a bullet so that should take five seconds we can go to our scene hit new scene make it a 2d scene we'll just come in here grabbing the Godot icon just because I'm a little on the lazy side and I don't want to go find a bullet so we'll just do that we'll change the icon and adjust its size to be nice and small so we'll go with something I don't know about this big give or take something nice and Tiny we'll make it right about here and I will pull this forward like this because it's a bullet so it's going to spawn out of the barrel of the gun so we want to make sure that it kind of you know is offset to the right a little bit because when an instance it's going to instance right here so we want to make sure that it's correct now we can right click add in a new node We'll add in a collision shape and we're going to match our Collision shape with a rectangular shape so we'll pull this out like this we're going to pull this down like so and up like that there we go and we need to actually change our node 2D to actually be some kind of node that can work now you could do this in a lot of different ways you have a lot of choices here if you do a static object you can move the object just by setting its position and go from there or you can choose to use a character body generally speaking I like to use character bodies but it is completely up to you so we'll come in here I'm going to make this a character body and I'm going to right click and attach a script I'm going to call it bullet and you can see that it gave us a bunch of boilerplate code now ninety percent of the spoilerplate code is not useful to us so stuff like you know gravity and all that speed that's all pretty useful jump velocity is not going to be and we don't really need to worry about handling or jump or anything like that and we don't really need to worry about Direction really all we have to worry about is just going to the right or I guess going forward whatever forward would be considered at a specific speed so so in my case I'm going to set speed to 500 and I'm going to come down here and pull out this entire section here all I got to do is say velocity is equal to speed multiplied by some kind of directional value when you fire a bullet out of a gun you need to tell it where or which direction it's going so we'll add in a VAR direction we're going to make that a vector two like that and then on ready we need to set what that direction is so we'll say Direction is equal to Vector 2 0 comma one dot rotated rotation and that's going to allow us to choose which direction our bullets going to get fired based off of the orientation of the bullet and then all we have to do is just say multiply it by Direction and we're good to go and then we can just move and slide when hit control s I'm going to say bullet and I'll use a capital B and that should work so now if we hit play you'll see a bullet falling through the sky so that's okay what happened right well so this needs to be one and then zero and that's my fault so if I get rid of this and I run this let's see what it does and there you go you can see it works now something that we should do is we should probably move this up above our velocity that way we actually start getting gravity so if we actually reduce the speed of our bullet down to something small like actually if we just increase the gravity I think that'll make things a little bit more apparent so we'll just increase the gravity multiply it by one and then you guys will be able to see what I'm talking about so you can see how the bullet now Falls as time goes on the reason why it wasn't working before was because this was down here and it was getting set by Direction which immediately sets at zero one so therefore gravity is no longer taken into effect so it's just something to keep in mind so that's why we want to have it like that now gravity of one might actually work but it's up to you guys on how you guys want to approach it I think I'll stick with one because it seems like it's going to work the best even though in my testing before it didn't really do very well so sometimes things work sometimes things don't now once we have that we can click on our player and we have to shoot our bullet now shooting our bullet is going to be easy we're basically just going to instance it right here right yes it should be relatively easy all we need to do is just come in here and say at export VAR bullet is equal to packed scene and then we can just come in here and say hey if input dot is action just pressed well in this case Godot is telling me fire which means I must already have that already put in you guys don't have fire but don't worry in a second you guys will so this was not supposed to come up but I think Godot is just being weird or I forgot to delete something so if we come up to our project project settings we go to our input map you can see we actually do have our fire here so let me get rid of that real quick let me add an action buyer like that and then we'll click on the plus and then we will click on our input and you'll see it says left Mouse button we'll click OK hit close and then that will allow our fire to work now I forgot to delete that so that's why it is showing up for me now once you click on fire all you have to do is instance your bullet right so VAR B is equal to Bullet dot instance or instantiate in this case so once we instance our bullet we need to actually put it underneath something for it to work so we'll say get tree dot root Dot ADD child B and that's going to allow our bullet to actually show up now something that we have to keep in mind is that we want to be able to set our rotation and our position so we'll say B Dot Global underscore position is equal to dollar sign bullet spawn dot Global position like that and we do the same thing with our rotation because we want our bullet to rotate with our gun right so when our gun is rotated the bullet follows along so we'll say rotation underscore degrees is equal to dollar sign gun rotation Dot rotation degrees and then if we go back to our test scene here and we hit play you should see then when we click we get a null instance so what does that mean well if we look at our player you'll see our player has bullet empty so that means we have to go to our player scene we got to click on our player and we have to pass in our bullet right here and then in theory if things are done correctly we can hit refresh we can click and now we can shoot bullets easy enough so at this point we're pretty much good to get started with our multiplayer now I'm going to do a quick Montage of me coming in and making the scene a little bit prettier but that's not going to have any bearing on the tutorial so you guys want to watch that's fine if not it'll be gone in like two seconds so hopefully it'll be quick so I will be right back thank you all right now that we have this which is going to be a very basic environment so that way we have something to run around in and things like that so you can see how that looks kind of like this you can see our character can run around they can jump they can move around like that simple enough and they can shoot their gun all right and once we have all of this all we have to do is set up our multiplayer and that should be relatively easy to do that we're going to need to actually build out a multiplayer connection screen so we'll come into scene new scene we're going to add in a user interface we're going to right click add any child node and I'm going to add in a button and I'm going to put in that button host so I'm going to say host here and then I'm going to do the same thing but it's going to be join we'll pull this across and we'll type join like that and then I'm going to do one more so that way I can start my game so we'll put it down here I guess over here and say start game like that and now we have to actually build out our code for this so when you do your multiplayer code you actually need to do quite a bit of prep work so we're going to call this our multi-player controller and we got to set up some things before we can actually get going so first things first we're going to need to create some variables up here I'm going to hit at export and I'm going to say VAR address and I'm going to make that equal to quote 127.0.0.1 now this is going to be a temporary address because we're going to need to change it I'm going to come in here I'm going to name this host and I'm going to name this joint I really should have just named that in the beginning but I did not we'll say join and start game and I'm also going to come in here go to node on button down I'm going to connect that to oh I'm going to connect that to here I'm going to do the same thing with join I'm gonna do the same thing with start game there we go and once we have these three things we need to set up a bunch of stuff so first things first we're going to hook up some signals here so first we'll say multi-player dot peerconnected dot connect and we'll pass in our callable now in our case I'm just going to make a function down here that's called funk player connected and we'll pass in an ID value and we'll just print out player connected ID and I could just pass in Connect player connected I'm gonna do the same thing well with disconnected so multiplayer peer disconnected dot connect and we will do player disconnected copy this guy player disconnected ID and we will print out whether or not that player has been disconnected like that and then we need one for connected to server and then one for connection failed so connected to server and connection failed I'm just going to grab this guy paste grab this guy paste and really I should just follow this bit of naming convention here so we'll actually just change these guys like this just to kind of match and we'll go from there so we'll say funk connect it to server and we'll print connect it to server and finally connection failed and we'll say couldn't connect now let's talk about what some of these are for so peer connected what is peer connected for this gets called on on the server and clients when a someone connects right this does the same thing this gets called on all of the servers and clients when they disconnect this gets fired only from clients okay and this one gets fired only from clients as well so what this means is this gets fired whenever somebody connects and this gets fired when when a client connects to a server now the reason why that's important is because if you need to send information from the clients to the server this is basically how you do it you would do it from here not from here okay and that's kind of something to keep in mind now once we hit our host button that means we're gonna set up an actual host so what do we have to do to actually host well first things first we need to make up here and we need that to be an e net multiplayer peer and we'll say dot new now it's going to create a new instance of that now we do need to create a server and usually you want to check for an error so we'll say error is equal to peer dot create server and we'll need to pass in a port now we don't actually have a port up here so let's set one and we'll set our port to 8 9 10. just because 8 9 10. I think it's a fun port to have so we'll create our Port comma and then it's going to ask a maximum number of peers now in my case the game is going to be a two player game though if you want you could have 6 or 10 or 20 people if I remember correctly it's a Max of 32 so you can only have up to 32 players at one time that's something to keep in mind so if error does not equal okay then we can print cannot host and we'll pass in that error like that and we're going to want to return if not then we're ready to actually get things moving now something that I like to do is I like to do a little bit of compression here so first things first let's type Pier dot get host dot compress and you can see that they have a couple of compression here's a little bit of compression algorithms here now if you look to enet connection there is actually an enumeration here that we can use so we can have compress none which basically means it's not going to compress at all that's really good if you have um a like a lan connection or something like that it's not a big deal and it works pretty well compress range encoding is used with small packets and it's not a super efficient algorithm but it does really well for you know least amount of CPU usage then you have fast LZ which basically allows you to have less CPU resources but it has more bandwidth and then compressed zlib is great for compressing larger things but uses more CPU and then Z STD is just the algorithm that's basically the general Middle Ground now what I would do is I would use just use compressor range encoder just in general it seems like it's a pretty decent impression algorithm so that's just something to keep in mind now you don't have to use it if you don't want to you don't have to set this up it's just that you're going to get a little bit more bandwidth usage than if you do compression if that makes sense now once we have our compression set we need to actually come in and set up our multiplayer peer so we'll say multi-player dot set multiplayer peer and I'm going to pass in my peer like that and that's going to set my peer this guy here my server as my peer so think of it kind of like this we created an object that said hey we want to host this thing right so think of like hosting as like a computer saying hey I'm ready to host this thing so we set this pure value as our host and then we are now setting and telling Godot hey we want to use that host as our peer so that way we can use our own connection and play our game if that makes sense now I'm going to put a print in here and say waiting for players and then I am going to go ahead and just wait for a second I'm not going to do anything else there is some additional stuff that we're gonna need to do but for right now this will work for what we're trying to do so once we have this we can hit control s because I just naturally do that and I'm just going to call it multiplayer scene I'm going to come down here to our join and I'm going to set up our join so that way we can actually join now something that we should do is we should make peer Global so I'm going to come up here and I'm just going to say VAR pier and I'll scroll down here and just remove our VAR like that now you don't want to locate the enet multiplayer peer until you're ready to go so that's the reason why I'm not doing it up here automatically on Startup because you know you may not want to have multiplayer immediately so there's no reason to kind of create that variable if we don't need to now if we come down to our join button we need to actually come in and figure out where we're gonna join so all we have to do is do the same thing so Pier is equal to e-net multiplayer peer dot new like that then we could say peer dot create client we have to come up with an IP address which we set up here address so address comma and then we need to come up with a port and we actually have a port set so our Port right and then we need to set up if we're going to use compression much like before so I'm just going to keep it at the same compression as the other one and you do need to make sure that your compression is set to be the same across the board so if you choose to do one you need to do the other on the other side so that's just something to keep in mind once you have that you can set yourself as the multiplayer peer like that and in theory that should work so hopefully this this will actually work so if we go to debug run multiple instances run two instances and hit the play button we can click host and we'll check out our output host waiting for players you can see right here and then if we click join we have a crash but it at least ran our peer connected it says invalid operand string and int that's totally fine so we'll just say Str and we'll wrap this guy in Str but you'll notice that our ID value here is one which means everything's working the way we expect it so if we hit play we try this again host join player connected one player connected that right some random number so what does that mean well player connected one means that that's the server player connected random number is basically saying a player has connected and we've assigned them a random ID that's gonna change every single time a player connects so it's something to keep in mind but our stuff is working which is amazing so what do we do now well if we click Start game well nothing's going to happen right because we don't have a game we don't have any code here to start game so what can we do to make our game start well we can do this thing called RPC and RPC stands for remote procedure call and basically that means that we're going to go out and call a function across all of our peers or technically it could be on any peer we don't necessarily need to do it on one specific peer but it's just something that we can need to keep it bind so when we click on start game how do we actually tell it to start the game well we could go and tell it to load our scene and instantiate it and then there you go right yes but no when you want to do an RPC it needs to be a separate function and it needs to have the proper decoration above it for it to know that that's an RPC so what does that mean for us well if we come up here and we create a function called start game like this and we tell to load our scene so VAR scene is equal to load and we're going to pass in our scene so we'll put in our test scene.tscn and we'll put dot instantiate like that and then we could just add it to our tree so get tree dot root dot ADD child like that and we'll add our scene like that and then I'm just gonna hide my actual scene like so and there we go now once we have here we could just say start game right and now it should work well no you need to actually tell everyone that they can call this scene so we have to use a decoration for that and the decoration we have to use is called at RPC now you'll notice that there's a bunch of options here any peer Authority call local call remote reliable unreliable unreliable ordered what does all that mean well it's actually pretty simple any peer means all peers will call it that means everybody that's connected when that RPC comes out everybody will call that function Authority will call only from Authority so only when the authority calls it will it actually go out to everyone else to call call local means that when I call that RPC I will also call that RPC on my end so I'll say hey I'm going to call that RPC while I'm here call remote will only call it on remote people reliable means that's going to be reliable which means we're going to use TCP that's going to be a lot slower but it's going to be reliable and then unreliable means that it's going to be a UDP which means it's going to be unreliable there's a possibility that other people may not get it we'll talk more about that in a little bit and then unreliable ordered means that it's unreliable but it will come in in an ordered fashion now in our case we're going to want any peer comma quote call local so now it'll work right well if we test it and we hit host join start game no so why not well that's because we're not actually calling it as an RPC we're just calling it s start game to start your game and to have it RPC you need to have dot RPC now you'll notice there are two options there's RPC and RPC ID RPC will call it across everyone so if I have five people connected all five people will get this RPC call and will run the start game function RPC ID will only call it on one thing so for instance if you wanted to have just the host or if you wanted to send an RPC to the host then that's where RPC ID comes in now I know that that's a lot of information and we'll cover some of the more fancy things in a minute but just remember that RPC calls everyone RPC ID is only when you want one specific person to run that bit of code 99.9 of the time it's going to be RPC id1 which will be your host so I'm going to say RPC and then I'm going to run this so I'm going to click host join and then I'm going to click Start game and you will see both of my players have started their game now you can see if I hit left and right and left and right they both can move their player which you'll notice that they're not synchronized nothing is happening so what's up with that well the reason why is because much like our join our code is not set up to work with each other okay and what I mean by that is in our player we don't have any kind of synchronization going on now we're going to need to have a whole nother conversation about setting this all up so that it synchronizes so don't worry we'll get to that but just know that there's a lot that's gonna need to change in here so let's go back to our multiplayer scene and let's do some fancy coding to get this to actually you know do a little bit more so first things first when a player connects to the scene I want to make sure that we keep track of all of the people that are in the project right so if there's one player or five players I want to know that those one or five players exist and I want to be able to have a reference of all of those players now you can do it one of two ways you could come in here and just have a reference to them here or in my case I think it's always good to have a game manager for that so I'm going to go to file new script and I'm just going to add in a game manager like that and I'm going to come in here and say VAR players and I'm going to make that equal to an object of some description and then I'm going to make my game manager Global by going to project project settings Auto load and I'm going to Auto load my game manager like so and I'll click add and that's going to make it so that I can access my game manager dot players at any time and I want that so that way I have a lot of flexibility here and now once we have our players here we can basically just add them to this list so we'll go back to our multiplayer controller here and when a peer gets connected right when you connect to your server you're basically going to inform the server that you've connected now I understand that we have the player connected with ID but what if your player has a custom name or if they have a custom icon or something like that right you want to be able to send that information across the wire and that's what connected to server is for so all we have to do is just come in here and hit at RPC and then we'll do any peer comma call local funk send Player information and you can pass in any information that you might want now in my case I'm just going to pass in the name and the ID of the player and you of course can pass in any amount of information that you want [Music] so I'll just say if not game manager dot players has ID if they don't have that ID then let's add it game manager dot players ID is equal to and we'll pass back and we'll build some kind of object so I'm just going to say name and we'll make that into their name comma we could say something like ID colon ID and then let's say score and we'll set that by default to zero now of course you could always pass any any from any information you want you could just pass whatever you would like but in my case I'm just going to pass this little bit of information and then I'm gonna check if multiplayer dot is server then for I in gamemanager dot players send Player information dot RPC gamemanager dot players I dot name comma I and that'll pass all that information to everyone and then from here we can basically call this function whenever a user connects so we could do it here on peer connected but that's not going to be great if we do it on peer connected then everyone's going to run this little bit of code here on their own machine so remember this gets called on the server and the clients and you could have it so that all the clients just broadcast their information out and you could just make sure that everybody's up to date that way or you could come into here and just say hey when on when connected to the server send my information to the server or you could tell it to send all of its information out to everyone when they're connected to the server and that's completely up to you on how you want to approach it in my case I'm going to say send Player information dot RPC ID peer ID is going to be one comma and we have to pass in their name and then their ID now we don't actually have a name so we'll just go with quote comma multiplayer dot get unique ID and that's going to pull back our ID now for this section here where we have the quote what we could do we can go to our control node add any child node let's add in a line edit like that and let's just say dollar sign line edit dot text comma get unique ID and then our line edit we can come into here go into our two player our 2D scene we'll just drag this guy out here maybe we can pull this out just a little bit right click add in a node add in a label like that and we'll just say name like that and I guess if you want people to use the stuff the way you would expect maybe we should take both of these guys put them up at the top and grab the rest of these guys just pull it down a little bit and there we go and that'll just give us a little bit you know better workflow so we can go back to our script we can say send our PC ID it's going to add it to our server and then our server is going to go and send it to everyone else so that everyone else is up to date now this is structured so that it's going to work with lots of players so you could have up to 32 players and this code will work um if you were just doing a single you know two player game this is probably a little bit on the overkill side but I want to make sure that we do it correctly now this is going to work but we need to make it so that our host also sets their information so we'll come in here and we'll just say send Player information I'm going to pass in my dollar sign line edit dot text comma and then my ID which should be one but just in case so that we're not gonna run into any weird funky things we'll just pass it in as you would expect so we'll say multiplayer dot get unique ID and that'll just pass back our ID now I know that there's a lot of information here but hear me out if I throw a break point here I hit play and then I set my name as test host you're going to see that we have a break here if multiplayer server for that send Player information we have a infinite recursion now why is that well that's because we have call local here so let's pull that out and then let's try that again so test host user join and then we'll click Start game now it's going to throw a break point here and I did that on purpose if we take a look at our Global as we go to our game manager and we take a look at that real quick you'll see that we have a dictionary of two you'll see we have an ID of one and an ID of some random string if we click on our dictionary you'll see we have a name test ID of one score of zero if we look at our other guy you can see we have name is user ID is this and our score is zero now in theory if we were to check our other remote it should say this as well that being said we don't really have a way to check that just because of the way that this all operates I don't think I can check actually I might be able to come in here oh there you go you can see right here we have both of them like that so I can go into session one and session two and you can see that we have as we would expect so that's more or less the goal now once we have this we're basically ready to move on from our multiplayer scene and into our actual gameplay so let's head over to test scene right here you can see here's our test scene we're going to actually come in and set up our spawning system okay and our spawning system is going to be relatively simple basically when the scene gets started we're going to Loop through our players and then we're going to spawn them in specific locations so how do we do that well first we need to actually get our spawn location so I'm going to right click our node 2D and add in a child node I'm going to add in a node to D and I'm going to drag that node 2D down we'll put it right about here we'll duplicate that node 2D and we'll put it right here now I'm going to grab node 2D number one I'm going to hit I'm going to make it a zero and I will make the other one one and what that means is index of zero and index of one so spawn location zero and spawn location one now we need a good way to get back that information what we could do is we could put it underneath another object so we could actually come in and say add child node to D and call this spawn location like that and we can grab these two guys like so and drag them underneath and that would work but what would be better off is if we have a way to just grab all that information so if we go over to node groups we can just call this a player spawn point like that and then we can just copy that go to the other one paste it and hit add now again if this is a two-player game you don't necessarily need to have all this fancy stuff you could just get away with saying here's where player one spawns here's where player two spawns and there you go right but in our case I want to make sure that everything is nice and well put together for expandability so we could have 10 or 15 players so if we come up here we get rid of our player because we don't need them for right now now we can basically set up our spawning so if we head over to our node 2D here which is our scene we right click attach a script and call it scene manager you will see that we have an empty script here now first things first we're going to need to instance our player so let's set up an export for that so at export VAR player scene and we'll make that a type packed scene like that now to get it to spawn our players all we have to do is say VAR index is equal to zero for I in game manager dot players spawn our players right so VAR current player is equal to player scene dot instance like that and then we can say ADD child current player now you might go okay that's great we've added our player but they're just there right they aren't spawned underneath our actual spawn locations well that's where some of the magic comes in so what we can do is we can Loop through our spawn locations so for spawn in get tree dot get nodes in group and I believe we called it player spawn point so we'll grab that player spawn point if spawn dot name is equal to our index then our current player Dot globalposition is equal to our spawn Dot globalposition like that and then of course we need to actually set up our index to be incremented so index plus equals one and there we go in theory that should actually just work so now if we test this if we go to our multiplayer scene we uncheck our little break point here we hit play test host player join start game we have a crash cannot call method instantiate on null value that's my fault so if we head over to our inspector underneath our test scene we click on our node you can see our player scene is empty so let's grab that real quick so player.tscn and then if we refresh it it's going to spawn the wrong scene so I'm going to click on that and hit refresh again so we'll hit test host player join and then start game you'll see we have another failure here inoperated stink string name and int so that's because this is not an Str so we'll fix that real quick and the reason why is because index is an integer and spawn.name is actually a string so we need to make sure that either it's casted as an integer or cast it as a string in my case I'll just cast it as a string that's fine so we'll refresh this one more time hopefully this will work test player join start game and you can see we now have two players now if I hit left and right you'll notice that well they're being controlled together and you also notice that it's not being synchronized so you can see if I move this guy left and right it's not synchronizing down here either so that's something that we're gonna have to take a look at but we did get our spawning to work and that's huge that's amazing that it actually worked so how do we get it so that our player can actually be controlled individually well that is where the multiplayer synchronizer comes in so Godot actually has this really cool tool that you guys are going to be mad at me if I don't tell you about and that is the multiplayer synchronizer it is basically a node that allows you to synchronize data across the Stream So if we right click our player add a child node and type multiplayer synchronizer right here you'll see that we have this little node now this node allows you to synchronize everything about your character so the question is how does this work well if I click add property to sync you'll see that I can click on any noted here and it will synchronize it across the way so if I click on player and hit OK and then I type position like that it'll synchronize my position awesome right so it just does all the work for us well kind of if I show you guys how this works so if I hit play and I hit host and I hit join and start game you'll notice that now the positions are synchronizing so you can see here they are now synchronizing if I go to this guy and I hit left and right you'll notice that this is not synchronizing right I can't actually move my player at all but on my host machine I can move my player just fine so what's going on well when the multiplayer synchronizer runs it sets a specific thing as the parent this thing will synchronize and everyone will follow me as the leader of this parent right as this thing so you need to tell Godot which one is the relevant one to synchronize so what does that mean for you well what that means is you need to set the multiplayer authority of your player to be the proper object right the proper client object so how do we do that well it first starts with getting our unique ID and assigning it to a player so what do I mean by that well if I head over to my player here and I open it up and I come in here and I say funk ready I can go dollar sign multiplayer synchronizer.set multiplayer Authority and I have to pass in an integer okay and that has to be my ID now if I pass in one it'll be the server if I pass in my own unique ID then it's going to be me but we want it to be a little bit more refined than that we want to actually set the multiplayer authority of each player as their own client unique ID so I probably will need to show you guys lots of paint for this tutorial but let's say we have player one and player two we need to set the unique ID of Player 1 to player one and we need to set the unique player ID of 2 to 2 but unfortunately 2 is not a thing it's technically a you know 16-bit character string right so it's a big string or integer right that we're using so what we have to do is we need to find a way to tell this player that I am X string and then we can check if uh if we are Str right if we are the actual string then do our bit of code right so that's kind of how we have to do it so how can we do it here well all we have to do is we go into our scene manager and on spawn we set our spawn name when we spawn our player we need to set our name to our unique identifier so we can do is say VAR currentplayer.name is equal to I dot gamemanager dot players I dot ID and in theory that should do what we need it to do and then here we can basically just say Str name dot to int like that and in theory that should work so that's great but how is that going to work when it comes to synchronizing our stuff well we need to tell our player our script here to say hey if you are not the multiplayer Authority right if you are not the actual authority of this character then do not do anything so how do we do that but that's actually really easy we can come in here and just say if dollar sign multi-player synchronizer dot get multiplayer Authority is equal to multiplayer dot get unique ID like that and if that's the case then all of this is good to go and that should pretty much do it so now if we hit our multiplayer scene we hit refresh we come in here we go host join start game you can see we have a crash so we invalid set index name on type int so Str because this needs to be a string it cannot be an integer so we'll just refresh that try it one more time post and join and start now you'll see if I move left and right these two guys are following so you can see these two on the left if I click on this guy you'll see that these two guys are following so awesome we have like 70 percent of our multiplayer actually completed now something that you'll notice is that when we rotate our gun you'll notice that that doesn't show up or translate so you can see if I move this guy up and down this isn't being translated well that's one of the nice things about the multiplayer synchronizers you can come in here and you can say add property to sync you could just say gun rotation hit OK and then type rotation and then when you click on your multiplayer scene you hit refresh you click host and then join and start game now it's synchronizing see and it's really that easy so it really does solve quite a few problems that some people run into with which is synchronizing data across the stream and the other nice thing is if you don't want to flood your network with packets you can actually change your replication interval to whatever the interval is going to be so if you're playing a game where you're not really worried about things being super duper immediate you can actually set it to something like you know .01 or 0.3 or 0.4 or 0.1 right and if you set it to something like 0.1 you'll notice that when I run this you'll notice that there is some stuttering on this side over here if you look at the gun you'll see how it's stuttering that's because it's actually replicating that information over but in a very lagged method right so it's taking a lot longer to synchronize that data because it's doing it every point one second but the amount of packets it's sending over the network is a lot less so that's something to keep in mind now generally speaking you could get a lot more flexibility by using something like a tween or something like that and that's totally doable um one of the things that I would definitely suggest is instead of doing player position and gun rotation is to set up two custom variables that you could use to actually synchronize that data across and the reason why is because that's going to give you a lot more flexibility with how you handle your data so you could add in things like lurping and stuff like that and not need to worry about passing as much data through them Network well if we come in here and we just type VAR sync position is equal to a vector 2 0 comma zero and then we come down here and we just set our position so let's come down into I don't know line 24 and say sync position is equal to Global position and then we need to lerp that value so if we come down here and where it says if we are multiplayer Authority since we're not we'll just say else our Global position is equal to globalposition Dot lerp and then we'll pass in our sync position and then we'll pass in a weight value now in our case I'll set 0.5 that might be a good value and instead of synchronizing these guys here I'll just come into my path and I'll synchronize sync position like this and I'll click add from path now that's something else that I probably didn't cover you can actually set custom parameters to be synced so you can see sync you can actually use this exact way to do custom stuff so if I want to do sync rotation I can say VAR sync rot is equal to zero and then I can come in here grab this paste add from path and you can see it picks it up like that and then I can come in here and say sync rotation is equal to rotation degrees and then I can come down here and say rotation degrees is equal to rotation degrees Dot lerp and then sync rout comma 0.5 and if we've done everything correctly and it looks like we'll have to change this to lerp F because it's got to be lerp float or at least I think is it lerp underscore F let's search our help lerp lerp lerp lerp f from float to float weight so it looks like we actually need to do instead of this I'm going to cut this do lerp f from float to float weight like that because it looks like vectors are done via DOT lerp but float back or float lurping is done through lerp F so it's a completely different way of doing things we're gonna hit play and then you'll see if we host join and start game you can see that people now move as if they actually should exist so you can see how he reacts and moves relatively real time this allows you to get smooth movement without losing some packet efficiency you just have to be careful because if this is a competitive game LARPing it can make things very painful for the other players so it's just something to keep in mind now once we have this and you can see it also works by the way with our actual rotation as well that lerp is actually working quite well for the amount of packets we're sending across now a common question that I get is how do I actually do a small server for land-based stuff now that's actually pretty simple what we can do is we can pull back our command line argument so we can just determine if we are a server so we can actually just come in here and say if quote dash dash server in OS dot get command line arguments colon and then we can do our code right here so anything that's special when it comes to our actual um server stuff so let's say we want to have it so it hosts our game well all we have to do is come down here to where we have our host button you can see right here on host button down I can just basically grab this bit of code control X come up here and just say Funk host game like that and I'll paste this guy in here and then I can just say post game like this and I can come up here and just say post game and then if I go to hey control s and then if I come up to project export I click on ADD I'm going to do a Windows desktop build here and then I'm just going to click export project now you'll see I already have a couple of these guys here so I'm just going to drop in multi-land tutorial.exe hit save hit okay hit OK and then I'm going to close it now if I go out to my documents folder right here like this you'll see that I have a multiplayer land tutorial console.exe so if I type CMD multiplayer land tutorial.console.exe Dash Dash server and I hit enter you'll see that it's waiting for players so you can see right here here's one of my windows if I come up here I make sure that my barn multiple instances is running too I hit play I come in here I click join and then I click join you should see inside of here that we have two players connected if I click Start game they both are in the game oh I think we actually might have a small bug let me check something real quick uh yeah because we're hosting our game here we're sending our multiplayer information we actually don't want to do that so let's come down here and say on host button then send our Player information because we don't want our server to actually house that information anymore so now let's close everything let's re-export our project that was my fault we'll kill this guy here and we'll save it yes hit close close and then we should be good to go now so we can hit up enter it's going to launch our game something to note in the Godot documentation it says that you can type dash dash no dash window and it should fire it off without a window but it doesn't so that's something that's kind of funky and I'm not sure why that is but I wonder if I can hit Dash H if I can get a help and maybe that'll give us some more information because their dash dash no window just straight up doesn't work so that means that there's some weirdness there so let's see if we can find something that works Works dash dash headless looks like dash dash headless is what we're looking for not dash dash no window it looks like the documentation is just wrong on that or maybe I'm looking at an old version of the docs that's very very likely knowing me so we'll just hit up up Dash Dash headless hit enter and you'll see it says waiting for players so our host is now running and then all we have to do is just hit play like so we will join and then join and start game so that's basically how you can create a dedicated server for your game now just keep in mind that if you want to host this out somewhere there's going to be a lot more additional information that we're gonna have to go through and I will make a dedicated tutorial specifically for that so look forward to that and we can go from there hey guys editor Mitch here so something that I forgot to take a look at was actually setting up multiplayer for shooting so to do that it's actually really simple all you have to do is just pull this guy out come down here and say funk fire like that pass this in just like that and then just put bracket bracket at our PC any peer comma call local and that should pretty much do it now you just have to come up here and say buyer.rpc and you should be good now all you got to do is just come in here hit play go over here join and join depending on where I am in the tutorial you may need to click host and join it just depends and click Start and then it should shoot just like that you can see right here when the player shoots it fires as you would expect anyway let's go ahead and get back to the video something else that we should probably look at is when a peer disconnects we want to actually delete that player out of the game so we have to do is go gamemanager dot players dot race ID and that's going to pull it out of our game manager something else that we're gonna have to do is we're gonna have to actually remove our player from the scene as well now that's going to be a little bit harder to do so what we could do is we could set our player into a group like this and just say player like that and then go into our multiplayer scene get tree VAR players is equal to get tree dot get nodes in group players and I think we use the word player not players so that's good so we'll say player for I in players colon if I dot name is equal to ID s-t-r-i-d then go ahead and I Dot Q free and that'll just kind of pull that back delete the player and take them out so in theory if we go back to our game we go ahead and hit play on that we hit play We join join start there's our two players go away and you can see that the player got disappeared easy enough and that's basically how we can approach handling that now now you might be asking how can you actually build out a dedicated server for your game now that's a question that a lot of people ask and generally speaking it is difficult to explain how it all works but what I can tell you is you need to actually have some kind of server to host it in my case I like to use digitalocean I have a link to them in the description if you want to use them of course you don't have to because they do cost money but all you have to do is create a droplet so you click create droplet and then you start building out the thing so you just kind of decide what you want it to be so like New York let's say I wanted to Ubuntu and you can come in here and select like the seven dollar a month one which is what I use and this is going to be mostly just for testing purpose not for actual production though you probably could get away with this for production for probably the first little bit of your game that being said if you're gonna be doing lots of multiplayer you'll probably want you know a matchmaking server and that whole nine yards and if you want to hear about how to build that let me know and I can help you guys out and possibly build that but you come down here you pick a root password you can come down here and you know choose how many droplets what the host name is and then finally what project you want it to be attached to now in my case I already have one built and that is my YouTube one right here now you can see here I have an ipv4 right here address and this is the address that I'm going to be sending out to connect to so that's great but how do you actually use this to do a dedicated server well all you need to do is make sure you have a console so we'll grab my console right here and you can see here's my console and first things first we're gonna need to open a port so IP tables Dash I input one dash i e t h 0 because it's going to be the Network address that we're using p for packet type TCP Dash Dash D port and then we need to pick our Port which is going to be nine eight nine ten Dash J except now in my case I already have that so it's probably not going to do anything but at least that's how it works and then we have to copy our actual code up which means we're going to need to build it out now to build out our Godot instance here we're gonna have to go to Project export and we can export this out as a Linux machine so we're going to go add Linux and then we're just going to click export project you'll see I've already done this because I had to do some testing beforehand but just before we export this out something that we're going to run into is we have an address of 127.0.0.1 and that works totally fine for local testing but for Global testing we need to set it to something that says that it's being hosted so in our case we're going to set this is zero zero zero zero so 0.0.0.0.0 and that says I'm hosting it open to everybody and then we can go to Project export export project save yes now we need to get our information up to digitaloceans droplet and I'm not going to go through that whole process if you want a more in-depth process on how that all works we can go from there in my case I already have my stuff set up right here so I have a droplet SFTP so I have it set up with SFTP and I have my IP address the reason why I don't want to go through all this is because there's a lot of private and public keys and things like that and you have to use if you've never used it puttygen which allows you to generate a key you click generate you're going to add some Randomness like so and it'll give you this key okay you can copy this and then you can go into your droplet here and actually add it in so you can just go to Nano tilde slash dot SSH slash authorized keys and you can see I already have a key here so I don't want to remove my key and don't worry it actually extends quite far beyond here so I'm not really worried about you guys stealing it but you paste that in here and then I'm gonna control X and then you save your public and private key so you want to make sure you save both of those guys so save public key you can see I have it right here and then save Private key and it's going to say hey do you want to save this without a passphrase I'm okay with that so I'm not too worried that I hit yes and then I saved it as that as well so now I have my public and private key on my machine after I've generated it and then all I did was I went into here go got into settings went to SFTP and then I navigated to my private key and I set that and then I came here to my site manager I clicked SFTP I set my host I changed my user to root and then I clicked connect and it says hey you're already establishing a connection so I'm not worried about that and then all you have to do is you just grab your guys's stuff here you drag it over it's going to copy it all up and then all you have to do is come in here and type LS you can see here's my sh file right here so we type dot slash quote multiplayer land tutorial dot sh Dash Dash headless dash dash server I believe we had it as server let me double check real quick yeah dash dash server so we'll hit enter and you'll see it says waiting for players and now all we have to do is come in here and input that IP address that we have so if we take a look it's going to be let's see come back here we'll copy our IP address so 204 48 28159 and you guys are welcome to use that by the way if you want to test your stuff go ahead and put that IP address in and you should be good to go and then if we hit project debug run multiple instances run two instances and then hit play we'll hit join and join and you can see that we are getting connected to server player connected player connected so let's see we hit start game there's our game working with everybody right next to each other awesome and that's basically how you can do dedicated hosting inside of Godot in the next GD video I am going to talk about how to do webrtc so that way you don't need to have a dedicated host running this because if you want to have more than one game going on Good Luck because it can cause a lot of issues because you're doing dedicated server hosting so kind of like Minecraft everybody needs to have their own server to play your game or at least an instance of Godot running for you to play your game so what you have to do is you either need to have an API that spins up Godot servers in the background which I can talk about and show you guys how to do that or you need to go to something like webrtc and have a signaling server that just kind of handles all of that kind of stuff and I'll discuss that in a future video but at this point I've given you guys kind of a big primer on all of the things that you need to know about how to build a multiplayer game inside of Godot so if you like this video go to hit that like button hey you know if you dislike this video go hit the dislike button because I am here to make content for you guys this video it came about because somebody went on my GitHub under fine point CGI suggestions and said hey let's talk about multiplayer LAN and dedicated server hosting so if you guys have any suggestions please jump on my GitHub leave me a suggestions my entire channel is dedicated to making sure that you guys get tutorials that you're looking for so please let me know because I'm always looking for something new to look at and hey if you guys have any questions or comments please leave them in the comments below or jump on my Discord link is in the description and anybody there will be more than happy to help you out but that is all I have for you guys today so thank you so much again for watching and I will see you all next time thanks
Info
Channel: FinePointCGI
Views: 89,997
Rating: undefined out of 5
Keywords: godot multiplayer tutorial, godot multiplayer, godot multiplayer server, godot, multiplayer, godot 4, how to make a multiplayer game, godot tutorial, godot network multiplayer, godot multiplayer syncing, godot multiplayer dedicated server, godot engine, godot dedicated server, godot 2d tutorial, godot mmo, godot 3 multiplayer, godot beginner tutorial, godot engine multiplayer, godot multiplayer network, godot multiplayer example, godot multiplayer player data
Id: e0JLO_5UgQo
Channel Id: undefined
Length: 76min 32sec (4592 seconds)
Published: Thu Aug 10 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.