Intro to 3D Multiplayer in Godot Tutorial - #1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so this is what we're making today it's a 3d multiplayer game it just runs over land right now but you can set up dedicated servers you could do port forwarding if you want to i'm not going to go over that in this tutorial but that's definitely an option and you don't really have to change much of my code if you want to do that right now we're just going over the basics of like multiplayer and applying it to 3d so we're not really going to get in depth on mechanics it's just going to be mainly just movement and spawning players in but you definitely can add extra things after if you want to so before we get into it let's hear a word from our sponsor you know multiplayer stuff's kind of hard if you don't want to deal with like paying for servers and like setting up all those random garbage that is networking maybe you should try out cory the sponsor of today's video with core you don't have to worry about the network back-end it's going to do it all for you and you don't have to worry about paying for server hosting because it does all that for you as well core is a new gaming platform where anyone can create share and play pc multiplayer games core is completely free so you can host servers for free you can play games for free you can make games for free which is you know kind of cool no coding is required so if you're new to game development this is great way to start making games thousands of free music sound and our assets are bundled in with core you can make your own scripts you can make your own 3d models and you can remix content shared by other creators if you're looking to make something more advanced core offers as well you can program game logic and lua core is powered by unreal engine so the possibilities are endless with that you're going to get high quality aaa graphics right out of the box you can make multiplayer games faster than ever with core if you're worried about making money off games core can help you there too core offers 50 revenue share with its game creators through the core perks program that's two times roblox revenue share and 10 times fortnite creatives revenue share core creators have been able to pay their bills buy their dream cars and quit their day jobs with the help of the core perks program in my experience i found core incredibly easy to use while still having all the tools that you need for complex projects if you want to start making multiplayer games core is an awesome platform to use for that use the link in the description to download core for free and to start making your own game so let's get into how we do this this character right here this model kenny's made it anime characters one you can go download it here if you want default format fbx doesn't really work well with godot so i converted it to gltf in blender you can do so if you want and then convert it to an inherited scene.tscn right here that's essentially all i have here for this project now we're going to make a network script we're going to set up a few constants we're going to set the default port you might want to make sure that port doesn't get blocked by another application i'm just using 289.60 maximum clients i'm gonna set up a server and client variable both are gonna equal null but they're gonna be set to multiplayer e-nets shortly and the ip address that we're gonna use by default we're gonna go over localhost which is one two seven zero zero one if you want to connect to another computer on your network what you do is you go to control panel you'd say ipconfig and you look for your ipv4 address and you put your ipv4 in of that computer that you're wanting to join that's hosting the game we're gonna make a few functions now we're gonna make a create server function now what this is gonna do is it's gonna print creating server we're gonna set the server equal to network multiplayer e net dot new that's gonna create a new network multiplayer e-net class that we can create the server from we're gonna do server.createserver under our default port which is this under our max clients which we defined up there and we're gonna get tree set network pure to the server so what this does right here is this grabs this remember the server's the networked multiplayer e net that we assigned right here made the new one of and assign that to the variable so what we mean when we set the scene tree to the network here is we're saying hey this entire scene tree we're going to put you under whatever id this network multiplayer ena is so then when i am checking if i'm the current player or if anything is belonging to my computer the person that's hosting i can check that by using this get treated using the network peer on the tree and this just essentially assigns it in the server if we never assign it we can never really send remote procedure calls we can never really communicate between computers which is exactly what we want in the multi-player system so we want to make sure we assign it our network multiplayer e-net now join server yeah so we're just gonna be printing joint server that's pretty good essentially we do the same thing we do up here with the network multiplayer e-net we assign that to the client and we create the client under our ip address which is assigned here which we will later allow the we will later allow the user to change if they want to and the default port and we still assign that to the network peer our client now up here we're going to assign a few signals so get tree.connect connected to server server disconnect and connection fails you want to make sure you at least name these the same as the functions that we're going to set up here that way they're actually connected all of these are for debug purposes they actually don't need to be in here but we're just going to throw them in here just in case just to make sure that your whole system is working so function underscore connected to server you can see this matches this one right here which is the connected to the server that we connected from the scene tree it just says successfully connected to server again debug purposes same with server disconnected and same with connection fail basically we print all the stuff that's basically happening with the server setup and then our final function in the script will be reset network connection now it says if get tree dot has network pure so you remember how we assigned the network peer peer if we still have one assigned to our scene tree then we'll set git tree that network pure equal to null now why do we check this before we set it to null well sometimes we might have no network peer and it's already equal to null because we already reset the connection and we don't want to set it back to know if it was already null previously i'm pretty sure that will throw a an error in godot so we just want to make sure that we have a network pure before we try to reset it now we're going to use this reset network connection we're actually going to use up here under server disconnected so reset network connection and connection failed we want to reset it because we want to redirect the player back to the server setup screen so if there's an error ever connecting to the server they could still reset up the whole server system that's our network code that's basically handles all the server and joining setup then we're going to do is we're going to go project project settings auto load and we're going to autoload our network.gd and we're just going to add it as network and what this does is now we don't need to have a direct reference to it basically everything can access it which is really nice so now we're going to go back to our 3d view we don't need our character yet so we can close out of that we're going to make a new 3d scene and this scene is just going to be our map i'm just going to call it map you can call it whatever you want and in this scene this will contain like all of our 3d assets but i also want to make the network setup screen in the same screen it just keeps everything simple for us so we're gonna add the new child node it's gonna be a control node so this is gonna be for our ui we're just gonna set the layout to full rectangle and we're gonna close control node network setup then under network setup we're gonna set up a vbox container and i'm going to set the size to 350 by 180 and then we're going to set layout center so this vbox container is going to contain a few items that will sort them correctly to how we want it the first item will be a line edit the second item will be a button and the third item will be another button in this line edit we're going to rename this to ip address i'm going to set the alignment of this ip address to center and we're going to set the placeholder text under this to ip address which essentially is just going to tell the user hey you can insert an ip address here and this placeholder checks will change once they actually start typing it now for our buttons you can see that they're really squished right now and we want more room on those buttons so what we're going to do is we're going to set the minimum size on the y-axis to be 60. we're going to repeat this for both of the buttons minimum size 60. i'm going to rename the first button to host and the second button to join now if you're going for a dedicated server approach you wouldn't want to set up a host and join button because the server is always going to be hosting so instead you'd always have the server or the network always host in that version of the game and then the players the clients will always be joining the server and you could give the clients the option to use an ip address or you can use a server that stores all the possible addresses of other servers if you're gonna do something like that in our house button i'm gonna set the text to host and then our join button we're gonna set our text to join and that's basically it very simple ui that's all we really need we're gonna make a script on our network setup so make sure you have network setup selected we're going to select the script and we're just going to call it network setup.gd hit create and after i clear all this code i'm going to press ctrl s and i'm going to save my entire scene tree as map.tsen i'll just save that there going back to our 2d scene we actually want to connect our ip address text changed back to our network setup script right here just press connect there and we're going to go to our host button and we're going to connect the pressed signal back to network setup same with join pressed network setup so that's all of our signals for all of our buttons when the host button is pressed we're going to call network.createserver now remember how we autoloaded network that means anything can access it so this is why we're able to say network.createserver right here then we're going to hide because remember we're in the network setup so when we toggle hide right here what this is going to do is this entire visibility is going to go off and what that's going to do is that's going to take us back to the 3d scene so then we can uh play the game same with join we're going to say network dot join server we're gonna say hide then on text change what we wanna do is we're gonna say network dot ip address equals new text so essentially whenever we update this ip address text it's gonna be updated here i'm just gonna press run and you can see i can't really make multiple instances of this window to test you can see it's just going to refresh it there is an add-on that will run multiple game windows when you're trying to do multiplayer i don't have that because i'm not very fancy right now but i'm just going to run it the old school way and essentially you just want to run a new instance ago and then you could just press run on your project that you have selected that is your project i don't need to put an ip address because i already assigned it as one two seven zero zero one which is essentially localhost so it will just loop back through on this computer i can press host and i can press join and you can see that it says creating servers so we did make the server but nothing happened it never said anyone joined and that's because we never actually set that up so i'm just going to close these two and we're going to connect one more just for debug purposes and this is going to be network pure connected we're going to connect that to self and i'm just going to call it player connected and now all the way down here i could just say function player connected we have to pass in an id an id is essentially when a player connects they're always going to return their id and so we want to make sure there's an id in this function and i can essentially just print that the player is connected with their id we should probably string that and there you go so we can test that now host and join and it says player connected in their id right here so that means it is working and we can close and we can close so sweet we have our multiplayer system basically working now that we have the multiplayer system in we actually have to get the gameplay into the game because we can send data right now but we want to have a game to show off so what we're going to do here in our map scene i'm going to add a new static body and i'm just gonna rename the static body to floor in this static body we're gonna set up a new csg mesh which will be the floor so for our mesh i'm just gonna make a new plane mesh and then i'll crank up the size to like 50 50. now we got our floor in which is pretty good but we need a collision shape on this because it's a static mesh and it's going to be colliding with our player so we're going to add a new collision shape this collision shape is just going to be a box shape and we're going to set the extends to 25 on the x 25 on the z and then i'm just going to move it down because it's kind of hovering above our plane so i'm just going to move it down a bit and you can just eyeball it it doesn't matter if it's perfect and that looks good so we got our collision shape and our floor in and this isn't needed but i like things to look nice so i'm going to add a directional light usually i want light in my scene i'm just going to move it up the position doesn't matter it's just the rotation of another shear for the rotation degrees on this directional light i'm just going to set the rotation to negative 60 on the y that's really what i found looks good and i'm going to save that so that's our map you know we still need a player so let's start working on the player we're going to add a new scene and this is going to be a kinematic body we're going to rename this kinematic body to player now we've already made our character if you haven't if you don't have a character you could just make a csg mesh and just use a capsule we're actually going to instance our character.tscn under our player i'm going to add a collision shape because this is a kinematic body needs a collision shape so it can collide with the ground and the shape is going to be a capsule shape and we're going to rotate this capsule shape 90 degrees on the x i'm going to move it into the center of the player and then i'm gonna set the height of this capsule to two and then you can see it fits around the player pretty well and now i'm gonna make a spatial note essentially just contains vector three coordinates and i'm gonna move it all the way up to the head on the player i'm just using ctrl to snap i'm just going to snap it all the way to the head and now it's in the general location of the head we're going to rename this to head and we're going to add a child node to this it's going to be a camera and you can see our player is not facing our camera so what we're going to do is we're going to go in our player we're going to set the transform and i'm going to set the rotation on the y-axis to 180 degrees now you can see the camera is actually going out of their face which is what we want now we can save this and we just save as player that's fine and now we have a player in our scene now we're going to add a script to our player and essentially we're going to remake a fps player controller if you've done fps games before you're going to notice a lot of this code is going to be the same but before we get to the code we actually messed up the input so go to project settings go to input map and we're going to set move forward action move backward move left and move right and we also want jump because that's fun okay so move forward i'm gonna set that as d wait no what am i thinking uh move forward is w not d uh move backward is s move left a move right as d and jump gonna be spacebar okay now we have all of our inputs set up we can close that let's set up a few variables let's set gravity to negative 40 and we'll set speed to 16. we'll set jump speed to 15. we're going to set our mouse sensitivity to 0.08 velocity is just going to equal vector 3. and we're going to get the path to our head so we're going to export node path on ready var head equals get node head as spatial now essentially if we are exporting a node path and essentially in the same line of code we're able to sign since it's a node path it's a string we're able to use get node of the string of this node path since it's on ready back to itself so essentially it's just going to return the node of what we assign as spatial essentially tells it hey this node needs to be a spatial type node it won't work with any other node so we can go back to our player it gets our head and it's going to say assign nodes so i can click assign node and i can assign it our head node 3d i can press ok and now we're getting a reference to our head under the ready function we're gonna set the mouse mode to input mouse mode captured it'll just make it so the mouse is disappeared on the screen and i'll just center it to the middle of the window and make sure that it doesn't go and go outside the window that way you can keep turning your head we're gonna use a get input event we're gonna set input direction to a vector3 value essentially resetting it every time we get input okay so right here we're just saying all we're essentially doing is these little handles right here move the player back and forth these are the transform.basis and you can move the node like this which is way nice when you have it rotated and i tried to move him you could see that he doesn't move in his rotated direction so essentially what basis does is it rotates the things with him and then he can actually move in those directions without rotations kind of screwing it up we're going to normalize it so if we're holding down two inputs it won't be bigger than one and we're going to return input direction now this is just a function this doesn't actually get input go. does have a built-in function for that and so right here we're going to use it function underscore input events if event is input event mouse motion essentially event basically is any type of input you can put in it'll be anything i mean anything mouse movement keyboard uh controller any type of input touch input will go through but we want to make sure that it's a certain type before we start messing with the event parameters because it might not have those parameters if it returns a different type if it's a mouse motion we're going to rotate the wire for character essentially just like if you go 3d scene this is the y you're basically making them face direction of negative event.relative.x multiplied by mouse sensitivity and we're converting from degrees to radians which is what you put in rotation y we're going to rotate the head on the x-axis to the negative event relative dot y to multiply by the amount of sensitivity and we're going to convert that to radians essentially what we're doing here is with our head we're moving along the x-axis moving it up and down our camera motion based on our mouse movement and then we will move our character left and right based on the x movement that's basically what those two do then we have to set our rotation.x and we have to clamp it this is for her head and we want to make sure that it doesn't go past negative 90 or 90. now this is because if we start rotating our camera and we move our mouse on the y-axis it'll just keep rotating around and around and around and this will lock it or 90 negative 90 and it can't go past those two positions so this just handles our mouse movements and rotating our head towards that in our physics process we're going to add gravity to our velocity dot y we're going to multiply that by delta then we're going to set a variable desired velocity this is going to equal get input which is this function up here which essentially you know does what it says returns our input and we're going to multiply that by speed because input is going to equal vector 2 and we're going to multiply that by speed and then we'll set our velocity.x equal to desired velocity which is right here x velocity.z desired that's z so this will basically handle our velocity how we want it then for jumping we want to say if we press the jump button and we are on the floor then set velocity.y plus equals jump speed sounds good and then at the very bottom we actually want to execute this velocity and move our player in that direction in this function we'll just move our player in the direction so that we move him in and he'll handle collisions automatically which is way nice we didn't put any networking code in it yet we're gonna get to that later once we get players instancing into the map but right now we just need to test to make sure our player works so we're going to instance our player under our map scene so you could see him and this ground is really blinding so what we're going to do is we're just going to make a material and i'm just going to set the albedo down it's like a gray there we go that's there and also if you want to you can go to your directional light you can go shadow you enable shadow you know make things look good and we'll play our game so we'll see if this works you can see i'm like inside my player's head and you can't really do anything especially this ui menu is kind of screwed up because i can't select any of the ui so i'm going to close this i'm just going to hide my network setup at the start just so i can test this but you can still see we're inside our player's head so how do we fix this well we just don't render our character when we are playing but this is going to change when we are actually having multiple players in because we want to render their characters but we don't want to render our character we still need to get a reference to our player's mesh so we can actually hide it i mean you could just hide the entire kinematic body but i just like to hide the mesh so what i'll do here is i'll just export another node path already var model equals get node model as spatial now this is really important right here if your model is not a spatial type a node right here and you're using a csg mesh make sure you have this as csg mesh or else it won't work so then we can go back in our player set model back to our character model press ok and there we go and now under our ready statement i could just say model dot visible equals false but you can see i can look around i can move around i can jump and that's basically our fps character so that's everything we need for him looks like he's working just fine so we can close the game and that's everything there we're gonna go back to our map we're gonna toggle network setup back on so we can actually use that later and we can delete our character because we know he works and because and because when we set up the multiplayer game we're actually going to instance our players dynamically based on players connecting we don't want to have a character just sitting there already because that's going to screw up with our view stuff so the next thing on our list is actually to set up a new singleton so what we're going to do is we're going to make a new script i'm just going to call the script global i'm going to press create and then global what is this going to do first thing that we're going to do we're going to set up two signals instance player and an id that you have to put in for that signal and toggle network setup with the toggle which is going to be true or false where are we going to use these signals well total network setup essentially if we send a signal and it's true then basically we'll set the visibility true if it's false we'll set the visibility defaults for our network setup this will let us change the network set remotely we don't have to be in the network setup node and we don't have to have a reference to it there's one more thing it's entirely optional function underscore input event if event is event key and scan code is key escape quit the scene tree so essentially just kill the game if we press escape and then what we're going to do here project settings auto load auto load uh global and you can add that essentially so everything can access global and essentially it will be loaded in the scene tree before everything else which is way nice which means that we can always check this scan code and always quit the game if we need to so that's pretty cool but we want to create players we want to do some cool stuff so let's go to our map we're gonna add a new script we're gonna create a variable for player we're just gonna preload under our player scene so make sure that this uh scene is valid and as you can see it's not valid on my end so i'm gonna re-update that to player.tsen make sure it matches the actual file and you should be good under the ready function we are actually gonna have to need these two uh signals these are not for debug purposes they are they are very needed player connected and player disconnected which will be connected from the scene tree remember the scene tree was assigned a network pier so that's why we're able to get these network pure connected and disconnected signals from it now we're gonna say global.connect instance player to ourself underscore instance player so essentially we grab this signal from global which is our instance player and we're able to connect it to ourselves without essentially having to know where the node is in the century because global is already pre-loaded and that means if we call instant player here or anywhere else we can receive it in this same place on the map which is way nice for instancing players outside of the script we're at check get tree.network peers not equal no null then we're gonna emit signal toggle network setup and we're gonna set that to false now remember we set up network setup here we have it set up in the actual network setup which we are going to later that will essentially say hey network setup we want you to basically turn yourself off we don't want to see you anymore so we're going to toggle it off using this uh signal and our map so when the player connects we're going to do our same debug stuff layer as connected and we're going to instance a player under this id now we don't have this instance function set up yet so let's actually set up this function let's set it up right here underscore instance player it's going to take in an id and it's going to say player instance equals player.instance we got a reference to that we're gonna set the network master of player instance to this id so what does this say well this says that this player belongs to this computer id if i'm playing on my computer my computer's id is one well if my player's id is one i know that player belongs to this computer so if the player cannot belongs to this computer then i can handle input events and i can move my player because i don't want to move other people's players because let's say my friend is player 2 right player id 2 and i'm id 1. id2 does not match my computer's id1 so that means that i can't move that player now if you were able to move all the players that's not really what you want so this is why we have this id system set up is so we can actually handle inputs between players and we can do other things using the whole network master system which is way nice we're going to set the name of our player to the id the string of the id this is also very important because when we're instancing nodes in our scene tree on the network's multiplayer game all of the nodes that are networked need to have the exact same names and need to be under the exact same parents all of the machines if they aren't go dot's network multiplayer system crumbles and it doesn't work and you get tons of weird errors in here like i have no idea what's going on well just make sure all your nodes are synced across all the clients and that's why we set our name to the string id well why does that matter because my player name is going to be the same across all clients right if i instance a player it's going to be player and that's the name of the player sure yeah that works for the first player but let's say i instance a new player well god has to fall back on its system for naming duplicates of nodes we'll just say player at one so all the clients has duplicated that player but let's say one client gets behind well it's at all the other clients are a player at two and this one client is that player at one for that one player well that screws things up and that will toss tons of errors everywhere for them and they're out of sync so essentially to mitigate that problem we set the name to the id and all the ids are unique from each other and we won't run into that issue reset player instance our transform.org which is location in 3d space to a vector 3 0 15 0. so why they choose this value this is a really generic value but let's show you this right here this where this is at this is zero zero we want instance our players about up here with the directional lights we want them to fall onto the map we don't want them to get stuck on each other so i just quickly set up a stupid system that instances them in the air they fall down and they can move around and then we can add the child player instance this is something else that's interesting that you might want to include in your other projects if you are working on uh multiplayer project i set the player's master before instancing as a child if you don't do this and you try to check in the ready event if you're the network master or not that won't work because you never set it up before you instances the child because as soon as you add the child the ready function gets declared and so this ensures that we initialize the whole networking system for the player that's why you just set that up up there before that all right so that's great we have players instancing when they connect but what about when the player disconnects well yeah we want to destroy that player right function underscore player disconnected if we have the node that is our player we string the id which is the name of our player right we have to find that node then we say git node the string of our id dot q free that essentially kills the player that has disconnected and instances the player that has connected we are not done yet because we still need to set up our network setup script so let's go here if you remember we actually set up in our map script right here we emitted a signal somewhere here yeah emit signal toggle network setup so in our network setup we actually need to receive that signal and so to do that we actually need to connect it to our shelf under the ready event global.connect hollow networks out to ourselves which essentially allows us to listen in to that signal and then we'll make that function below toggle network setup with the argument visible toggle visible equals visible toggle this doesn't really matter name could be anything it's just what we essentially sent when we called the signal which is the boolean true or false this should work we should instance players they should get instanced in as players join so let's try this you can see my mouse isn't locked yet because there is no player in the game which is nice we're going to run it twice now so i'm going to host i'm going to join you can see it only created the player after i joined which is interesting let's look at our error right here all right so i made a mistake right here we actually can't set our position before it's not in the scene tree so just cut this line and just move it after we add the child now it still wouldn't work because we have forgotten something in our network setup we are only instancing a player when a player connects right that signal is only called once well if i host my game this signal still won't go off until someone joins my game right and when they join my game it'll instance a player for them that's why you didn't see me fall until a new player is created well why they see their view they're the only camera in the scene tree so it looks at their camera through their player and there is no player for me so we still need to make a player for yourself because right now we're only making players for everyone else well that's simple enough we just go in our network setup and when the host button is pressed we will say global.emit signal instance player get tree.get network unique id don't do this if you're doing a dedicated server because obviously you don't want a player for the server because this is what happens when i press the host button i want to create a player for myself i am making a game that i want to host and play with my friends right instead of the whole dedicated server approach get tree dot get network unique id essentially it's just like the whole is network master it just returns the id of my entire scene tree of my id essentially who is me the unique id of myself and that will make it so they can actually assign their network peer to the id of the scene tree which is what they want now when you join the server you still need a character for yourself so what you want to do global.miss signal same thing instance player unique id right we want to instance a player for ourself when we join and host otherwise we're only going to be instancing players for everyone else which is what we don't want so we can save that and we can run our game i'm going to host and i'm in you can see i immediately fell into the game and i'm gonna press join and i fell into the game on the other side hey don't forget use the link in the description to download the core for free and start making your own game so that's the end of this tutorial in the next tutorial we're actually gonna be finishing all the networking and all the other the other the stuff and and it's going to be finished so that's going to be cool so thanks for watching you guys are awesome [Music] you
Info
Channel: PlugWorld
Views: 18,318
Rating: undefined out of 5
Keywords: gamedev, godot, game, development, design, multiplayer, networking, 3D, fps, first person shooter
Id: CT7FmCmfxrw
Channel Id: undefined
Length: 28min 4sec (1684 seconds)
Published: Thu Oct 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.