Learn Unity Multiplayer (FREE Complete Course, Netcode for Game Objects Unity Tutorial 2023)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome I'm your code monkey and here is a free complete course on making a really nice multiplayer game if you have lots of multiplayer game ideas but don't know where to start then this course is for you here we are going to build a simple game but also one that involves using lots of multiplayer tools so while learning how to build this game you won't by the end have the knowledge required to be able to build just about any multiplayer game in any genre you can think of we're going to use unity's official multiplayer solution called netcode for game objects this is a very robust tool set and once you understand how it works it's actually surprisingly easy this is a complete free course video but it has the same level of quality as my paid courses or my Steam games you can download the project file so far along or inspect the final game you can even play the final game right now directly from scene this course is a follow-up to my free ceiling player course in that one we built this project completely from scratch every line of code was written on screen during that course and now we're going to pick up from where we left off and Implement multiplayer also just like the cylinder course one very important thing is how everything we're going to do here it's all going to be focused on writing good easy to understand clean code the code that we're going to write here is production quality code this is not a throwaway demo the quality of the code and structure of the game that we're going to build is on the same level of quality as my own Steam games as you can see from the video link this is indeed one complete very thorough course so don't try and watch this whole thing in one setting take your time and take it slow and just focus on learning there are chapters for every lecture in the video here's a quick overview of the entire course all the steps that we're going to take to reach the final polish game so first we will Begin by taking a brief look at the starting game this is what was made currently from scratch in the ceiling Point course so here we're just going to do a quick overview as a refresher to see how all the code is set up then we're going to begin by installing netcode for game objects this is unity's official multiplayer solution we're going to install the package and do the basic setup with all of these settings and spawn a player object after that we're going to begin by synchronizing the player movement and also at this point we're going to talk about one extremely important thing in multiplayer games which is server authoritative versus client authoritative with the movement synced we are then going to synchronize the animations this one is pretty simple to do thanks to the built-in components next we're going to synchronize our first proper gameplay logic we're going to begin with the delivery manager so we're going to synchronize how the recipes are spawned make sure only the server spawns them and all the clients see the same list and also synchronize delivering the recipes either correctly or incorrect one after that is just a quick lecture to fix the selected counter visual this is something that is one of the many differences between making single player games and multiplayer games we need to think in different ways especially because in multiplayer we no longer have just a single player object then we're going to synchronize picking up objects this involves learning how to spawn objects on the network so that all of the players can see it after unlearning how to spawn them we're going to synchronize the kitchen object parent so that multiple players can hold objects and everything is correctly synchronized across the network then we're going to synchronize the plates counter make it so that only the server responds points then for the trash counter this one involves learning how to destroy Network objects after that is synchronizing the cutting counter so this one will involve thinking about what parts we need to synchronize and what logic can be just local then for the stove counter for this one instead of using rpcs we're actually going to use a network variable the server won't keep track of the stove State and sync it to the clients next is synchronizing the logic for adding ingredients onto the plates after that for an optional design question we're going to implement some player collisions then then we're going to synchronize the complete Game State SO waiting for all of the players to be ready before starting the game and also synchronize the game timer and game over next we're going to learn how to deal with pausing so do we unlock it or not in this case we are going to allow it and all of the other players must wait until everyone is unpaused then for something very important which is how do we handle disconnects how do we clean up all the objects so the game doesn't crash when a player leaves in the middle related to that are only joins so how do we handle a player that joined after the game has already started or should we even allow that then comes a really important and relatively complex lecture in this one we're going to handle the complete connection scene flow how we begin in the main menu in single player then we have an online lobby after that we create a netcode connection and go into the character select scene then when all the players are ready we then go into the main game scene and after that just play the game as normal this is one of the most important lectures in this entire course after that with the connection firmware working we're going to build out a nice character select scene this one is of the main things that I saw people ask about in my netcode video so we're going to make a nice scene where the players can join and customize their character next we're going to build the game lobbying so the player can create a Lobby or Join one then we're going to implement relay in order to allow our players to connect to one another easily without having to open ports next we're going to talk about some more Unity multiplayer Tunes dedicated servers with game server hosting Matchmaker and vvox after that we're going to talk a bit about all the tools at your disposal to test your multiplayer games then just before the end we're also going to add a really important option we want the game to work in both multiplayer and single player so we're going to make it so you can basically bypass all the multiplayer connections and play in an offline single player mode and with that everything is done so we're going to inspect the funnel game and have some fun so as you can see you will learn about a ton of Topics by following this course by the end you will have the knowledge required to build just about any multiplayer game now if you're new to the channel then welcome and here's a bit about me and my credentials or why you shouldn't listen to what I have to teach my name is Hugo and I've been running this Code Monkey YouTube channel for five years now in total almost 700 videos on all kinds of topics including tons of tutorials sharing my knowledge to help you on your own Game Dev Journey I'm also a professional indie game developer making games for over 10 years with 8 successful Games published on Steam so what I'm teaching here is based on a lot of years of experience making a lot of games just like with my paid courses I'm always in the comments answering your questions every single day so if you get stuck on a particular point or need extra clarification on something go ahead post a comment and I'll do my best to help do make sure to include a timestamp of what you're referring to I will also be updating the pin comment with any frequently asked questions that I see especially right now pause the video and scroll down a bit and look at that comment since on YouTube I cannot update a video after it's published I will be updating that comment over the next months and years and I also made a dedicated course on my website in there you can download the complete project files for every single lecture so if you get stuck at any point you can download the code for the deck Ledger and compare with your own there's also links to all of the reference videos for each lecture and I won't be including the frequently asked questions if you have a common question then chances are I've already answered it in that page so it's faster to just check that page where then wait for me to reply to your comment so definitely do keep that page open in a second tab as you follow along each lecture now both this free course and the single player one took a ton of work to make so I really hope you find both these courses home phone go ahead and hit the like button if it helps you it's a small thing but it generally does help this video on the YouTube algorithm making this course was a ton of work and by making it completely free means that it won't obviously never make as much money as if I just made this a paid course I'm perfectly okay with that decision with the Hope set by making it free it won't reach and help many more people I'm also a big believer that education should be free so if you can't afford one of my big courses like if you're just a kid or if you're going through a rough time I still want you to have access to high quality education so you can achieve your Game Dev dreams one easy way it can help me for free is similar on liking this video subscribing to the channel and just watching this video that will hopefully help push the video on the YouTube algorithm and help it reach many more people another free way to support what I do is so I'm currently working on my next steam game called term 1 Liberation you can wishlist the game on Steam wishlist met a lot for scene visibility so just by doing that he'll be helping me and just in case you can't afford it and you find both these three courses useful you can also support what I do in a few other ways I added this exact same course on my website as a regular paid course although I want to be very very clear there's absolutely no difference between this free video and the paid course there's absolutely nothing behind any kind of payroll all the lectures are free only purchase files are free everything is free you don't have to pay anything if you can't afford it or you just don't want to the paid version is essentially a donation the only difference is this free YouTube video has regular YouTube ads whereas the paid version on the website doesn't have any ads that's it so the only reason why I made that paid version is just in case some of you can afford it and you want to support what I do but again only do that if you can afford it if you can't then that's perfectly fine I hope you'll learn a ton from watching and following this free course beyond that if you follow this course and you enjoy my teaching sound perhaps log into my other one if you like this video then I think you will really like my turn-based strategy course that is the perfect course to follow up on this one it Dives even deeper into some of the concepts used here and it will help you make the jump from beginner to Advanced and since you're interested in unity then I think my ultimate unity over your course would also be very useful to you each lecture in that course is focused on teaching one entity two more feature there's already over 15 lectures including plenty of small but very important things that just wouldn't work as a regular YouTube video if you're interested in visual scripting I have a course on making three unique games internally with visual scripting and no code at all or if you prefer you can learn how to make a nice Builder Defender game so if you enjoy my teaching style in these three courses then check out my paid ones but of course YouTube has Channel memberships and super thanks so you can use those if you want I also have my patreon if you prefer that and a lot of my videos I have film links for the NTS store or Humble Bundle if you ever pick up anything from those I get a nice commission and I also have some of my own assets on the unity store so if you enjoy these three courses and you want to support what I do there's plenty of ways but again don't feel obligated if you can't afford it or you just don't want to then that's perfectly fine I hope you learned a ton from watching and following this free course alright so that's enough time for that for now before we begin building the game Let's inspect the final game that we're going to build so let's see that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to take a look at the final game that we're going to build in this multiplayer course okay so here's the final game that we're going to build in this course and right away on the main menu you see a very important feature the goal is indeed to make a multiplayer game but thanks to how netcode works it actually makes it really easy to support both multiplayer and single player so here we have buttons for both we can go into single player and if there go the game starts playing so exactly the same as we made in the Singapore course so everything works perfectly offline everything works great so we can move act and everything works great so it works in single player or of course we can go into multiplayer and as soon as we do we go over here into a Lobby scene this is where we can view all the lobbies that other players have created right now the game is sent out so there are no lobbies here but if there were they would appear on this list since I'm the first player I can go ahead and create a Lobby I can give it a name so my awesome game Lobby I can make it either private or public so if I make it public as soon as I click if there go it creates a Lobby and this one goes into the character select scene and over here I have a bunch more clients so on these let's go ahead into multiplayer then load up the lobby scene and you all of them can see the same Lobby so I can join Lobby either by clicking on the lobby name directly there you go joining Lobby connecting any of this client is now joined Lobby alternatively I can press quick join and unity won't automatically try to find a found Lobby to join and also as we saw the lobby can either be public or private if we had made it private then the lobby would generate this kind of code so you could take this code give this code to a friend they would put that code over here on these input box they would join by code and they would end up joining the same Lobby also one very very important thing actually happened in the background without the player even knowing that is the entire relay as a host I did not have to handle any port forwarding or dealing with any firewall when I created the lobby in the background the game actually created a relay allocation and connected through there same thing for all of the other clients they all automatically handled getting the relay code from the lobby host and connected perfectly so like this the game supports connecting any two players anywhere in the world without any issues with ports or firewalls okay so then here we are all on the nice character select scene we can look at the players and choose a color also over here on the host the host has extra buttons on top of each player in order to kick that player then for each we can select any kind of color we want for our character so I'd say instead of yellow I want to be purple and there you go I change the color and yep look at all of those synchronized correctly then the server also does some Foundation to ensure two players don't end up with the same color so if I try to select purple nope does not work so each player can really select their color and once they're all happy with their colors there's a ready button so each player can Mark themselves as ready and ready synchronized but the game is not starting just yet instead it must have all of the players great in order for the game to start so let's set ready on this one on this one and finally on this one and once they're all ready yep the server automatically unloads the game scene and all the other clients load the same scene and now here just like in the single player game we have our controls so each player can take their time to read the rules before moving on then when they do and let's interact any of the server is currently waiting for the players so all the players must go through the controls before the game actually begins so let's go ahead interact on all of them and when I do on the last one if there you go it goes into the countdown it counts on the timer and after you go the game is now playing alright great and as you notice the countdown all of that was perfectly synchronized and now here everything else is exactly like we built in the single player course except obviously the big difference is everything is synchronized so on the recipes over here on the side all the players are receiving the same recipes I can move around on either player and yep all of them are perfectly synchronized then I can go ahead pick up objects and yep all of them they get the objects funding all of them get the object parent changing all of that works perfectly then I can place the objects anywhere and yep it works so I can place it on the cutting counter I can do the ont interact action and yep all of them see the object is being cut and you all of them see the cheese slices then I can also go into the stove pick it up drop it and yep the timer for the serve that one is actually being synchronized by the server so there it is and if I leave it to burn yep all of them are giving the warning and if I leave yep there go that one is charred and it's charred on every single client so now I can trash it so this involves destroying a network object now let's do a proper one so let's go ahead that one sets it on coke then this one let's say this one picks a plate tries to pick up that one and goes and grabs that one then this client down here go ahead pick up a brand drop it and now we can go ahead and deliver any of their delivery success synced on all of the other ones and of course the game timer itself is also being synchronized and as soon as that timer ends up if they go they all get a nice game over scene alright awesome so this is the complete multiplier game we're going to take our single player game and synchronize all of this game logic to make it all multiplayer and we're also going to implement the two homes for Lobby and relay to make our game easy to play for any player anywhere okay so now that we've seen the final goal let's go to the next lecture and see what you should know hello and welcome I'm your code monkey in this lecture we're going to see what you need to know in order to be able to follow everything in this multiplier course okay so for this course like I mentioned it's a follow-up to my film player course the starting project files here are exactly the project files from the last lecture on that course so I will assume you've watched that and you are familiar with that code base and how the project is structured in the next lecture I will do a brief overview of the code base so if you've seen the course a few weeks ago then just watching that lecture should be enough to quickly remember how everything works in this specific multiplayer course we are going to be using unity's net code for game objects this is their official multiplayer tool set I've covered it in a general video previously and like I said in the single player course here I will mostly be using it to achieve our goal with this game rather than covering every part of the tool set itself so first go watch that video to learn about the tool set in general here I will assume you know the general idea for how it works meaning what is a network manager what is a host and a client what are rpcs and network variables you don't need to memorize that video just watch it once just to get an idea for how it works in general then here as we use each part of the tool set I will explain what it does also I would highly highly encourage you to follow the course website as you're following along with these lectures I saw a bunch of comments on the cylinder course asking the same questions over and over again those people could have gotten those answers much faster if they had just read the website FAQs rather than waiting for me to reply so definitely keep that tab open and read through it as you go through each lecture but at the same time I answer comments every single day so any questions you have post them here and I'll do my best to help just like the Salem player course this one is pointed to lectures they are all as chapters in the video so you can navigate around and once again let me remind you that you are not expected to follow this course in one sitting take your time focus on actually learning remember that's the only goal you're not competing with anyone you're just gaining knowledge for yourself so take as much time as you need re-watch some lectures if you feel you didn't fully Get It Go watch your related videos read the frequently asked questions or just ask a comment mainly take your time and just focus on learning okay so all of that to say that you should know the contents of the cylinder course and the netcode for game objects video as long as you've seen those two you should be able to follow everything here and now before we begin let's take a quick look at the starting ceiling Point project and how it's set up so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to take a look at a quick overview of the code and the game that we made in the single player course okay so here we are in the game built from scratch on that single point of course we start off in a super simple main menu with a bunch of buttons then we can go into play and right away it loves the game scene and here we can see a bunch of basic controls it's selling as the base game rules the controls and asking for interact to continue so now as I press interact button yep the game starts a countdown and with that I can now move around then on the left side I can see a bunch of recipes being generated so I can approach any counter and interact with it for example there's a container counter from where I can pick up some objects when I pick up the object hovers in front of the player then over here is a clear counter so I can place and drop some objects now over here is a cutting counter so I can place on some objects and with the alternate interaction I can start to cut them after cutting a bunch of slices I can cut the entire object when that happens is cheese Moab became cheese slices then for the other one is over here the stove if I place some uncooked meat on the stove a timer starts counting up that timer is the meat cooking so as it goes yep there you go the meat is cooked but the timer keeps going so if I don't take it out then it suddenly becomes burn so yeah there you go the meat is Charn so down here there's a counter to destroy it so let's destroy it and let's cook some more meat and now let's pick it up correctly so for picking up there's also a plate and when carrying a plate we can pick up ingredients of the plates so there you go pick up meat pick up some cheese and let's also drop some bread on there so we have a complete recipe so this is the cheeseburger that the clients are requesting so let's go ahead drop it and if there you go we have a successful delivery now finally the game itself has a game timer and when the game timer elapses yep here we have a nice game over screen alright awesome so this is the game that we built in the single player course now let's see the main Concepts and how the code works the core of it is the kitchen object class this is the class that represents a kitchen object like for example some cheese or tomato then for the type itself we have defined a kitchen object so a script on object which holds the prefab reference and a bunch more data for the counters they all extend this base counter class this class has a bunch of logic and importantly it over here has an interact function this one is marked as virtual some of the other different counters all of them extend this base less and they override this function for example here on the container counter on the interact it checks if the player is carrying anything if not if the player isn't carrying anything then just spawns the object we also wrote some clean code so we used events all over the place in order to separate the logic from the visuals so in this case this event is what triggers the animation on the container counter now over here this one spawns a kitchen object and gives it to the player so the player in here is a kitchen object parent importantly each kitchen object can only have one parent and then each kitchen object parent which is the finest interface each of these can only have one kitchen object basically the interaction between kitchen objects parents counters and players all of that is really most of how the game works beyond that here we have the delivery manager this is a script that handles generating recipes and keeping a list of all of the wedding recipes for the recipes themselves they are also defined in a recipe so this is a scriptable object just only a list of kitchen objects so for all the ingredients there's only three counter simply calls they deliver recipe function passes in the plate and then over here we do some validation to check if it is the correct recipe and if so then once again we have some nice events which then have the visuals hooked onto it another important script is the kitchen game manager this is the general script that handles most of the Lobo game logic importantly it handles the state of the game SO waiting to start doing the countdown playing the game or game over and that's really it for how the project and the code base set up it's a relatively simple game so hopefully this quick refresher him to you remember how all of it works finally before we begin let me just quickly talk about the two main options you have with regards to making a multiplayer game one option is to do just like I ended up doing with these two free courses first make your game in single player and then convert it to multiplayer that's one option and the other option is to get the multiplayer working right from the start both are perfectly found options which one you go with really depends on the game you're making specifically with how complex it is for very simple games this approach works great first make it internally in single player and then convert it to multiplayer but if multiplayer is a very core part of your game then implementing it from the very start is likely the best and of course there is a third option where it's really a mix for example if I were making this game all by myself instead of making these two courses if it was just me making this game in multiplayer I would end up with a mix of both approaches I would first get the basics working in somewhere like just the character moving interacting with the counter and pick up something then before I went further I would synchronize just that part in multiplayer after that I would build one mechanic in Sound Player then synchronize it and so on so you have lots of options for how you can build your multiplayer games okay so hopefully by now you have a good knowledge of the starting code base and how all the elements and systems are connected with that knowledge now let's begin building our multiplayer game we're going to start off by installing the netcode for game R6 package so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to begin making our game we're going to install net code for game objects which is unity's official multiplayer solution and we're going to set up a basic scene with a spawn player for a host and client all right so here I have the project this is where we left off on the single player free course so everything here in this project was built during that course from scratch again definitely go watch that if you haven't seen it it won't be quite tricky to follow this multiplayer course if you're not familiar with the code base you can download the starting project files from the course website if you follow the course yourself and you built your own project then perhaps you can start from there although depending on how much you went off script from the course code perhaps it might be best to start from the exact same project files that I have here just to avoid any confusion the only difference is I updated my Unity version to the latest version as the time of this recording which is 22.2.7 like I said in the single player portion make sure you're using the same version as me the last number the 0.7 over here doesn't matter but make sure you're using 22.2 or if you're watching a few months in the future then you can use the 22 LTS but if you're watching this many years in the future and there's version 23 or later then still stick with the 22 LTS okay so let's begin making our multiplayer game now for making this multiplayer course I won't be using unity's official multiplier solution called netcode for game objects here I'm going to assume that you've watched my dedicated netcode for game objects video so I will assume that you know what is a network manager what is Unity transport what is a network object and so on you don't need to memorize that video I will still do a brief description introduction of the components as we use them but I will assume that you've seen that video and have a general understanding for how the tool stack works so let's begin by installing the package let's go into window the package manager then up here let's go into the NT registry and let's make sure we are on all then just scroll down and down here we can find the netcode for game objects and as the time of this recording the latest version is 1.2.0 so we want to install this but again like I mentioned with the NT version here let me say the same thing if you're watching this a long time in the future I would still highly highly recommend you use this version 1.2.0 and not whatever is the latest version the reason for that is because I cannot see the future so I don't know what changes feature versions will bring for the most part they won't probably be very minor but even so if just a function changes name that could be a breaking change so I would highly highly encourage you to follow this course using this exact same version just to avoid any confusion then afterwards after following this entire course you can go and look in the netcode package and read the change along to see what changes I've had it since like I mentioned in the single player course don't worry about using a quote-unquote older version of the knowledge you will gain from this course will still help you many years in the future even when netcode for game objects is on a different version for example right now we can see the change log for the developed branch which is what they're currently working on and over here we can read that change log and we can see for example the only significant difference that I can see is really over here the network prefabs apparently in this feature version instead of being on the network manager it won't be on a separate certain wrong object so that's the kind of very minor thing that changes in the versions but despite being very minor if you're trying to follow this course with a different version it can still be quite confusing and as usual I will be updating the pin comment and the course page to reflect any important updates so if you're watching this in the future and there's a different version still make sure to install this one and the way you do it is instead of using this and sound button here let's click on the plus icon on the package manager and let's add a package by name then let's type the exact name that we see there so com.unity.netcode.game objects and let's make sure we don't have any typos so that's the exact same name and then over here for the version let's go 1.2.0 okay so let's go ahead click on ADD there you go it's installing the correct version and yep everything was installed so we have netcode 1.2.0 and on dependencies we can see we also have the ND transport 1.3.1 okay so with the packages and so on let's begin using it so let's close this and let's begin working on the game scene so let's go inside of that now the first thing that we need is a network manager so let's create a new empty game object for the network manager as usual let's reset transform keep things nice and clean and let's add a component and let's add the network manager okay so this is the main component that netcode for game objects uses then for the setup down here the main thing is we need to select a transport this is what will actually send the packets so let's go ahead and select the NT transport and that's it and add this component down here with a whole bunch of fields for now we don't need to touch any of this so just leave them all in defaults importantly make sure that over here the connection data make sure for the address we have 127.0.0.1 this one is in localhost so we can develop and test the game in our own machine now if just with this if we had on play right now nothing really happens because we're still not synchronizing anything so let's do that first thing is over here on network manager we have a film for a player prefab this is what gets instantiated automatically when a player connects so the way we want our game is over here on the scene view we've got our player game object this one is just placed in the scene in single player we only had one so we had no need to make the same prefab but for now we do need it to be a prefab so let's make it let's just drag it over onto our prefabs folder there it is there's the player prefab and let's delete the one from the scene okay so far so good now we can go into the network manager and just drag the player and drag it in there okay we have assigned a player prefab but just like this it won't actually do anything that is because every object that exists on the network must have a network object component so let's select the player prefab and over here on let's add a component and let's search for the network object okay that makes sure that this object can exist on the network now let's open up the player script here is our script again all of this would be ultimately from scratch in the single player course so I assume you are familiar with all of this code and over here to make this a network object instead of extending mono Behavior instead of that let's extend the network behavior and this one we can see that this one exists inside using unity.netcode so let's set that and yep there you go this one is now a network Behavior so just by doing this change this script is already marked as a network script and by the way over here in the editor if we didn't add the network object so for example if I remove this and if now I click away and I select it if there you go now we've got a nice pop-up window telling us that we need a network object component so if you're ever making Network behavior and you forget to add the network object and you get this nice pop of windows then you can either manually edit just like within or you can automatically so just click on yes and if there you go now the player does have a network object again remember it must have this component in order for this to exist on the network okay so we have the player we have a network Behavior we have a network object and on the network manager we have it set as the player prefab so like this the network manager shouldn't automatically instantiate the player as soon as the player connects so if we test this and nope we have a ton of Errors right away basically what we have here is the first of many errors that we're going to see that showcase the difference between making a game in single player and multiplayer this specific error is over here on the slight counter visual over here we are accessing the player instance now in our single player game the player was added onto the scene by default so it was there right as soon as the scene was loaded which means that the player instance reference was already set but here in multiplayer the player is really only created when a connection is established so as soon as the game starts running there is still no player just yet so this instance is going to be set to null again remember how making multiplayer games requires a bit of a different mindset this is just the first of many examples that showcase why that is so important so over here for now let's just comment out the logic that uses this instance so let's go ahead change this and save and we can go over here onto the player script and we can find the other references so using visual studio I can right click and find all the references and I can see that there's just two more over there on The Sound Manager so let's go on to this line and over here let's comment this out and down here we've got another player instance and let's also comment this out then same thing over here on the player itself let's comment out this one just like this basically in multiplayer we are going to have just a single instance of a player there is no Singleton Since By definition we're going to have multiple players however we will have just one local player so this logic will still be useful in a little bit so that is why we are commenting instead of just deleting it but then down here on the awake we've got a test if the instance is already set if so we have more than one player again that's a mistake in single player but in multiplayer this is Perfectly Natural so let's cut these lines and then on this one just commented okay so that should fix some of the instance errors let's try playing again and okay so far so good we have no errors then over here on the network manager when the game is running we can see these three buttons we can start as a host server or as a client again I cover them in detail in the netcode video server is just a server the client is just a client and the host access both a server and a client so for our first player let's make it a host so if I click on this and if we still have yet another error let's see where this one is and if it's right here it's on the name input reference again this is yet another thing related to the different setup in single player versus multiplayer in single player the player was placed on the scene which allowed us to directly drag the reference to the game input but when we made the player into a prefab like this on this prefab we can no longer drag a scene reference the reason is because this prefab can be spawned anywhere on any scene so you cannot drag scene references onto a prefab but later on in the chorus over here for the game input we also made it use the Singleton pattern so over here on the player we can just modify that so for the game input instead of having a field let's go into the game input let's access the static instance just like this on all of these references so wherever we have that one replace it and down here replaced okay we have fixed another error so let's test again also by the way if you don't see the network manager game object that one isn't over here inside your scene it is actually inside the don't destroy unload scene so over here we have our buttons let's start as a host and the up now it works we have no more errors okay so far so good now using the inspector buttons obviously isn't very useful we cannot access these buttons from the game view itself which means we can't really click on it if we make a second build so let's make some simple in-game buttons on the hurricane let's go inside the canvas and inside let's create an empty game object call this the testing netcode UI then let's make it stretch to occupy everything so put 0 0 on everything now inside let's make a new UI image call this the background let's make this one in phone black and once again stretch it to occupy everything and put it wrong on zero okay then let's make a button so let's regularly create a new UI button conversely start host button and inside for the text let's say host let's change the vision a little bit so let's put the text in white let's put it in bold a tiny bit bigger and let's increase the size of the button as well so something like this and let's put it on a dark gray and put it on an X of zero okay so that's our basic host button let's lift it up a little bit then duplicate it push it down here this one is going to be the start client button and inside let's just say client okay we have our two simple testing buttons which is make sure they are on top of everything else so we can click on them remember how the Sorting ordering DUI works it is all based on the order in the hierarchy so in order to make this one always on top drag it to the bottom of the canvas hierarchy okay now let's make a script to run this so let's go into our scripts into our UI scripts let's create a brand new c-sharp script for the testing netcode UI let's attach it to our object and by the way if you're following along this specific entity version has this strange bug or if you drag a component that actually adds twice if you're using a later Unity version probably won't have this bug but if this is still the latest version by the time this video goes on just go ahead and remove the second one okay so let's open and over here let's just add some simple references to our buttons so as usual let's make it a serialized field of type button for the start host button and then we have another one for the start client button then over here in the editor let's drag the references so the host and the client okay and now let's add our click events so let's go make an awake and go into the start host button let's add an on click let's add in listener and for the enlistener when we click on start host let's go into the network manager let's access the class itself which again is inside using unity.netcode then inside that one there is a static Singleton and from there we can then call the function start in this case start host okay so this will start the host let's just do a debug.log so we can see so we are starting a host and then afterwards we want to hide this testing window so let's make a simple import void hide and on high just set this game object to active as false so that will hide it so we post a message start host and then hide and then same thing for the client so on the start client button on this one start as a client and just call the different function so start client okay that's it a very simple script make sure you drag the references and now we're ready for testing with multiple builds so let's go up here into file and let's go into build settings now importantly for our single player game we were starting from the main menu but here when we're developing our multiplier game we really don't want to have to go through the main menu every single time so let's just drag the game scene on top so that is the one that we start with then over here select your target platform for me I'm going with Windows and then for some other settings let's go down here into player settings this opens up the project settings and goes into the player Tab and over here let's go inside the resolution and presentation and now in order to make testing easier let's make it with Windows instead of full screen so put it on windowed then the Size Doesn't Really Matter let's just make sure we run it on background so the game keeps running even as we switch between the windows and then down here let's make it a resizable window that way we can stretch and fit them in order to fit multiple windows on our screen okay so these are the settings let's just close out of the project settings and over here let's go ahead and make a build just go ahead choose a folder and build alright so here is the build so let's open it any up here is the build running now in the editor let's head on play as well so we've got both of them now in the editor let's click on host and down here let's click on client and here both are connected and we can verify that so on the editorial let's minimize this and we can look in the game scene over here see yep we do have indeed two player clones alright awesome now of course this is just a Bare Bones connection so if I move this player there you go both players are moving and obviously the movement isn't being synchronized so we're going to need to fix this in the next lecture but the important thing is that we have a nice network connection on fully established this is the absolute Basics and basically all we need now is just to synchronize everything now before we end this lecture let's just do some more small things first of all on the game state right now the way we made our single player game is we have this controls window then we go into a three two one countdown and only then the game is actually active now this is great in terms of the funnel game but it's a bit annoying while developing and testing the multiplayer game so let's just modify the code to skip this part let's go over here onto the kitchen game manager and down here we have all of our various things so we have that we start off on waiting to start end to end when we get some input we go into the countdown which then counts down the countdown timer so let's basically just make this start playing automatically so let's go over here on start and let's just run the code to automatically start it so let's run this let's put a comment here so we remember why we made this so just say debug trigger game to start automatically okay and also same thing for the countdown timer so Pierre for this one instead of starting on three seconds let's start in just one second and then also important over here for the game playing timer Max pretty soon let's make sure we leave enough time so let's say something like 300 basically we don't want to trigger a game of well we're still busy doing some testing okay so let's test here in the editor I click on host and there you go the game starts playing right away okay great now for one more important thing when testing our multiplayer game we're going to need to read the logs now here in the editor we can just access the console and read it but in the build we don't really have this so to some of that there is one extremely useful asset that I like which is called the quantum console although I should point out this step is optional you don't need this asset to make multiplier games it just makes it a bit easier so before I show the yes let's see how you can read logs without it so over here I have both builds running so on the editor I can read the console but on the build I cannot if you go on to the ENT documentation here you can see the path for where all of the unlock files are now in this case we want the build log so that's not the add to roll in log so let's scroll down and down here we see the player related logs in this case I'm running on windows so this is the path that I want to find so it's under user profile app data local low then the company name and the product name now for the company name and product name for that you go into file let's go into build settings and let's go over here into the player settings and over here on the player tab up here you see the company name and the product name so make sure you write these before you actually make the build and if you go to that path you won't see these logs so if you go ahead and open this text file if there you go here we do see the logs for the actual build so over here on the build I just started as a client so it just allowed the client message and it is exactly what we see over here also by the way you can just keep this file open and just press F5 to refresh it for example if I exit out of the build it is going to update the log so if I exit this and over here I press on F5 and there you go it updates everything so this is the minimum wage read it you just go to this file and refresh it so that works but having to have this file open all the time and having to refresh it is a bit annoying so personally I really like using Quantum console which easily adds a console that you can also see in the build and in general it's just a great asset all around really useful for all kinds of testing I made a fully detailed review on it if you want to learn about it and there's also in the film Link in description if you want to get it but again this is completely optional if you don't want to buy this asset you can just keep that file open and hit refresh just to read the console now since I do have that asset I'm going to use it to make developing easier so I'm going to go into window package manager I'm going to go into the my assets then just search for the quantum console and up here I have the asset so I'm just going to import it I'm going to import everything then over here in the project files inside the plugins folder qfsw Quantum console source and over here is the prefabs any of there are two prefabs this game is made using urp which is an SRP so let's drag this one there you go there's the quantum console now I'm just going to resize this a little bit so inside on the console rect I'm just going to move this make this a little bit thinner okay something like this and that's it there's nothing else we need to do so now if we just go ahead build and run any up here is a console which we can now easily read the editor unlocks for both the editor and the build okay great now just one more tiny thing related to the setup if we unlock in the network manager over here there's something called the unlock level you can put it on normal error nothing or developer mode now normally I would put it on developer to get as much info as possible but it seems that this version of NGO has a bit of a weird bug during my testing later on when we add some animations it was constantly pushing a weird warning which was causing tons of issues so because of that over here I'm going to leave this on the normal out alright so that's it over here we created the basic setup we installed all of the packages that we need and we set up the network manager so we have a player prefab that we can then instantiate all of the basics are perfectly set up now that's left is really just synchronizing the entire game so let's begin doing that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to handle player movement and as we're doing that we're also going to talk about something extremely important whether to make your multiplayer game server authoritative or client authoritative both methods are valid I'm going to Showcase both them and then it's up to you to decide which one best fits your game okay so the basic setup is already working we have the network manager set up so over here with these two builds I can start this one as a host this one as a client and yep both of them are connected so far so good however if now I move with some input yep both objects are both on the exact same position and they are both moving with the same input and of course the movement is on local so nothing is being synchronized so let's end on this for the first problem we just need to make one small change over here on the player script like we saw right now the input is moving both players but we don't want that and the movement is down here we have our update where we are handling the movement and interactions both players have this grip so both players are running this code but we only want a player that is local to that building to run this code and how we do that is very simple on the network Behavior we have a bunch of nice properties we can check out a bunch of is things so we can check his client is host his local player his owner is server and so on and basically for this one in this case for checking if this player is in local player we can check his owner that is because the player game object won't be owned by the player when that player joins and that object is spawned so if we checked his owner this one is only going to be true for the unlock on player so we only want in local player to run this so over here we can just check if this one is not the owner if not then we just return so this one will only be true for the local players so only the local player is going to run the movement and the interactions okay that's it that's the only change now if we test so here are the two players and if I move just this one up here yep it only moves one and down here and yep it only moves on okay great however of course as I move it the movement is still not being synchronized the client down here still thinks that the host is over there on the spawn position same thing on the host some things that the client is over there so let's synchronize the movement and we can do this using a super simple component let's go over here onto the player prefab and we can just have the component search for our Network and let's add the network transform basically this one synchronized all the transform data we can even use these check boxes here to help reduce the bandwidth by only synchronizing the things that can actually change for example in this game the player only ever moves Left Right further than back there's no jumping involved in this game so there's no need to synchronize the Y position for the rotation we're only going to rotate on the Y so there's no need to synchronize these two and for the scale the scale is never going to change so we can also not synchronize these two okay so this won't synchronize the transform and only the things that actually matter and this is where the question of server versus client auth comes in the way this component works this one is only server authoritative so if we try like this let me go back outside save the changes and make a build so here are both builds up here the hose down here the client now if I move on the host if there go the host does move and it does get synchronized over there on the client so that's great that looks like it does work however if now I go down here onto the client and I move and nope the client doesn't even move I'm pressing the buttons the animation is actually playing so the input is being received but nope there is no movement that is because that component the network transform that one is only server authoritative meaning that only the server which is also the host only this one has authority to move this transform if this local client down here tries to move it then basically just snaps back to where the server says that object is like I said I'm going to Showcase both methods because both methods are valid let's begin by looking at the client auth method and for this one we are going to use a different component we can go into this page so onto the docs you can just go into the docs themselves and go into the netcode for game objects then go under components and go into the network transform page so on this one if we scroll down down here we can see a client Network transform this is exactly what we want it allows for client authoritative gameplay so we can either import the entire samples from git or just down here we have on the code so I just go ahead and copy all of this code then over here in the editor let's just make a new c-sharp script call this the client Network transform and then over here just select all and paste entire code that's it so here basically all it does is just extends the network transform and just does an override on is server authoritative and returns phones so this way this one is no longer server out and works as client out so now if we select the player prefab and over here let's replace the natural transform for the other one so the client Network transform and let's add the syncing on the same thing okay that's the same setup so we just change the component now if we test this so here is a host and as I move it yep it does get synchronized and down here the client as I move it any up now this one does get synchronized so we can move both independently and both of them are being synchronized alright awesome so this is how you can make your game client off meaning that the client has the authority to make changes on the server State this has some pros and cons which I'm going to talk about in a bit but before that let's actually look at how to make this internally server auth basically in order to make this server authoritative we need to make sure that only the server can move the objects the client can request a move but it's up to the server to decide whether to actually move it so we're here on the player script let's go down into where we are handling the movement so on the handle movement function let's go to this one and basically what we want is over here we are moving the transform position directly and again remember this function is going to run on the unlock on client every client is going to run this whether they are the server or just a regular client and to make this server out we need to make sure that only the server runs this code so how we can do this is basically do a server RPC to tell the server where we would like to move now if you don't know what is an RPC at all make sure you watch my netcode video basically it's a remote procedure column meaning it's a way to run code on the server or the client from another place so here the clients will tell the server where they would like to move also by the way for this section I'm going to rewrite this code to make it several auth but then I'm going to come back to this state the rest of the game won't be client Earth so if you're following along there's no need to follow this part so for that we're going to have a function like handle movement call it server auth this one is going to run on every client so on this one all we get is the input and then we're going to send the input to the server so we're going to do that with an RPC so private void handle movement server RPC and on this one we are going to read a vector 2 for the input vector then we need to mark this as a server or PC up here we are going to call this function and pass in the input vector and then down here we're going to run the exact same code so I'm just going to copy all of this so just copy and paste the exact same thing so we get the input converted into a move Direction and then the server itself is actually going to move the object and that's really it that's how you make it server out so let's go up here instead of running this function let's run the one with server auth okay that's it here then in the editor let's just go into the player and once again let's remove this one and add the other one so the network transform let's add the regular one this one is server auth and again the same thing then now we can test so here we are and if the host moves and yep everything does move that's correct and down here on the client if the client does move and yep it does still move all right awesome so in this case making it server auth is actually pretty easy the basic idea is you only actually modify the game say just on the server the clients can make some requests but the server is the final source of Truth now let me talk about the differences between server and client auth and where you'd want one versus the other the obvious Pro for server auth is security if the server is the only source of Truth for the game say that makes it much more difficult to hack the game the server gets requests from the clients and then can validate those requests to see if the values are valid meaning for example if the client down here if it tries to move on to an impossible position the server can just say nope you cannot move there whereas if the game is client off with that technically a hacker could modify the game files to change something like the player speed and make the player move much much faster since the server would just receive an accept the player position that would actually work a hacker could modify the game and suddenly the player can walk through walls because the server just accepts whatever the client gives it but if it is server auth then the client just sends an input and if that input has a bit of a weird magnitude then is it expected if so then the server can just revalidate that input and that way the hacker can no longer move faster than expected so when it comes to multiplayer the big question is really about trust so do you want to trust a client or not if you do and the client is malicious then they might break the game they might get some infinite money or just walk through walls so with that said you might be thinking that means server auth is the way to go all the time but the answer is it really depends on what kind of game you're making server auth also has some downsides building a purely server off the game really requires quite a bit more complexity you need to validate every single input and everything coming from the player that really complicates things so there is a cost to making it server auth it does require some effort one example as to how server auth is much more complex is simply with regards to client-side prediction so right now the game actually looks pretty normal New Movement looks pretty good so I'm moving around over here on the client and everything does seem pretty correct but that is really because I'm only hosting the game locally so right now I'm seeing pretty much no lag now thankfully the unity transport over here actually has some nice debug fields we can for example over here put 500 milliseconds of DNA to test the difference so now here I am playing with the same server auth and if I move on the server over here the host is nice and responsive everything works fine because this one is actually the host so as I move it does move automatically however down here on the client I'm going to press a button hard so you can see so move and yep look at that it takes half a second for the player to actually move so I press the button and it takes 500 milliseconds before that one actually responds to input now if you launch your game like this every player would find this completely unacceptable you cannot have the player press a button and then have to wait a long time for the changes to reflect in their own build so if you implement server off then you absolutely must Implement client-side prediction which is a pretty complex topic basically you would need to create just a local object then when the player press a button you would move that local object to where you think it won't be when the message actually gets the server whereas if you just make it clean dot you don't really have to worry about any of that the client updates automatically and then the changes are sent to the server so when working on games kind of like this something casual in Co-op for this client auth is usually somewhere and won't work just as well people will be playing in co-op with their friends so if a friend really starts cheating they won't just stop playing with Aspirin in the end the basic General answer is if you're building some kind of PVP competitive game then you probably want to go with several to some cheaters but if you're making something Co-op something more for fun rather than competition then those cases you're probably best to go with clientot now this game is exactly that it's a casual Co-op game so for this game I won't be going with the client auth approach so with all that said let me revert back the changes to make it client off so over here I'm going to get rid of this function and go back into the general in the movement and down here I'm just going to take these and both these functions Get Rhythm so exactly the same as previously then back in the editor on the player let's once again remove this one and add the client Network transform instead same thing let's not synchronize all of these and finally on the network manager down here let us not add some debug delay okay so let's test again so here I am if I'm moving the host yep everything works down here on the client move it and yep everything still works alright awesome so here we'll learn how to synchronize basic layer movement and importantly we also learn the differences between server and client auth and which one you should choose depending on what game you're working on now like this so far we only have the movement synchronized our nice animations aren't actually playing so let's solve that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize the player animations this is actually extremely simple to do in netcode for game objects so this is actually going to be a super quick lecture okay so here we have our players and both the hosts up here and the client down here both of them can move and the movement is indeed correctly being synchronized so it's all good except only the movement is synchronizing so as I move this one up here it's playing the animation but down there nope no animation so let's fix this and in order to fix this once again we have two options the default way is using the built-in component the network animator so let's go inside the player prefab and over here we've got the player visual this is the game object that has the animator so we can add a component and let's add a network animator this one takes an animator film so let's just drag this animator put it on there yep there it is now this will automatically synchronize the animator and all of its parameters now before we test let's just see one very important thing over here on the player animator this is the script that we made in the single player game over here for this grip we need to make sure that this one only runs on the owner otherwise this script will then override the network animator so instead I'm going to be here and let's make this a network Behavior let's add unity.net code and down here on update if not is owner so if not is owner just return okay and by the way this object doesn't need a network object because there's already one on the parent player game object okay so like this we've got the network animator something like this it should work so let's test so up here if we move on the host and if they're going with that the animations are indeed being synchronized okay so that's great all we really had to do was just add this component and the entire animator state is already perfectly synchronized so that's awesome however if I go over here onto the client and as I move it let's see and nope over there we do not have the animations being synchronized again we have the exact same issue that we had previously with the network transform the network animator just like the network transform is server authoritative so it will only work if the server is the one sending out the commands and it will not work when the client is the one trying to send out the commands that is why over here the host does synchronize with the client does not so again we have our usual two options we could modify this code to make it server auth basically use some server rpcs to tell the server what state the animator should be in or alternatively we can make the network and meta client auth let's go with that approach and again the docs have a nice simple script to make this so if we go into the multiplayer docs if we go over here into netcode for game objects then under components and under the network animator over here if we scroll down we can see yep the owner authoritative mode so if the client is the owner which it is on the player if so then this becomes a client authoritative mode and you've got the script and literally is just this super simple so let's go ahead and copy this then back in unity over here let's create a new c-sharp script for the owner Network animator and over here let's just select everything in paste the code okay that's it super simple now let's go inside the player prefab and over here on the visual let's get rid of the network animator and instead at the other one the owner Network animator this has the exact same field so let's just paste it and just like this some of our animation should already be perfectly synced so let's just go outside save the prefab and make a build so up here is the host and as I move it yep the host is indeed synchronized and down here on the client if I move it any of the client is also nice and synchronized alright awesome so as you can see really is this simple to synchronize animations in multiplayer you just set a component and that's really it so with that we now have the movement and the animations both of it working perfectly and synchronized DC were pretty simple thanks to the built-in components and now we can start handling how to synchronize some proper game logic like for example the delivery manager and that's exactly what we're going to do in the next lecture hey there here's a quick intermission so how are you doing are you enjoying the course so far are you having any trouble with anything is there something you didn't understand multiplayer can be complex but once you understand it I think this tool set is actually pretty easy to use just make sure you fully understand the differences between all the types so what is the server and what is a client if you get that part then everything starts to become pretty straightforward so from that let me ask you what has been the most challenging part so far remember that I'm always active in the comments answering all the questions every day so if there's anything you need extra clarification go ahead and ask and I'll do my best to help also remember to check out the course website I will keep that page updated with frequently asked questions so you can see what others have asked for each lecture and you can also download the project files at each point and compare with your own so keep that page open on the second Tab and check it out every time you start watching a lecture I hope you are enjoying the course and already learned quite a few things go ahead and hit the like button and subscribe to the channel if you haven't already Okay so let's go to the next lecture hello and welcome I'm your code monkey in this lecture we're going to begin synchronizing some proper game logic by handling the delivery manager okay so for our first lecture synchronizing the game logic let's begin with the simplest one which is really just the delivery manager so here we have the game playing right now we have two players connected the movement and the animations of it is being synchronized but for example over here on the recipes note that each client is generating their own recipes that is not correct we only want the server to generate recipes and we want all clients to be seeing the exact same recipe waiting list then we also want to synchronize whenever a player delivers a recipe either correctly or incorrectly and again here we have to answer the same question as always do we make the server auth or client off but before that let's start from the beginning let's first go up here onto the delivery manager script and as usual let's swap out the mono behavior for a network behavior and let's go ahead and add unity.netcode then over here in the editor let's find the object with the delivery manager and as soon as you so like that yep we've got the nice window so let's go ahead click on yes and there you go it does have the network object so back onto the delivery manager like I said we only want the server to generate recipes the other clients should just receive the recipes from the server so let's go down here and where we have the update where we count on the timer and spawn the recipes over here we want to make sure this logic only runs on the server so like we saw if we have a network Behavior we've got all kinds of is properties in this case for running things on the server we can ask is server so if the Nissan is not the server if not then we just return okay so let's do a quick test and yep both the host and the client both of them are connected but only they're the host only that one is generating recipes okay so far so good now we need to do is really just synchronize e-spawn recipes so that the client knows about them and for that we basically have two options we can use rpcs or we can use a network variable both are valid options I cover them both in detail in the netcode video the one big difference between them is mostly related to late joiners so if a player joins late they won't receive the current state of a network variable but they will not receive the client services that were sent before that time this means that it is actually very important for you to decide whether you want to allow late joining in your game or not that is a very important decision that will decide how you implement certain features for this game this is a simple game with a short session duration each game session is really just only about 2 minutes so for this game I'm going to decide to not allow late joining so all the players join in the beginning of the game and they play until the very end no player can join the middle making this Choice really helps cut down on the complexity needed to make this game and near the end of course I will have a lecture talking about this difference in more detail and what you would have to change if you want to enable the game to support late joiners the main takeaway right now is that this is a very important question you need to ask yourself when making your game in my case like I said for this game we are going to not allow late joiners so for synchronizing the standard we going to do it through the simpler RPC method although also don't be confused rpcs and network variables can both be used regardless of what you choose it's just that in a design that is meant to support light joiners you probably want to use Network variables more often but even if you don't want to allow it you can still use Network variables just like we will use later on in this course okay so with all that said let's implement the synchronization with rpcs back in the delivery manager over here on the update basically the server is generating all of the recipes and when it does we want to tell the clients that this specific recipe has been generated so let's make a client RPC to tell the clients to spawn a new waiting recipe so let's go up here make a new function private ruined let's call it spawn new waiting recipe and as we know from seeing the other netcode for game objects video on the client rpcs must end with client RPC so let's end this with client RPC then to make this an RPC we also need to add the attribute so client RPC and finally the goal is to spawn a new winning recipe so let's receive the recipe so that we want to spawn so this is the waiting recipe so again remember the RPC rooms that I covered in netcode video so first one is make sure the name ends exactly with client RPC so it has to be like this it cannot be in lowercase and so on so it has to be exactly client RPC then make sure you add the attribute and also remember how the client rpcs actually work basically the server will call this function so up here when we generate something we are going to call this and pass in the waiting rest PSL so the server itself is running this code and calling this function but in reality this function will actually run on every single client also remember that the host access both a server and a client so the host will be running the code up here and also the code over here for the client RPC so up here we trigger the client enter PC to spawn the recipe and then down here we just do our local logic so we add it to the list and we fire off the event okay so this looks like valid code we have no errors however if we go back in the editor you appear in the console we do see a bunch of errors this is also important server and client rpcs have various rules and Foundation which does not run on Visual Studio but it does show up over here on the console in the editor so when you make an RPC always check the console to make sure you didn't break any of these rules for example this rule here is telling us that the netcode library does not know how to serialize our recipe so object basically for rpcs we can only synchronize value types or we have to tell netcode how to serialize them the more complex option is to implement I Network serializable I cover that in the netcode video but a much more simple option is to just use a type that can already be serialized for example over here on this script we already have a recipient list so and for deciding which one is going to be the wedding recipe we are really just randomly generating an INT so generally a random index so we can just modify this code so that instead of sending a recipe so instead of that we can just send the index of where it is on the list since all the clients have the exact same list by sending the index we're actually going to be able to get the exact same ASO so let's do that so over here instead of a recipe so let's receive a parameter of type int this is the waiting recipe so index and then up here let's also Define that so the in for the wedding recipe is on index and we do our random.range so the usual stuff then we pass in in this as our parameter and then down here we can simply get the waiting Rest vso by just going into the exact same array and grabbing it from there okay so that's it very simple again remember that the host access both a server and a client so the host will run both the code up here as well as the code down here so importantly make sure you only add this local code adding it to the list and spawning the event make sure you only add this one down here and not also down here as well as up here if you add it in both places then the host will end up spawning two recipes every time now before we test let's just go up here for the spawn recipe timer here this one starts off at zero and we count down meaning that literally on the first frame it is going to spawn right away let's add a bit of time over here let's say for F this is just so we have some time to press the host and the client buttons before anything is actually spawned okay so with that let's test so up here let's connect the host down here the client and now let's wait a little bit and see if the recipe is spawned and you better go down and spawn the recipe and yep that one did yet the recipe synchronized so it's one that one and then that one so they both have the exact same recipes and if we ate a bit yep both have the exact same max amount of recipes alright awesome now here let me make one point later on in this course we're eventually going to synchronize the game start the game countdown and so on so when we do this code will work perfectly but right now you do need to make sure that you connect the host and the client as quickly as possible if instead I connect the hose here and I wait four seconds to spawn a recipe so just wait a bit I want to spawn and now I connect down here on the client if I do that then you have to look how now we have two recipes but down here only one recipe so this is a good example of the difference between Network variables and rpcs basically this client joined late so because of that it missed the RPC spawning the first recipe but again like I said for the design we're going to do this scenario where the player joins late this one is never going to happen just make sure that during testing you click on host and then on client as quickly as possible so you get the actual improper behavior and not just a testing bug okay so now that we have the spawning synchronized let's handle the delivery if I go on the host and I just try to delivering something right now there you go only that one receives it this one down here has no idea something was delivered so we need to synchronize the actual delivery back in our delivery manager let's go down into the function here it is the delivery recipe here we are going to have the exact same question as always so do we make the server auth or client auth meaning do we validate the delivered plate on the client and then the client tells the server whether it was a correct or an incorrect delivery or does the client pretty much only send the Plate Kitchen object and then the server validates the contents again for this Co-op game let's just trust the client and go with client art so the client is going to run all of this logic and then down the end it won't tell the server whether it was correct or incorrect In this case we want the client to tell the server so instead of a client RPC we're going to use a server RPC so let's go up here and make a private void deliver correct recipe server RPC and we're going to add the attribute server RPC okay this is it however this will only run on the server again remember the very very important differences between server host and client if we do it just like this and I copy the code so the local code for delivering the correct recipe and I just put it like this if we don't like this then only the server will run this function so if you do it just like this the client will not know that the recipe has been delivered so always remember those two types server and client basically we want the client to tell the server that it delivered a correct recipe but then the server needs to broadcast you all of the clients that that behavior just happened so when the server receives a server RPC we then need to send a client RPC to broadcast that message to all the clients so let's go down here make a private void deliver correct recipe this time it's a client RPC and we mark it as a client RPC and then it's down here that we do the actual behavior for actually delivering the correct recipe so then on the server PC it just calls the client RPC which again remember how this runs remember how the host is both a client and a server so if we run this on the host the host is going to run this function and then the host is going to run this code and then the host is also going to run this one whereas a client a client is going to call this function but then the client itself does not run this the server runs this calls the client RPC and then the client will also run this function so with this the logic should be working correctly on the all of the correct places we just need over here we need the index so this is the index of the recipe that has been delivered so I just added over here as a parameter since it's an INT we can use it on a server and a client RPC so let's just find an end for the waiting recipe SL list index and up here we pass in the eye then we pass that one in onto the client RPC and then we just use it over here okay so the correct delivery has been synchronized now let's do the exact same thing for the incorrect recipe so let's do a private Droid deliver incorrect recipe for the server RPC and then we're going to have another one but this one is going to be the client RPC then let's say the attribute so client RPC and up here we've got the server RPC then the server is going to call the client RPC to deliver the incorrect client RPC yep just like this and then on all the clients we're really just going to fire off this event so just like this and we're going to trigger the server RPC up here okay so that's it some pretty simple logic as long as you understand the flow for how the server rpcs in the client rpcs work as long as you understand that then all of this is pretty straightforward so let's do a test and see if this works so up here on the host let's deliver a correct recipe so let's make a quick Burger so just put that on the fryer let's grab some bread pick up some plates pick up the meat pick up the bread and now if we go ahead and deliver it and if there go it does work both them so it only re-success and both of them removed it from the recipe list okay that's great but now down here if we do it on the client so let's try to deliver a cheeseburger so let's pick up some meat cook it let's pick it up we just need this and let's try delivering it over here on the client and nope over there we have an error this error has to do with ownership and just like it says only the owner can invoke a server RPC that requires ownership since the delivery manager belongs to the server and not the client that means that only the server can trigger that server IPC that is the default behavior for Server PCS they can only be called by who has ownership and to solve this problem we actually have a very simple solution over here on the server RPC attribute we can have some optional parameters and one of them is down here the second one the require ownership so we can set require ownership equals phones and this way the server RPC no longer requires ownership in order to trigger the server RPC that means that the client that does not own this network object will be able to trigger This Server RPC so let's see this both appear on the incorrect recipe and down here on the correct one okay so just with this change Let's test so down here on the client let's try deliver a salad so let's pick up the tomato and just slice it then pick up some cabbage and slice it pick up some plates put both of them in there and let's go ahead and deliver and if there you go delivery success alright awesome now let's try delivering a final recipe and yep that one also works and up here on the host deliver a film recipe yep also works and now we success so let's cook a nice burger now let's go ahead and delivery correct and if there go delivery success alright awesome so we have everything everyone logic working now with this working let me just quickly talk about how you could make this system server off the answer is really just like I mentioned a while ago so over here instead of running the validation here and then telling the server whether correct or incorrect instead of doing that the client would simply tell the server I want to deliver this Plate Kitchen object then the server will check the contents of the plate and basically validate them as long as you make every step of the process for ADD adding ingredients onto the plate as long as you make all of that server off then the internal logic would be fully server off but again in our case for our simple game let's just stick with the simpler client off so here the client validates the plate and then just tells the server whether it was correct or incorrect then the server receives that RPC and simply broadcasts the message to every single one end okay great so over here we handle synchronizing our very first custom game logic to make our game fully multiplayer we really just need to apply the same process to every other part of our game but before we get to synchronizing some more things let's quickly fix just one minor thing when we first converted this game to multiplayer we had to get rid of the player Singleton which in turn broke the selected counter visual so let's fix that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to fix the interact selected visual okay so here is the game so far I can move around as either the host or down here as the client but when I look at a counter nope there's no selected visual there's no select Vision down here nor over here on the host so let's fix that now this is actually super simple the issue was over here on the player script we had our instance but in multiplayer we don't have a single player instance and it's also not spawned automatically however we still have just a single local player and that is really all we want for the select visual so let's uncomment this code and instead of instance let's rename this to a local instance so this is going to be the local player and for assigning it usually we do it down here on awake however when dealing with multiplayer in netcode for game objects for networked objects you really don't want to usually use the awake or the start inside there is a similar function that is specific to netcode that one is called on network spawn so we're here public let's override override the void on network spawn so this one basically this function is called when this object is spawned on the network so over here we can just test if is owner so that will mean that this is the unlocking player so if so then just set local instance set to this so you do this and over here on awake we don't do anything okay so that should pretty much set the in local player over here on the local instance then let's go over here onto the selected counter visual script over here we were listening to the event and we just do the exact same thing except now it's called local instance then the rest of the code is exactly the same however if we do it like this we're actually going to have the same problem that we saw previously again that is because the player is not going to spawn by default it is only going to spawn when we press the host button so if we run this then this is still going to give a non-reference exception we don't want that so basically we need to know when the player spawns so let's go back into our supply script and up here and let's make a nice static event so a public static event event handler and let's call it on any player spawn we're making this static because we want this event to be long to the player class itself and not any specific player so we have this event and then down here when we have the onetwork spawn when this one happens let's just invoke this event as usual so this an event args.empty okay so now we have this nice event now we can go back into the selected counter Visual and over here first let's test if it already exists so if the local instance is not known if so then just assign it right away but if it is known if so then let's go into the player and the on any player spawned event and let's listen to this event and when this happens we're just going to run the exact same code so check if there's any local instance and if so listen to the event however yet another potential sneaky issue here this event won't fire multiple times for multiple players so if the first one were the in local instance then we could end up with multiple listeners which would cause a lot of duplicate logic so in order to make sure that doesn't happen let's just duplicate this and we do unsubscribe and then we subscribe this way we make sure that no matter how many times this event is fired that we're only going to have a single listener okay so that should fix it however unless you do one more thing like we saw at the end of the single player course for static events like the one that we just made those can cause problems when changing scenes that is why we made this class at the end of The Seven Player course so since we added a static event on the player let's also clear it so we can just copy the function from one of these so it's just a static function to do that so let's copy this let's go into the player and over here on let's paste our reset static data function and we just set the event to no then we just need to go into the reset static data manager go into the player and Trigger that function so this won't clear up and not cause any problems okay so with this let's test so up here let's make a host down here make the client and now on the host if I move and I approach that yep there you go that counter is now selected and down here on the client we can see that one does not show up as selected and now if down here I select a different counter yeah there you go now that one does show up and selected so the selection logic is fully working and it is local to the local player alright awesome let's just fix one more related thing over here on The Sound Manager down here we were also listening to the player event when the player picked up something so we could uncomment this and listen to the local instance however now we're going to have more than one player and we don't want to listen to this event only on this local player we won't listen it on any of them so if any player picks up something we want to play that sound so as usual let's make another static event so back here on the player class let's make another one public static event event handler and let's count on any picked something so just following the same pattern as usual and we're going to fire this on the exact same place where we fired the unpicked something so let's go down here where we set the kitchen object so it's on this one and let's just invoke the event passing this and even RX not empty so over here instead of listening just on your local instance let's listen to the on any picked something and that is going to run this function and again let's uncomment this code and over here we also don't want to play this on the local instance position we want to play it on the position of the player that actually picked something so we can just grab the player and grab the play reference from the sender as player so over here just use the player transform that position okay so that should do it let's test okay so up here is the host down here's the client and now if I go ahead and I pick up something and technically this did work so we don't have any errors anywhere but we can really test that this is working because we haven't yet handled syncing and picking up the objects so when the host appear picks up something the client down here doesn't know that actually happened but we don't have any error so the code is not working perfectly with that now let's hand on synchronizing the object pickup in the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize picking up objects now this one and the next lecture are going to be some quite tricking lectures it requires us to learn various quirks with how netcode for game objects works so definitely do pay attention if you manage to understand everything in this lecture in the next one then you will understand pretty much most of what is required to build any multiplayer game okay so right now we can walk around as either the host or the client but if one of them picks up something like for example appear the host the host picks it up and nope the client down there does not see it so we need to synchronize this now this topic involves first of all spawning objects so when we pick up a kitchen object from a container we are going to spawn it and for spawning objects you always need to do it on the server so let's go over here onto the kitchen object script and like we already saw in order to make this script multiplayer inside amount of behavior let's implement the network behavior and this was in inside using unity.netcode okay so let's go ahead Swap this and save and back in the editor we need to attach a network object so let's select every single kitchen object over here and let's click on no just to be able to select all of them and now just add component and let's add a network object okay so like this all of them have a network object okay so far so good now we're going to spawn these objects dynamically and for any object that we want to spawn the server we need to add it to the network objects list so let's go into the network manager and over here we've got the natural prefabs every object we want to spawn needs to be here so let's go ahead and drag all of these so just add all the entries and drag alright so here are all the references make sure you add all of them so you don't get any strange errors so over here we got 3 6 9 10 11. and over here 3 6 9 10 11. okay great so now that this network match is set up let's see how we're going to spawn it let's go over here onto the container counter this is where we are spawning some kitchen objects so let's inspect this function so here it is the spawn kitchen object function and to do that we are just going to the script more object and in searching it in the prefab now like I said spawning objects needs to be done on the server and how we are going to enforce that is by using a server RPC so technically we could just mark this function as a server RPC however for this function we made it static and we cannot make a server RPC static it needs to be a non-static function so technically one alternative would be to remove static over here make this a non-static function but then we would need a reference to a kitchen object in order to spawn more kitchen objects so that's not very good instead let's make a general class to handle our specific multiplier logic so we can get return let's create a brand new c-sharp script this is going to be the kitchen game multiplayer let's make a game object with the same name let's reset the transform and attach the script and let's open it again just one there's this weird bug in the CMT version so just one let's open now over here first of all as usual instead of monobehavior let's make this a network Behavior so back in the editor let's just set the network object component okay great over here let's begin by making this a Singleton so the usual stuff so public static kitchen game multiplayer call it instance and we've got a public get and a private set and on private void awake on awake let's set the instance equals this okay we have the nice Singleton that we can use now let's just copy pretty much the code exactly so let's copy this let's go into the multiplier and over here let's paste it except this one is not going to be stunning so like this then back over here on the kitchen object is essentially just going to be a pass-through function so let's go into the kitchen game multiplayer access the incense and spawn this kitchen object so passing the kitchen object the so and the kitchen object parent so this just like this also the return type is going to cause some issues with the rpcs you cannot have a return other than void when you're working with an RPC now in the single player game we made this return a kitchen object just in case we needed it but we never actually end up using it so just swapping this out for a void shouldn't break anything and same thing on this other one so let's go in there and over here inside return kitchen object just return void okay so far so good so now we have this function where we want to spawn a kitchen object now again this one is still not a server RPC we're going to add that in a little bit here we are instantiating to spawn the object and then we get the kitchen object script and then we set the parent then here on the function for setting the kitchen object parent we do a bunch of logic and then importantly we modify this transform.parent now changing the transform parent is actually going to cause a lot of issues with netcode so for now let's just comment out this part so this doesn't run let's just do it like this first the test that spawning is working and then we'll worry about this so here we are spawning the object however just like this we are really just finding the object locally in multiplayer when spawning something we need to go into the network object and spawn it so it actually spawns on the network so let's grab this kitchen object transform and let's see we get component of type Network object so we get this network object so the kitchen object the network object we get this one and then we can call the function spawn and this is actually going to spawn non-nentor then takes the parameter for destroyed scene so let's make this work just like any other game object so by default game object gets destroyed when you change scenes over here let's do the same behavior okay so let's test and see if the object is being spawned on the network okay so here we have a host and a client and on the host I approach this and I pick it up and if there go it did work the object will spawn over there on the host and also over there on the client okay so so far so good but now if I go down here on the client and let's try to pick up something so let's go in there and pick it up and nope there you go we've got an error as it says only the server can spawn Network objects so this is the error that I mentioned we need to use a server RPC to make sure the spawn code only runs on the server so we're here on the kitchen game multiplier script let's make a server PC that will actually run this code so let's do a private void spawn kitchen object server RPC and let's mark this as a server RPC and we're going to want the client to be able to call this so as usual let's make sure the set require ownership equals false so that the client can call this and over here we are just going to run this code just like this so now we need to pass in the kitchen object that so as well as the parent so let's put these as parameters so just like this and okay we see no errors here and up here we are really just going to call this so kitchen object this so and then the kitchen object parent okay it looks good but if we go in the editor and I hope we see a bunch of Errors so this code is not valid it's pretty much the same problem that we saw previously we cannot pass in a script object because it does not know how to serialize it so over here let's use really the same solution let's just convert this crypto object onto an index so for that we need to define a list of kitchen objects so now we could go up here and just find a serialized film for a list that would work or let's do it just like we did with the recipe and make a proper kitchen object list so if you remember in the single player course we made the recipient list this is a scribble object that holds only several of our recipes so let's do the exact same thing to home a list of all of our kitchen object SOS so let's go ahead and make a new script in you on these script mode objects let's create a brand new sharp script call this the kitchen object list so and over here on let's make this a scriptable object and inside we just have a public it is going to be a list and it's going to be a list of kitchen object SL and just call it kitchen object that's selling list okay now in order to construct it let's add the create asset menu and now in order to be able to construct an object we need to be able to compound the code so let's go back into the multiplayer and over here let's just come without the RPC just so our code compiles so just comment on this okay so now making the editor the code compiles so let's go inside the kitchen object so folder and create the new a new kitchen object list of so and let's give the name and start with underscore just so it shows up on the top of the list and okay now here we have the list so let's just populated so let's use the nice inspector unlock button or unlock it and just select all of them and just drag all of them onto the list okay great so now we have this group magic that holds a list for all of the kitchen objects it shows and just make sure we don't accidentally create more of them which is coming out the create SM menu so we cannot create any more and if we go over here on the kitchen game multiplayer we can add a serialized film and we can make it a type kitchen object list so so we have now this field and back in the editor let's just select it and just write down list okay great so with that we can now access the list and pass it in as an index instead so let's uncomment this code and then for the parameter instead of receiving kitchen object so let's receive an end for the kitchen object as so index and then here we convert it back so kitchen object as so we grow into the kitchen object Melissa cell then access the list inside of it and then we'll text us on the kitchen object so index so now here we can pass in the index and let's actually make some nice helper functions so we don't have to write all this code over and over again so a private return end get kitchen object so index and this one receives a kitchen object a cell and very simply just returns just goes inside the kitchen object Melissa so we grab the English inside of it and we do index of this kitchen object okay so that one converts into an index number to the opposite so return a kitchen object to sell get kitchen object so from index and receive an end for the kitchen object so index and over here we do the code that we're doing up here so just going to list and access on this and just return it okay so we have these two nice sample functions so over here let's just grab the index and pass it in and then on this one for the kitchen object itself let's use the function and grab it from this index okay so that solves that problem now we are only synchronizing the server RPC with a nice int index however here in the editor we saw as the same error this one is related to the kitchen object parent again does not know how to serialize it and to solve this one we are going to use a really useful netcode type which is a network object reference so over here instead of receiving that one let's receive a network object reference and let's name this kitchen object parent Network object reference this is how you can pass in an object reference through an RPC and then on the other side convert the reference back into the actual object if we just comment out this function call and look in the code as well as this one down here and if we have no more errors so this is now if only the RPC so we can now call this function and everything should work but of course now the question is how do we get the network object reference from this interface in order to get a network object reference really all we need is to pass in a network object then in the background to automatically convert into a reference so we need a network object from the kitchen object parent and how we do that is super simple this one is an interface so really let's just make another function this one is going to return a network object just get network object okay so that's it super simple now we just need to implement this function on all of our interfaces so for example over here on the player the player has an eye kitchen object parent so let's go down to the bottom and let's Implement our function and the player is already Network behavior and from Network Behavior we can access the network object that is attached to this network Behavior so just like this then the other place we need to implement is on the base counter so here we are on the base counter and let's implement the same function and now for this one we still haven't yet made the base counter into a network Behavior we're going to do that in a little bit but for now we don't want to worry about it so just make sure the code compounds over here and let's just return no right now we really just want to handle the player picking up objects then afterwards we'll handle the counters okay so back here on the multiplayer class now we can just access the interface and through the interface we can just get the function get the network object and yep there you go the type Network object gets automatically converted into a network object reference so that's right so this one is now valid now of course we need to get the kitchen object parent back from this reference and how we do that is super simple so we can access the network object reference and in there we have a function try get this one basically lets you get the network object that was originally sent so let's get out of type Network object for the kitchen object parent Network object so we get that and then from this one we can just do a get component of type I kitchen object parent and with that we have the kitchen object parents so then we can just run the original code just like this now here let me point out one thing perhaps you might be thinking that these variable names are way too long and again it goes back to what I mentioned in the naming rules on the single player course naming rules can really be whatever you want them to be in my case personally I prefer to have extremely descriptive variable names even if they become a bit too long I prefer that over having compact names which then might cause confusion because I don't know what variable actually contains but again this is personal preference so if you don't like the super long variable names then by all means go ahead and follow your own rules okay so over here we wrote quite a bit of code but everything should now be working we have no errors some of the parameters for the server RPC of these are valid so we pass in the so as an index and we pass in the parent as a network object then on the server side we just get the other references and we use them okay so we definitely test so here we are and up on the client let's try to pick up some cheese and you better go with that work again don't worry about the fact that it's on the floor that is because we disabled the parenting we're going to handle that later right now we just want the spawning and that did work and then if we go down here onto the client let's try to pick up some meat and if they go with that work nowhere is nothing everything worked perfectly all right awesome so here we learned how to spawn an object and synchronize it across a network however like you can see that object is still being spawned just in metal on the ground instead it should really be being held by the player so let's handle that tricky part in the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize the kitchen object parents so that the objects are actually being held by who owns them okay so here's what we have so far I have both a host as well as a client and I can interact with the container counter any update does spawn the object correctly but as you can see the object is spawned on four it is not being held by the player so let's handle that and this is actually going to be the really tricky part which is parenting the object let's go over here onto the kitchen object script and down here we have the lines that we come to the one here modifying the parents so let's uncomment these let's save and let's test again so here we are and now if I try to pick up something from the container counter and if there you go got an error right away right away the message says in valid parenting the network object is moved onto a non-network object parent and that is something you cannot do so the issue here is because when we made the game we made it so that the spawn kitchen object becomes a child of some transform in order to automatically follow it around so over here the player has in front of it an empty point so that is where the kitchen object would be placed this is an excellent approach to do in single player but in multiplayer handling object parenting becomes a lot more complex the specific issue that we can see down here is that the player itself so the player the main game object this one is indeed a network object but the empty container over here this game object this one does not have a network object so we cannot make it a direct channel of this object and beyond that netcode for game objects actually has one more limitation which is you cannot set a network object as a child of another Network object that will spawn dynamically if you have objects that are already placed in the scene like for example our counters here if you have that you can make a network object like for example a spawn cheese you can make it a Channel of one of these counters but the players they are spawned dynamically so you cannot make one of these a child of the player so basically everything that has to do with parents becomes really tricky in multiplayer the best option is really to avoid doing that altogether and really just come up with a different solution the only reason why we made it using this pattern of changing the appearance was just to make the movement simpler by making an object the Channel with another one it means it automatically moves along with the parent but if we can change the parent we can still make it just follow some object without having to modify the parent the end result won't visually be exactly the same so let's do exactly that let's make a script to phone object so let's create a brand new c-sharp script call this the follow transform and let's go ahead and attach the script to every single kitchen object so let's go inside the prefabs the kitchen object select all of them and let's attach this script so the phone will transform let's add this okay now let's open so over here we really just want to store the target transform that we want to follow so let's define a private for our transform for the Target transform then let's just make a function we can expose in order to set it so set Target transform and receive a transform for the Target transform and we just do this not Target transform equals this target transform okay so this way we can set it and then for actually moving the object for that let's go with a private void late update let's go with the late so it happens after all the updates and first of all let's do just a quick safety check so if the target transform if it is null that means we have nothing to follow so let's just return let's stop but if it isn't known let's just set this transform.position equals the target transform dot position and same thing for the rotation so rotation and rotation okay so we have a very basic script that only does it receives a Target transform and just follows it and rotates alongside it now let's go over here onto the kitchen object and first of all we need to get that component so let's define up here a field for the follow transform the phone will transform and we're going to get this let's make a product wide awake so let's see we get component of time follow transform and set this on the phone load transform okay we have our script reference and then down here instead of modifying the pairing instead of that let's go into that one and set the target transform and pass in the exact same one so this target transform okay so let's do this instead of modifying the parent all right with this let's test okay so up here on the host let's pick up something and if there go it does work so as you can see the object is indeed perfectly following it as if it were with a change parent but without actually changing the parent so that's right that works but down here the client has no idea that the host is holding something and now if I try to pick up something on the client so let's pick up a tomato down here and look at that very strange Behavior so if you see the object was indeed spawned over here on the client and on the host the client did indeed pick up that object so everything is working perfectly over here on the host but as you can see everything is on the floor right down there on the client honestly this one part confused me for quite a bit as I was making the Prototype the issue is actually over here on the function to spawn a kitchen object if you want pause the video and look at this code and try to figure out what might be the issue it's actually very obvious once you remember how multiplayer actually works always remember the big difference between server host and client and you also have to remember how the various things you do in netcode are synced here we are instantiating and then spawning a network object when you do that it gets actually spawned in the network so that gets synchronized automatically all declines will receive this brand new spawn object however down here the code for setting the parent for this one the clients will not receive this automatically so this code is only running on the server that is why the client was holding the object on the host but not on the actual client build that is because only the host actually ran this code so that means that we need to synchronize this parent data somehow for that let's go ahead and do it with a nice RPC let's go over here onto the kitchen object script and when setting the parent first we need to tell the server that this object should change parent so let's begin by making a server RPC so a private void set kitchen object parent server RPC this one is going to be marked as a server PC and again we want the client to be able to do this so as usual let's set require ownership equals false okay we have this parent RPC and now we want to pass in the kitchen object parent except of course again if you remember we cannot pass in a kitchen object parent directly this is not yet serialized so we cannot use this so let's pass it in as a reference exam like we did on the multiplayer class so we're here on the multiplier class we had this reference and then we did a try get to get it so let's see exactly this code so first let's copy the parameter and then let's paste the code to actually get the kitchen object parent okay so now we have the kitchen object parent but again this is just a server RPC meaning this is only going to run the server that is not what we want if we want all of the clients to update the parent then this code this code to actually set the pairing this one needs to run on all the clients so basically the client won't have the server and then the server tells every single client what the new parent is so let's make another one let's make a private void and for this one set kitchen object parent client RPC let's make this a client RPC and let's pass in the exact same parameters so let's pass in this and it's over here on this one that we actually run this code and then for the rest of the RPC we're actually going to run the regular set parent code so let's copy this and paste it over here okay so we've got the nice line RPC and then of course when we call the logo function we're going to call the server RPC in order to tell the server that this object should have this new parent and for this one lets you get network object okay so we have that then the server receives the server RPC and recently just broadcast it to all the client rpcs and tells every single client that this object now has a brand new parent okay so with this all the client should receive the message that the parent has changed now it says to see if the client can pick up a new object so here we are and up here on the host let's pick up some cheese and if there you go it does get synchronized okay great and then down here on the client let's try to pick up something else pick it up and if there go it does get synchronized so both of them have the exact same state all right awesome so this part is working perfectly now if I go over here on the host and I try placing this object somewhere and there you go we've got an error there is that the argument is returning null and this is actually if we follow it we can actually find where we're finding this here it is it's on this line on the kitchen object so this one goes into the parent gets the network object and apparently this one is returning null and again this is the issue that we saw a while ago so if we go on the base counter a while ago down here we had to implement this for the interface but we just made return known so this is the issue the solution is very simple let's just go ahead and make the base counter instead of moderate behavior let's make this a network behavior and then down here inside return no let's return the proper Network object okay so that's good now all we need to do is make sure to attach a network object to every single base counter so back in the editor here let's go into our prefabs onto our counters and here we have on counters and the way we made them is they are all variants of this base counter so we can just select this one and just add the network object so there you go just have this one onto the base and now all the others yep all the others now have the network object okay great so if we test like this so here we have the host and let's pick up something yep that is synchronized just as previously and now if I go and I drop it there and if there go that one also does work same thing on the client down here let's pick up some bread yep picks it up everything works perfectly now drop it and you'll ever go everything is synchronized perfectly alright great again here we have yet another excellent example of the power of writing good clean code because we center part game with some very good code by using our interface and the base counter class because of that just by making a few changes we already have a ton of the game working in multiplayer so that's great however we also actually have one slight issue here so if I try to pick up something from a container counter yep it does work all of them work however if now I go over here onto the plates counter and I try to pick it up and nope there's our error let's see where this error is actually coming from so over here kitchen object 50. and this is actually a pretty sneaky error so something in here is set as no now we already know that we added the kitchen object parent correctly so this one cannot be null so the only thing that I can possibly know is over here the final transform and the final transform is actually set up here on the awake so it seems like that should always work however the reason why this error only happens on the plate that's actually a nice clue if we go over here on the Plate Kitchen object script over here we already defined an awake in order to initialize our list so the plate has this awake and then the kitchen object also has an awake so like this we are defining two commonly separate functions so the plate is actually hiding the other awake that is why over here for the plate when interacting with the plate the plate is not going to run this so the final transform will always be known this is something that actually took me quite a bit of time as I was building the Prototype that's because Unity for some reason doesn't show you a warning for hiding functions if they are mono Behavior functions if this was a regular function it would show that warning but for some reason on the Model Behavior functions this one does not show anyway thankfully the solution is actually pretty simple let's just go over here on the kitchen object and for this way instead of private let's make it protected and let's make it virtual okay so this is your rank and over here on the Plate Kitchen object we can make this protected and then make an override now this one will override the other one but we still want to run that one so up here we can just do base dot awaken or to run that code okay so now it should work so over here I can drag you into the plate and pick it up and if there you go now it does work okay great now by the way we still have one issue where we cannot pick up an object onto the plate so if I try to grab some bread over there and try to drop it like this the plate contents are not yet being synchronized that's normal we're going to handle that later on the course for now we just care about changing the kitchen object parent and that part is indeed working perfectly so on either build I can pick up interact with the container counter to pick up something oh if it works so now this one is now picking up something so that's great however the counter interaction itself is actually not being synchronized so for example if I'm controlling the hose up here and if I go and I pick up something look what happens down there on the client I pick it up and if there you go it does spawn the object but there no animation played the animation only played locally on the actual object that was interacting with the counter again that's because the interact function this one is only local so far so let's synchronize this as well let's go over here onto the container counter and over here we're basically spawning a kitchen object and firing off an event this is what actually plays the animation now for spawning the event this one is already being synchronized so that's great all we need is really just to synchronize this part so let's basically make a function to synchronize the interact logic so let's make a private Point call it interact logic server RPC because we're going to first on the server so this one is a server PC and as usual let's make require ownership as false so that all the clients can call this so we do this so we can tell the server that this counter was interacted with and then the server needs to broadcast that message to every single client so over here let's make a private void for the interact logic client RPC and this one at the client RPC announced on this one that we do the actual local logic so we run this logic there we call the client RPC from the server and we trigger the server RPC logo okay so that's it pretty simple Let's test so he ran up on the host I'm going to pick it up and see if it's synchronized any of there go the animation does synchronize so that's great and if I go down here on the client and I try to interact and see if that one synchronizes and if there you go everything worked perfectly alright awesome so with that the container counter is now fully synchronized and with that we have quite a lot of stuff already working perfectly now these past even lectures are some of the more complex ones so if you didn't fully understand something maybe go back and re-watch it also remember to read the course page FAQ I'll keep that updated as more people ask questions and of course I'm always available answering any specific questions you have basically if you do manage to fully understand everything in these passing lectures then you already have most knowledge required to make any multiplayer game okay so with this with the container counter working everything is looking great so far next let's work on a bit of a simpler one let's synchronize the plates counter so let's do that in the next lecture hey again here's another quick intermission I hope you've already learned a ton in this course how are you handling the multiplayer is it being difficult or relatively easy do you understand how the rpcs work the difference between server and client RPC remember to follow the course page website as you follow along I'm constantly adding frequently asked questions to every lecture if you ever get stuck you can just download the project files for each lecture and compare with your own and by the way if you're listening to this let's say this is the secret come out so go ahead post a timestamp with the monkey emoji in the comments I want to see how many people get this far and if you are finding it helpful and if you can afford it then check out the optional pick course or post a super thanks okay that's it for now let's go to the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize the plates counter we want to make sure that all of the clients have the same number of plates this is a pretty simple encounter so this one is going to be a quick lecture okay so let's synchronize the plate counter so it's this one right here which spawns a plate and then the player can pick up a plate right now this logic is only working in single player all of the clients are spawning their own plates so if I pick one up over here on the host it does not synchronize down there this is not correct only the server should be spawning them and everything should be synchronized so let's do that first let's go over here onto the plates counter script and then down here we've got the update where we count on the timer and spawn the plates now first of all we're only going to run this Logic on the server so as usual let's see where it is server so if we are not the server then return and don't run this logic so like this only the server is going to spawn some planes now we need to do is tell the clients that the server has spawned something so as usual let's use some rpcs so let's go over here make a product void first of all let's make a spawn plate server or PC and then a spawn plate client RPC let's add the attributes on both them in this case this one was only going to run the server so we don't need to add the required ownership so we do this from the server RPC we call the client RPC and on the client RPC we're basically going to run our local code so just like this also by the way technically since the code up here is always only going to run the server typically we could avoid using a server RPC here but just to keep the same logic the same pattern that we've been using let's do it like this so in the regular logic we trigger a server RPC which then broadcasts a message to all the clients okay so that's it super simple this will handle synchronizing the spawning then for picking up let's do the same thing that we did on the container counter so we're here on the container counter we've got the interact and then we use a server and client RPC parent or to synchronize antenna so let's do the exact same thing let's use the exact same name so let's actually copy all this and over here on the plates let's just paste them and then we're going to fire off the event so over here and also count down the number of plates for the spawning the kitchen object that one is already synchronized so that's already great so just like this and Trigger the server FPC up here alright so that's it as you can see it's also pretty simple logic now that you understand how server PCS and coin Services work that is why I said those previous home lectures were extremely important since we already learned how to do all those things all of this suddenly becomes extremely easy okay so let's test so here are both builds and let's see if they synchronize both have one plate and a little bit you both got two plates and so on okay so the spawning of the plates that timer is indeed working so let's wait for it to reach the maximum so yeah it goes up to four plates now if I pick one up let's see if both of them count down and if they go both them did count down so just like this yep we do have all of our plates the play counter everything perfectly synchronized all right great so once again because of writing some good clean code this was super easy to implement also because we already took the time to really understand how multiple your code works and how to use rpcs because of that this is really one of the shortest lectures as you can see once you understand how the tool set Works making multiplayer games is actually super simple now we want to handle a bit of a more complex counter the trash counter so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize the trash counter this one is very important because we're going to learn how to destroy a network object okay so here on let's handle the trash counter right here this one just destroys whatever you place on it so I want to be able to pick up something like a tomato approach it interact with it and destroy the object now remember how all of the spawn objects the kitchen objects those are all Network objects so this is excellent to learn how to properly destroy if Network objects so first of all let's go over here onto the trash counter script and let's make the usual server and client RPC pair in order to run this Logic on the client so a private void interact logic let's start with a server RPC and then we're going to have another one for the client RPC okay we have both knees let's add the usual things so the server RPC and for this one let's add require ownership as false okay we have our usual pair from the server IPC we call on the client RPC and from up here we trigger the server PC and down here let's just fire off the event okay so just like this let's leave the destroy itself up here to see what that happens so it says this so here all it says and there's the host let's pick up an object go into the trash counter and trash it and if there you go it did work it disappeared over there on the client and we have no errors okay so that seems like it's working but now down here on the client let's try doing the same thing pick up something go into the trash counter and interact and nope we've got an error the area is exactly what it says which is destroying a spawn object on a non-host client is not valid so only the server can destroy objects if you want to look over here on the kitchen object the story sound function over here yep we are indeed calling destroy on this game object to actually destroy it and again the issue is that only the server can do this so basically we need to make sure that only the server runs this code and for that let's do the same thing that we did down here with the spawning let's make a function to destroy it so let's let's make a public static void destroy kitchen object and let's receive a kitchen object so we're going to destroy this one by the way here let me point out that obviously you wouldn't need to make this a static function itself for the spawn we made it static because we didn't want to require a kitchen object reference in order to spawn another kitchen object but over here we already have one so we could make this non-satic to destroy it I'm doing it just like this just to match the same pattern that we defined up here so let's do this and then let's make a function on the kitchen game multiplayer to actually destroy that object so over here on the kitchen game multiplayer and let's go down and make a function to do exactly that so a public void call it destroy kitchen object and this one receives a kitchen object this is the one that we're going to destroy then in order to make sure that destroy code only runs on the server let's make a server RPC destroy kitchen object server RPC and this one as usual is going to be marked as server IPC and we want the clients to be able to destroy objects so let's require ownership equals false okay we have our function and for this first of all we're going to need a reference to what kitchen object we're actually trying to destroy so in order to pass in that reference let's pass in a network object reference so we're here for a parameter Network object reference this is going to be the kitchen object Network object reference so you have this and then from this one we can do a try get in order to get the network object this is going to be the kitchen object Network object and then from this one we can just do get component and get the component of type kitchen object and then we have our kitchen object okay so we have the kitchen object and on this one this code is only running on the server so over here now we can indeed do our destroy sound function and up here when we got the usual function let's just trigger the one with the server RPC okay just like this let's pass in the object reference so that's that one we just need to get the network object okay so this is all great and back here on the kitchen object for destroying it let's go into the kitchen game multiplayer let's access the instance and call the destroy kitchen object function okay so just like this it looks like it works so basically this function goes into the kitchen game multiplayer and that one destroys the object only on the server however if we inspect over here the destroy sound function we are not only destroying the game object but we are also clearing the kitchen object on the parent this is something that we must do on every single client it's basically the same thing that we had up here when setting the kitchen object parent we had to make sure that we use a client RPC to broadcast it to all the clients and not just do it on the server so basically let's just split this logic into two functions so this one runs on the server and this one on only cleans so let's make up here a public void clear kitchen object on parent and we're going to just run this code so just like this so we now have the two separate functions and then back in the kitchen game multiplier script over here let's just make another one so this one is going to be a client RPC let's make a private void call it clear kitchen object on parent client RPC let's pass in the same network object reference and let's grab the kitchen object from that reference and then on this one we can call the Clear the object on the parent and this one is going to be a client RPC okay so just like this and up here before we destroy the object on the server let's just sell all of the clients all of them to unparent the subject so let's just pass in the reference just like this okay so now we have all the logic running on all of the correct places all of the clients are going to clear the parent they're on local parent and then only the server is going to actually destroy the object which in turn is automatically synchronized and all of the clients get that object destroyed so let's left this back here on the trash counter instead of going through the kitchen object and accessing the destroy sound function instead of that let's just use the other one so let's go inside kitchen object and let's use our static function in order to destroy a kitchen object and just pass in this player.kitchenobject so let's do just like this okay so this is going to handle everything on the client and the server and then we've got the Israel interact logic and we fired the event over here only on the client okay so this should do it it should clear the parent on all the clients and it should destroy the object on the server which is also then destroyed on only clients what says okay so here we are and if I'm up here on the host and I try to trash something and if there go does work no errors everything is synchronized and then down here on the client pick up something and let's try to trash it and if there you go it also works nowhere is nothing alright awesome so in order to destroy a kitchen object we really just need to run this function instead of doing it through the destroy itself directly now we can use Visual Studio to find all the references so if we right click over here and find all the references so we see all the places where we're calling destroy self and basically we're going to need to replace all of these to go through this separate function we're going to do that as we go through all of the counters in the following lectures over here let's just quickly synchronize the delivery counter because that one is so simple so here we are on delivery counter script here it just calls a function to deliver a recipe on delivery manager we already synchronized this part all that's left is really just destroying the plate object so again instead of doing this let's call the other function that goes through the server so the kitchen object destroy the kitchen object and just pass in this kitchen object so just like this okay that's it let's test okay so here we here and if as a host I try to deliver something if there go it does work no errors okay and now down here if I try on the client to deliver and if there you go it also works no errors nothing so the client can also deliver something and destroy an object and we have no problems okay great so here we added yet another very important synchronization to our multiplayer game and in doing so we also learned how to destroy Network objects now we want to synchronize the remaining counters so let's begin by synchronizing the cutting counter in the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize The Cutting counter this involves synchronizing placing the right objects then doing the alternate interact action and handling converting an uncut object onto a cut object okay so let's synchronize The Cutting counter let's try it first to see what we need to think so if I pick up some cheese and I drop it over there on the cutting counter yep there you go dropping the object that one is already being perfectly synchronized so that part works fine but then if I try to cut the cheese there you go it works in there but nothing is being synchronized so we need to do that let's go over here onto the cutting counter and really let's do the usual server client RPC pair so just like we did on the other counters this is going to be on the interact alternate so let's go down here and start running our functions so let's call this the cut object server RPC and let's make another one the cut object the client RPC let's add the client RPC attribute and the server RPC and again as always let's make it require ownership equals false so that the clients can trigger the server RPC okay so as usual from the server RPC we trigger the action on the coins and on the clients over here we run the actual regular logic so let's just copy all of this and paste it over there and from here when we cut let's just do this okay so just like this we don't have any errors so let's try it and see what happens so if you're in the host if I pick it up and I cut and if there go the cut is indeed being perfectly synchronized so that's great however we actually do have a problem if instead of the hose if I do it down here on the client so let's pick up some cheese drop it onto one down here and there you go we have an error we have the usual null reference exception let's actually swap the order so we can see it up here in the editor okay so now I have the host down here and the client up here so on the client go and drop it and there you go there's the error the no reference exception and let's see what is this line this line is throwing in non-reference exception and just by looking at this we can immediately tone which one of these is actually possible as being null and the answer is over here the get kitchen object this is the only one that can possibly be known which we're then accessing and returns no so that has our exception and the issue that we have here is very very important basically the issue is that in single player all of this code this will all run sequentially right away whereas in multiplayer some code like for example using rpcs that will not run immediately basically the issue that we have here is that we are changing the parent over here on the kitchen object that the player is holding so that makes sense but while in single player and this changes the parent right away so then the code down here this kitchen object on this counter has already been switched so when the code gets down here on the host that is not going to be known so that is correct however in multiplayer the kitchen object will only change parent when the message goes to the server and back so when the client is running this line this code modifying the kitchen object parent this one isn't going to handle immediately however even as that message is being sent through the multiplayer netcode even through that this code is going to continue executing so when it gets down here that message hasn't yet reached the server so this object that is on the player is still going to be on the player by the time we get down here this is a very very important thing you always need to be very careful with when making multiplayer games you have to remember when the functions run so on the host all of the code won't run in a certain way whereas on a client things might take a bit more time so that is something you always need to keep in mind here thankfully the solution is actually very simple we don't really need the object to change parent all we're doing down here is accessing the exact same object so we can just cache the object up here and we don't mind that it takes a little bit of time to change parent so we can just go up here to find the kitchen object kitchen object and go into the player and get the kitchen object so then we take that one and we modify the parent and then down here we use the exact same reference just like this this way the client code is not waiting not expecting the server code to run immediately this way it will always work okay so let's test so here on let's start a host down here and a client up here okay so now on the client if I go pick it up and I drop it and there you go it does work no errors okay great now if I cut on the client if there you go that action is also already synchronized same thing on the host if I go up there and I cut that object yep there you go everything works perfectly alright awesome so everything is working great so far however if I finish cutting on either of these and there you go we have an error this is showing an issue with the kitchen object parent but in reality this is really because when we finish cutting we try destroying the previous object but we are still using the old method which no longer clears the parent so this is really related to destruction not really parenting the solution is the same thing that we've already done so many times so let's just go down to where we are destroying the object so it's over here we are calling the story itself instead let's go through the kitchen object and destroy the kitchen object and pass in this kitchen object okay so now the structure should be working let's see so here we are and I'm going to test just with the hose here no clients so just with one hose let's go there pick it up go there drop it and let's cut one two and three times and if there you go everything seems to be working perfectly however now if I test with the host appear and a client down here and on the host let's go there and cut it one two there you go everything synchronized cut one more and there you go we have an error so again always remember that when you make any modifications in multiplayer you need to verify that it works on the host and on the client so you always need to verify every possible use case Okay so let's see exactly what this error is this one is a much more sneaky issue note how in this code here for running the server and the client RPC this one is a client RPC meaning this code is going to run on every single client so all the clients are going to run all of this code meaning that all of the clients are going to increase their own cutting process and all of the clients are going to run the sieve so all of the clients are going to basically try to cut the object as many times as we have clients that obviously creates a conflict when it comes over here to destroying and spawning objects because these things are only going to happen on the server but we're going to run it as many times as we have clients so that is why we just one Host this isn't actually causing problems but as soon as we have two clients and two clients are going to run this code meaning that both of them will attempt to destroy the same object and then spawn a new object so we have duplicate logic that is not good the solution here is basically for the code that we have down here we really only want to run this once regardless of how many clients we have so basically let's split this cutting process testing into another function and make it just a server RPC so let's go down here make a private Point call it test cutting progress done server RPC let's make this a server RPC with required ownership as phones and then over here we're actually going to run just this logic so we also need the cutting recipe so like this and then for calling this function let's just go up here to where we're calling the cut object server RPC and then let's call the other RPC okay so that way now we know that this function this code is only going to execute on the server so it is no longer dependent on how many clients we have so let's test so over here up here I've got the host so if I go and I cut so one two and three and if there you go it does work it cut perfectly and now let's go down here and try it out on the client so let's pick it up go down there drop it and let's cut once two three times and yep it also worked so it seems like everything is working however now let's say on the client I'm going to reuse the cutting counter up there so let's pick this one up let's drop another one paste there and now if I cut and there you go look at that issue the client cut just once over there the progress is correct but on the server and look how the process is already maximized and the object was immediately cut basically the issue is that the host is now resetting the progress if we only look back in our code here when we're placing an object on the counter we're going to run this code so first of all unfortunately the parent this is already going to be automatically synchronized but then down here setting the cuttering progress to zero this one is not automatically synchronized so as usual we have two options we could just make the same network variable or let's just keep using the usual server client RPC pair so let's go down here to make that function a private void call it interactlogic Place object on counter this is a server RPC so it's a server RPC would require ownership as phones then let's make the corresponding client RPC so let's go for the client RPC and the exact same name just end with client RPC okay then from this one we run the other one the client RPC and now on the client RPC we're going to run the regular logic again the parent that one is already automatically synchronized so let's just cut this and paste it down here and for the server RPC let's just run it all the way up here okay so like this so we run the server RPC that one then runs this code on all the clients and over here we actually have an issue with the kitchen object reference so we could pass it in but actually we're really not going to need this at all we're using it down here to set the cutting progress Max but the progress normalized only is going to be zero because getting progress is zero so instead let's just not do that and just pass in zero f okay that should do it let's test okay so up here on the host let's drop it cut one two three okay great now on the client pick it up go there drop it and cut it and there you go the progress is synchronized one two three and there you go it does cut perfectly all right awesome with this we no longer have any errors and our cutting counter logic is all fully synchronized like I mentioned one alternative here would be to synchronize The Cutting process using a network variable and that's exactly what we're going to learn about with the stove counter in the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize the stove counter this is the more complex counter but thanks to what we have already learned this isn't actually going to be too difficult we need to synchronize the timer the object conversion from uncooked to cook to burnt and handle the various States okay so let's handle the self counter we can start off with a quick test so I'm going to create a host down here and a client over here on the editor and now on the client if I go ahead and I put something on stove so let's drop it and there you go we have an error right away here it is on this stove counter line so let's see it and the issue is we're only the exact same issue that we saw previously which is the host is going to run this code sequentially but on the client setting the parent is going to take quite a bit of time so when it gets on here this kitchen object hasn't yet switched parents so let's do the exact same solution let's just cache the kitchen object so kitchen object and we grab the player get the kitchen object then we use this one both in here as well as in here okay so that won't fix that issue then we need all of the clients to know what Frank recipe was selected so let's make the usual server client RPC pair for our interact logic so let's go down here and make those functions sorry private void interact logic Place object on counter server RPC and the same thing for the client RPC so just change this let's add the usual client RPC attribute and the server RPC as well as required ownership as false okay our standard functions then on the server RPC we call the client and up here when we are dropping something so in here we're going to trigger our server IPC okay so let's copy this little code cut it from here let's go down to the connect RPC and paste it okay now in order for this to work we need some reference to the kitchen object or we can also grab the frame recipe just by using the kitchen object so so basically those are the three options we have we could add a parameter here and synchronize directly the Frameworks PSO we can synchronize just the kitchen object or the kitchen object that so all of those options are valid let's go with the kitchen object so method since we already have these functions on the multiplier class to convert it into an index so here on the kitchen game multiplayer we already made these functions to convert an so into an index let's just make them public so we can count from there so both of these make them public okay so now we can hear for our rpcs let's receive an INT for the kitchen object so index we have one here and one down here and then we get there okay so now up here when we are calling the server RPC let's just go inside the kitchen game multiplayer let's access the instance and get the kitchen object that's so index and now we pass in this kitchen object dot get kitchen object the cell okay so that way we get the index and then down here really just need to convert the index back into the kitchen object the cell so the kitchen object as so we're going to go into the kitchen game multiplayer the incense get the kitchen object that so from the index and pass in the index so we have this and then we can grab the frying or spso based on this okay great no more errors with this we are now going to have the same frame recipe so synchronized across all of the clients so let's test it out and see if the client can now place an object on stove okay so let's put the host on here the client up here and on the client let's pick up some meat and cook it and there you go it did work no errors both of them are being synchronized and if we wait until it gets cooked and then we've got an error so this is actually going to be the same issue that we already saw previously which is destroying the object however before we actually love that issue and let's solve another issue right now all of the clients they're all running their own timer on the stove we really don't want that we just want one source of Truth so only the server should be handling the stove timer and when we have that then we're going to need to synchronize the same timer to all the clients so technically like we've been doing we could use a client RPC fire it on every single update in order to update the clients that would work but that would be quite wasteful so instead let's use the other method for synchronizing data let's use a network variable again I cover the bottom all in detail in my dedicated net code for game objects video go re-watch that section to see everything that Network variables can do so over here if we scroll down on the frame timer instead of using a simple float let's use a network variable of type float then for natural variables we need to initialize them so let's do new network variable and start off on 0f for the other parameters we can leave them all as defaults so everyone can read and only the server can write to it so now what we need is to fix all of these errors and first of all before the only with any actual errors over here for the update we only want to run this on the server so it said if not is server if this is running not on the server let's just return okay so this logic is only going to run on the server then for increasing the value we want to increase by the same amount the only difference is when working with a network variable we increase it by dot value okay then for the on progress changed event if we're leaving like this and the event is really only going to be fired on the server and not on all the clients so you need to make sure that all the clients fire off this event whenever the frying timer changes now thankfully the network variable itself this one also fires off an event when variable changes in any way so let's listen to that and usually for listening to an event you would do it on awake or on start but remember we're working in multiplayer so when listening to a network variable event you really shouldn't listen to it on a on network spawn like we already saw this is kind of like an awake but for Network objects so let's do a public override and let's override the void on network spawn so let's override this one and over here we can listen to it so let's go into the frying timer and it's called the on Valley changed and now this one is actually just a delegate and not an actual event so the home phone Visual Studio shortcut where we hit Tab and automatically writes that doesn't work here so we need to manually write it so let's just do a private void call it frying timer then underscore on value change so pretty much the same naming format for the parameters going to have a float for the previous value and another float for the new value so we make this function and we assign it to our event okay great and over here we can actually run the on progress change event so let's fire off this one just like this then instead of using the front timer we use the frying timer dot value because again all of the clients can read this network variable however over here we actually still have one potential problem that problem is going to be if the frying timer changes in any way like it gets initialized before the frying recipe associate if that happens this one is going to fire off a non-reference exception we don't want that so let's just add a simple node check so let's define a float for the frying timer Max and basically we just check if the frying or spso if this one is not known if so then let's use the frying recipe so dot frying timer Max but if it is then let's use one f one F basically it's a default since over here we're dividing by it if you divide anything by one you always get that something also by the way if you're not familiar with this code this is called the if shorthand so what we're doing here is pretty much the exact same thing as this so if frying recipe so if it is not null if so then the frying timer Max becomes a frying recipe so dot frying timer Max and if not the frying timer Max becomes 1f so this line up here is doing the exact same code as this down here so just a much more simpler way of doing a simple if so let's do that just like this okay great now let's continue our update logic let's fix all these errors so again on the frying timer we need to access the value okay then here we have the problem with destruction but again we're going to handle that in a little bit for now let's just fix the rest of the errors so let's scroll down and find them okay so down here this one is dot value and same thing over here for resetting the timer this one dot value but again here we are working inside a client RPC and the network variable only the server can write to it so if we do it just like this we're going to have an error because the client cannot write to this variable so let's just make sure to do this on the server RPC instead then also for the on-preg exchange this one is automatically going to be fired whenever we modify the frame timer so we can actually also remove it from here okay so no more errors so everything should be working so let's test so up here on the client let's pick it up and drop it and there you go everything is nice and synchronized okay so great so now let's fix this error when destroying the cooked object so as usual in the fix is super simple example like we've already done so let's go down into the update okay so here we've got the frying and we are calling this right self so instead of that one let's use the other function so kitchen object let's destroy this kitchen object so this one down here let's destroy this so that is going to handle that let's see where else we're destroying it's also down here on the Fright State going from fried into burned let's also call the same function okay so it says so here we go let's pick up some meat and cook it and there you go the timer is synchronizing let's wait a bit and see if it actually cooks and yep there you go it did work all right the object was indeed replaced okay so that's great except we can already see on the timer not exactly great basically what happened is that the burn State isn't really synchronizing but at least the object transformation did work so that part is great so we have the correct object just not yet synchronizing the actual States so for synchronizing the burn state we really need to synchronize two things first of all is the burning timer just like we did the frying timer and then we're also going to need to synchronize the state itself so first let's in the burning timer so exactly like the frying timer so if here a network variable of type float and let's start off sorry off on zero f okay there it is then down here let's listen to the same change event so on the burning timer let's listen to the unfail change we're going to make another function so burning timer on value change let's just copy this and just replace all the names so this is the burning timer and for here we have the burning time Max and we're going to access the burning recipe so and from the burning recipe so get the burning timer Max so we have that and on the progress normalized your strength timer replaces with burning timer and up here I actually made a mistake that I only noticed just now we made this one to avoid any null checks over here with the frame spso but then I forgot to use this one so let's actually remember to use that one and down here same thing let's use this one okay that's good again make sure all of the references have been replaced so you can do a quick search for frying and make sure there are no frying references down here okay great now let's continue solving of the errors so let's go down for the burning timer we need to modify the value the progress change this one is going to happen automatically so move it first burning timer this one is the value okay and finally up here when modifying also Modified by the valid okay we have no more errors like this the client will indeed synchronize the burning timer but it will not synchronize the state now since we used an enum for our state we can easily make this a network variable enums are serializable so you can just go up here and make this a network variable of type State and let's initialize it over here instead of doing it on start so let's initialize on state DOT idle so let's do this instead of doing it over here on sart and now let's fix some of the usual bugs so instead of doing a switch on safe switch on state DOT value then for modifying the state so state DOT value for firing Deon say change event let's do the exact same thing let's go up here onto the state and the on value change let's see one so State on Valley change let's make this function so down here on a private void State on valid change so we've got a state for the previous state and a state for the new state so you have this in over here on this one let's fire off the unlockable event so let's cut this and paste it in there so we have this state DOT value okay so that is going to fire off all the events locally so that's great let's keep solving all the errors so over here on this logic is already working great all right now working on fried let's modify the state.value and we don't need to modify the state.changed and over here for the promise change we're doing this basically just to hide the progress bar it gets hidden automatically if the progress normalizes zero f but again over here this code is only going to run the server so we want to run this on every client so on sectionally put this on the on say changed event but only when the state is either burned or idle so let's go up here onto this one Let's do an if if the state DOT value if this one is State DOT burned or state DOT value if we are on the state DOT idle see if you are on either of these states then let's fire off the progress normalize zero just so we hide the bar okay great now let's fix the remaining errors so down here on the interact when we are resetting the state let's say dot value back into idle and let's get rid of the events since those are already happening then over here same thing state DOT idle and get rid of this and down here on our server inclinator PCS modify the state so state DOT value and then say change get rid of this except of course always remember that Network variable this one can only be modified on the server whereas here we're working inside a client RPC so we need to make sure to do this up here just like that so by now we can probably just rename this function since all this is doing is setting the frame rest BSO Sun sectionally rename this so let's use the visual studio shortcut just right click and let's go ahead and rename this let's call this set frying recipe so client RPC okay so that won't set the frame recipe so and then we're also going to need the function just like this for setting the burning rest PSO so let me just copy this and do the exact same thing so this one's going to set the burning rest vso so get burning rest BSO with input and this is the burning recipe so also by the way one note several people in commented on my single player course and yes you could refactor this code to have just a single unscriptable object to Define both the frying and the burning you could definitely do that that is an equally valid option I just went with this pattern to keep the states a bit more separated so you could potentially expand upon this with more States and more custom Logic for each state okay so now let's just call the function to set the burning rest BSO also down here let's fix this last remaining error okay so for setting the burning rest BSL that one is going to be up here so the update the frying we're going to get the burning recipe so but just like this it will only happen on the server we want it to happen on every single client so let's go ahead call this we go into the kitchen game multiplayer the instance let's get the kitchen object there so index and let's press in this kitchen object this kitchen object is so okay so just like this we've got no more errors so all of this logic should now be working so let's test so up here on the host let's cook something and there you go it is being synchronized okay great let's wait for the timer to reach the end and yep both objects were synchronized as well as that and there you go once it gets there it also spawns the burning timer warning and yeah both of them get burned and both them stop okay so with that everything works perfectly awesome now we just have one error if we go down here on the client and I try to pick up something there you go got an error invalid operation basically it's telling us that the client is not allowed to ride to a natural variable if you look in the code it's over here on the interact function when we go down when there's a kitchen object here and the player tries to pick it up so this issue right here we have the client trying to set the state value again only the server can do this so let's go ahead and do this through a server RPC so a private void set State idle server RPC make this a server RPC with required ownership as false and over here we just set the state DOT value just like this okay that's it super simple change now let's test so down here on the client let's go ahead pick up some meat drop it cook it and there you go it is working let's wait for it to cook a little bit and there you go it's cooked now pick it up and there you go it works no errors same thing up here on the host pick it up drop it everything works perfectly wait for it to cook for a little bit and there you go it's almost burned there you go now if I pick it up and if there you go it does work no errors nothing anywhere all right so with that we have essentially all of our counters all of them if only working of the multiplayer state for all of them all of that is being perfectly synchronized the interactions work perfectly except for one thing which is adding an ingredient onto the plate so let's handle that in the next lecture hey again quick intermission you're past the halfway point so congratulations looking at my regular corsets it seems about 80 of people give up by this point so great job on sticking with it and actually if you are following this course I'm assuming that you've also completed the single player course so really double congratulations I really hope these two courses have humped you out a lot in your Game Dev Journey now my question is are you finding this course to be more difficult than the single player or just about the same remember to post in the comments if you need extra clarification on anything and I'll do my best answer also check out the website to see what questions others best and of course remember this is your Learning Journey you're not competing with anyone but yourself so take your time re-watch some lectures if you need to just focus on learning okay let's go to the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize the logic to add ingredients onto the plate okay so right now we already have quite a lot of the game logic working in multiplayer I can pick up items and it's synchronize I can drop them synchronize I can cut some objects I can cook some meat everything is working great the one big thing still missing is picking up ingredients onto a plate if I go ahead and I pick up a plate and then try to pick up some cheese and yep it didn't really work on the host it looks like it works but down here nope there's no synchronization so this client does not know that cheese was added to that plate and if I try doing it down here on the client so try to pick it up and there you go the client does itself get an error okay so let's fix this for handling that logic it's on the various counters so let's go first over here onto the clear counter let's go down to where we are seeing if it is a plate so if the player is holding a plate then it's going to call this function to try to add an ingredient so let's see this function this one goes over here does a bunch of validation and then adds the kitchen object so onto the enlist on the plate so we really just need to synchronize this and as usual we have our two options one option would be to make the list itself make it a natural variable or alternatively there is actually a networking list that would work we would need to make the kitchen object Association which we could do since we already handled the index functions so that wouldn't be one option but perhaps another similar option is simply to use the usual server client RPC combo so let's do exactly that let's make those two functions so let's make a private void call it add ingredient server RPC and we're going to have another one for the client RPC let's add the attribute so call enter PC and up here the server RPC and as usual we want the clients to be able to call this okay then up here when we have our interaction let's trigger the server RPC and down here on the planet RPC we do this and pass it into that okay so that's our simple logic now obviously down here we need a reference to the kitchen object so so as usual let's receive an end for the kitchen object so index let's also receive it on the client RPC over here we pass it in then down here let's go into the kitchen game multiplayer the instance and get the kitchen object that so from the index and let's grab it from this index and this is going to be our kitchen object so kitchen object so and you haven't liked this the rest of this code is indeed working so now up here let's just grab the index go into the kitchen game multiplier the incense and get the kitchen object is so index of this kitchen object itself alright so that's it all this is pretty simple now back here in the clear counter so basically we already handled the synchronization of the try and ingredient so the next thing is just over here the story self we need to use the other function so let's just replace this so going to Kitchen object and call destroy a kitchen object and let's pass in this kitchen object okay so that's it and same thing down here let's also replace this function and destroy this kitchen object okay so just like this some of the logic should work so let's test so first let's test up here on the host let's pick up some bread and drop it on equal counter okay now let's pick up a plate and try to pick up the bread and if they go it did work it picked up the bread and the client down there does see that this host is carrying the brand okay great now let's do the same thing on the client so down here in the client pick up some bread drop it on there pick up a plate go and grab it and there you go it does work and both of them are synchronized okay great now let's do the opposite so let's drop the bread in there let's pick up a plate drop it in there pick up some bread drop it on the plate any other go it does work and same thing over here on the client pick up some bread drop it pick up a plate and let's go ahead pick up the bread any of there you go everything does work all right awesome so once again because the power of writing good clean code we didn't really need to modify many things we really just modified one single function and everything already works perfectly now really all we need to do is just apply the same logic to every single counter so let's go here onto the cutting counter and we have our interact function okay we have the usual interaction and over here we've got the plate logic for this one we already handled the triangle green so that one's already going to be synchronized so really all we need is just going to Kitchen object and use the other destroy kitchen object method so let's just use this one like this and yep that's it nothing else we need to change next is over here on the stove counter so again let's go down into our interact function and let's find where the player has a plate and really the same thing the adding the ingredients that's already synchronized so let's just replace the kitchen object dot destroy kitchen object just replace this one with that one and then over here we're also sending the state so this one is going to give the same error that we saw previously the client cannot set the state so that is why one year we made the server RPC so it just also replaces like this okay so that should really do it these are the only three counters where the player can pick up something onto a plate so everything else should already be working let's test so up here on the host let's cook some meat let's also cut some cheese so both counters now pick it up let's pick up the cheese and you better go it does work it will synchronize pick up the meat and yep it also works okay great and then down here on the client let's do the same thing so cut some cheese it works cook some meat it does work pick up the cheese and yep it does work now pick up the meat and yep it also works both of them are perfectly synchronized then we can even make it delivery so let's pick up some bread delivery over here and yep there you go it does work perfectly all right awesome so with this the plates are fully working pretty much everything is perfectly synchronized next we want to sort something pretty basic handling some player collisions so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to hand on player collisions okay so a lot of the games already working great I can cook some meat cut some cheese and so on so everything works perfectly however one thing we don't have are some player collisions so right now the players can just face through one another now this is actually a design question for some co-op games they usually have no collisions at all but some of them do have them and for this game I think either approach works if you want to make it more casual and easier to play then no collisions works fine but if you want to make the game a bit more challenging a bit more rage inducing in a good way then adding collisions is a simple way to do that that allows you to be more complex we Journal level design by making some small levels where for example one player can only go through one tiny corner so here on let's add that then it's up to you if you want to keep it or remove it now thankfully due to the way we built our game this is actually going to be super simple so this is going to be yet another quick lecture over here on the player script if we go down into our handle movement function so let's go down to this function so here it is for this one we are already testing four collisions we're doing a capsule cast to see if we can collide with something see if we can move or not so this code is already working but actually let's first refactor this code to be a bit more adaptable I saw some people trying to expand upon the single player game by adding some trigger colliders to do some external logic and like this using this capsule cast this cast won't hit every single home either so that means of the counters as well as any other colliders that you probably don't want to hit so to solve that let's Usain layer mask to make sure we only Collide against things we want to collide with suddenly our mask is going to be exactly like we did appear on the handle interactions we made it in layer mask just to be able to hit some counters so let's do the exact same thing down here let's look at all the versions of the capsule cast to see which one we can use so let's use this one down here version number four which is exactly the same so has the same parameters and at the end we have the layer mask so at the end we can just add and we can just reuse the counters layer mask so let's do that and this way this capsule cast will only hit things on the counters layer let's make sure to apply it here as well as these two other caps on casts so on this one and also the one down here okay so let's do a quick test just to make sure that nothing really changed so here I am I can move around and yep it is in the testing for collisions okay so far so good except now if we wanted we could add some things so let's say I would add a cube this one has a boxed on either I don't want any visuals so let's say this was just a trigger collider so I wanted to place it somewhere in here as long as this one is not on the counter's layer as long as it isn't then over here on the game I can move around and yep there you go there's no issues I can go through that invisible Cube so this allows you to expand upon the game in order to add some more logic based on colliders okay great so back to our original goal let's add some player collisions right now this is only testing against counters and only we really need to make this work is also test against players but for the interaction up here we still only want this one to hit just the counters so real let's just make two layer masks so here we have the counter's layer mask and let's go with another one and for this one let's go with a more generic name so let's say collisions layer mask okay so we have this we're going to set this in the other term a little bit let's just go down here and really just replace it with this one so replace it on that one and over here on this one and then down on this one okay great that's it there's nothing else we need to change in the code here and now if we go in the editor and we select the employer prefab and even down here we have the Collision Slayer mask so let's make sure to include the counters and now we also want to include the players so let's go into our layer let's add a brand new layer let's call it the players layer then over here on the employer game object let's put this one on the player's layer and for this case let's not apply it to all channels let's leave the children on the similar they are so let's apply to this object only okay so this one is on the players and on the collisions layer Max let's just include them okay that's it now really all we need is just a physics shape and we can use whatever shape we want since we made the movement work with the colliders on the counters which are really boxing letters over here let's use the same thing let's also use a box collector let's actually go inside the player prefab so we can scale it and now here just a quick tip usually for physics and letters you want to make them a bit smaller than the visual usually that makes for a better experience for the players so up here this one is a bit too big so let's make it a bit smaller so on the X let's put it on 0.7 on the Y we can leave with one and Z of also 0.7 so it's a bit smaller than the actual visual now let's also lift it up by half of the height so let's put it up 1.5 so there you go it is exactly like that by the way important make sure that the collider essentially touching the zero on the Y so pure don't lift it up by more than half the height that is because at the bottom that is where we're finding the cast on the player if you lift it up by too much it might not hit it depending on the size you use okay so that's really it if we test it just like this let's just exit save the prefab and let's test so here I have two players and moving around it still doesn't go through the counters okay great now if I go into the player and there you go now it no longer goes through the players all right so that's great it works over here on the host and down here on the client same thing it also does not go through okay awesome now one more minor thing for the Collision detection for the player shape we used a caption now in most cases this is actually a good shape for the player but due to how we handle the Collision detection here how we handle that code for checking the X and Y in order to make it easily slide around this method isn't it great but it works best on straight colliders meaning that if I try to hit the player on the corner like this there you go and look at that the player is stuck I try to move straight down or straight to the right and nope it does not work basically that's because the caption collider that one has a round Edge so if we hit perfectly on the corner based on the code that we have here it will not slide around it will just be stuck some people mention this in the single player course because they made the map different from mine In My Map There's never an issue because there are never any corners but if you do have corners then you have swapping it out makes sense so one option would be we can modify the Collision detection code to work better against some Corners we could use the Collision normal to move or something like that or perhaps a similar approach which is refactor the code to instead of using a capsule cast to use a boxes that way we don't have any round corners so back in the pointer code instead of using a Capstone cast let's use a boxcast then just need to modify the parameters let's use this one version six so first parameter is the center so let's use transform the opposition okay great then the half extends for this one let's use Vector 3.1 this is just a shorthand for writing one one one so let's do this multiply it by the player radius that way we have the box has size so next we have Direction so that is going to be the move there then we have the quaternion this is the rotation for the Box cast we don't want any rotation so let's just use quaternion.identity this essential means no rotation then we use the move distance and the layer mask collisions okay that's great so this is exactly the same thing so let's use the exact same parameters down here so we use a boxcast let's use the same version version six so we have that then for this one we have the vector 3.1 times the play radius then we move the ear x then we have quaternion.identity and then we have the other two okay great and same thing down here also a boxcast then replace the 0.2 with this one then we have the move there and again quaternion identity just like this again make sure you don't make any mistakes on the parameters I saw a bunch of questions in the same employer course because a bunch of people got confused over here would move to your ex and move to your Z so make sure you don't make any mistakes so that's it let's test this okay so here we are and if I touch a player from a corner and there you go it no longer gets stuck so if I go straight into a corner now the code does behave the same as we have up here on the corners so it goes in and it slides around either up down left or right all right awesome okay so that's it with this everything already works perfectly just one thing which is the fact that when they spawn they will spawn the exact same position so let's just make a minor change to make them spawn on different positions this is also super simple over here on the player script let's go down into our on network spawn function and over here to know the player name we can just access the owner client ID we can basically use this as an index in order to access a list to get the position so let's remove that just so it compiles so let's go up here make another serialized field a private let's make it a list of vector three and come with the spawn position list then back here in the editor let's select the player and on the player script let's put in four elements so for positions we're going to have four players for the first one minus two zero zero then plus two zero zero then minus two zero and minus two and plus two zero minus zero so we have four positions and over here it's pretty simple so we just go we just set the transform dot position and we go into the spawn position list and access it on the index of the owner client ID and this one is a yo long not an end so we can just cast it down to an end okay that really should do it so let's test so here connect as the host and yep it's on that position down here on the client and if there go it is on that position all right great now I should point out that this code actually causes an error if a player disconnects another one connects that is because the owner client ID this one is not really sequential but don't worry about that for now we're going to refactor this code later on when we handle the lobby and the character selection okay so here we have our perfect conditions between all of our players again like I said this is a design decision so it's up to you whether you want to keep it or disable it you would just go into that layer mask and either include or not include the players so that's it and with that we have pretty much our game commonly synchronized the one thing we still don't have synchronized is the game state so the countdown starting to play game over and so on so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize the game state so that's the waiting game start game timer and game over okay so we already have quite a lot synchronized but one of the main things that is not synchronized is the game state in the beginning of this course we skipped the states just to make testing easier so let's get those back now let's go over here onto the kitchen game manager and let's remove the auto start code this debug trigger that we added quite a while ago so let's get rid of this and for the countdown timer let's reset this one back into 3F and that's it nothing else okay so let's test okay so it starts off and yep it is indeed showing the controls and as I interact if there you go it starts the countdown okay so it's back to normal except obviously now this one is actually playing the game where this one down here is still staring at the controls we want to synchronize these two Saints basically we want to start off by showing all of the players the controls window then as each player presses the interact action instead of going to the countdown on that player instead of that we want to go to another state waiting for all the players to be ready and then when and all the players are ready then we do start the countdown so let's do that over here in the kitchen game manager basically we need another state for when the player is ready and waiting for the rest so one option could be to make another state here for waiting for the players to be running however actually in a little bit we're going to synchronize this state across all of the clients in order to synchronize the countdown the game playing and so on so since we're going to synchronize the same state across all the clients we cannot have one that is different on a perkaline basis so instead of adding a brand new state right here let's just make a simple Boolean so a private ball let's call it is local player ready so we have this and then down here when we have the interact action instead of going straight to countdown start instead of this one what you said is local Point ready into true okay so now we want to hide the tutorial when this player is running so for that let's basically fire off an event and then expose this Boolean so first of all let's expose this bullion let's go down here and make a public boom is local player ready and we just returned the islow complete ready okay so we returned this and then up here let's make an event so a public event event handler let's call it on local player ready changed and then down here when we have our input over here let's invoke this event okay so we have this event now let's go over here onto the Eternal UI script and previously we were listening on the state change and we were only hiding the controls when the countdown was active now we don't want this one so let's go into the kitchen game manager instance and this time see on local Ready Player change so let's just rename this to the kitchen game manager okay we have this function and then over here if let's go into the kitchen game manager the instance and let's test if the unlockable player is ready if so then let's hide this and we know we'll do anything on the state changed okay yep just like this and now by the way some of you might be thinking if we have this event why do we need to test for the bullying couldn't we just hide it when we get the event regardless of any bullying and yet that would indeed work the only reason I did it this way is just in case you want to add the ability for the player to unwrite themselves in this case I made it stay stuck and ready but you could easily modify this to let the player go back by combining the event in the Boolean you can easily add that feature okay so with this the tutorial UI should hide now we just need some visual to tell the player that they are waiting for the others so back in the editor let's go inside the canvas and let's start off by duplicating the external UI so let's duplicate this and let's zoom in the camera put it into D and go in there okay for this one let's call this the waiting for other players UI and let's put it on the same sorting order so just under the tutorial UI okay like that and over here we basically just want some text so let's just keep the same background and get rid of all these objects and instead let's create a new UI text and for the text let's say waiting for players let's put it in bond let's put that one put it on overflow down the center let's put it in black and lift it up a little bit okay so very simple window now let's make this quick to run this so with the exact same name so let's go into our UI folder and let's create the Brandy c-sharp script waiting for players UI then on the game object let's not forget to get rid of the own Eternal UI instead let's add this one so waiting for other players UI and let's open this script and over here let's begin by making the usual show and height functions so private void show and then a private Droid hide and over here game objects and active into phones so the same thing we've already done so many times okay so we have this now let's listen to the unlock on play Red event so let's make a private start go into the kitchen game manager and let's listen to the on local Ready Player change let's just rename this to give it a proper name okay so we have this one then let's do the same thing so the instance is the local play ready if so then let's show okay so that handles the showing which by the way over here on start we listen to the event then we hide it okay so it will start off hidden by default and then show when the player is ready then we need to know when to hide it and that is going to be when the countdown actually starts so let's also go into the kitchen game manager instance and let's subscribe to the on stay changed event so let's go kitchen game manager okay so we have this event so when the state changes let's test if the instance if the event is on the countdown to start active so if the countdown is active then let's hide this window okay so that's it pretty simple let's do a quick test so here we are and both of them are looking at the controls now press interact and there you go instead of starting the countdown now it is waiting for players same thing down here interact and waiting for players okay so far so good now we basically just need to check if all the player States if all of them are ready in order to know when to start the game now there are actually many ways we can do this but recently we just need to synchronize a simple Boolean to know when a player is ready the only tricky part about this is it depends on how you want to handle the number of players so do you want the game to forcefully only work with 4 players or maybe two or make it work with any number that's another design question that will impact what data type you use so over here and let's make it work with any player mount back in the kitchen game manager script over here let's use a dictionary that way we can support any number of players and also the reason for using a dictionary instead of a list is because the player calling Teddy is not necessarily sequential for example if one player connects and then disconnects it will not reuse that ID so if in the end you end up with four players connected it is not guaranteed they won't have ID 0 through 3. so because of that a dictionary using a client ID for the key that one is a much better approach than using a network list okay so let's build our dictionary so a private a dictionary for the key and let's use Yong long which is the time for the client IDs and for them let's use a simple Boolean so let's call this one the player ready dictionary okay so we have this and over here on the Wake let's initialize our dictionary so by default all of the keys with all the possible client IDs they're all going to be unset then down here when we have the interact action when we set this player to ready over here let's tell the server that this player is ready so for that as usual let's make a server IPC so a private void let's call it set player ready server RPC and as usual mark this as a server RPC with require ownership as phones okay and now in order for the server RPC to work we need to make sure to mark this one not as a mono Behavior but as a network Behavior okay great so we have our server IPC we just need to also go back here in the editor let's select the kitchen game manager and yep let's set the network object component okay great so now here on this function basically the server needs to know which player is ready so technically up here when we call this function to set its player as ready when we call this function we could pass in the owner client ID this is going to contain the client ID of the player that set the ready so this could work but on the empty docs themselves they don't encourage us the reason is because technically a hacker could fake their client ID and possibly break everything now in this simple Co-op game we're really not worried about hackers but still let's do it the proper way so instead of having the clients and its own owner client ID instead of that let's go down here into the server RPC and let's add a parameter of type server RPC params this is a built-in type part of Neko for game objects so let's receive this one as a printer and let's just default it meaning that up here we don't need to pass in anything it gets defaulted then now here when we're on the server side we can access the server RPC params and inside we've got a receive and Ascend so in this case the server is receiving the server PC so let's go inside the receive and over here we have the sender client ID this is going to be the ID of who sent this server RPC we can do a quick unlock just to verify so let's see we debug the unlock on This Server client ID so let's see okay so up here on the host if I press a button if there go the host sent the sender client ID which is zero and now down here if I interact that one should say one which should be default client ID for this one so interact and there you go got one okay great so with this we know which player set already now to sort that that is really super simple let's just go inside our player ready dictionary and let's access it on this key the key of this sender client ID and let you set this to true so this will set the play ready for this length I need then we just need a basic Loop to check if they are already so let's do a four inch to cycle through all the clients so you long for the client ID and let's do a for each inside the network manager let's go inside the Singleton and let's cycle through the connected client IDs so this won't go through every single client ID then over here let's do a basic test to see if this length ID is not ready so if and there are two ways that it can be not ready so it can either have phones on that key or you can simply not have that key at all so let's go into the playwritten dictionary and let's test contains the key of this client ID so if it does not contain that key then this one is unready or it does contain that key but that key is false so on the client ID is false so if it is like this then this player is not ready so to check if they are already up here and let's first Define a Boolean let's say all clients ready and let's defaulted to true and over here if just one of them is not ready then we set this one to false and let's break out of the cycle okay so then down here now we know if all the coins are ready so let's do a debug the homework just see this so all clients ready and let's print the alt lines ready next one over here I forgot the nut so if it does not contain this key or this one is not ready then this one is not ready okay so with this one says okay so here we are with the host and the client now from the hostess I set it as ready and if there go online ready is phones because only the host is ready but now down here if I already on this one and if they go all coins are indeed ready alright awesome so with this all that's left is really to start the countdown and for doing that we have two options we can use a client RPC to tell all the clients to go to the next state that's one option however that wouldn't be very good basically we would end up with each client having their own local state technically that could work but I think it makes more sense for the say to be synchronized just once for the home game so instead of synchronizing both the state as well as the timers instead of doing that through client rpcs I think it makes more sense to use Network variables so let's do just that first let's go here on the state let's make this a network variable and and because state is an enum we can just make a dragon like this so let's make a new state and for the default instead of defaulting it down here on the way let's see if under appears so default on waiting to start okay we do that instead okay now let's fix the remaining errors so over here when we have the input let's get the state.value okay and then down here on the update for this update this logic is only going to run the server so it says if not is server if this one is running not on the server let's return so we don't want to do anything outside the server then we do a switch on the state.value we do a bunch of things then we modify the state.value and over here modify the state.value okay let's see some more errors over here all of them pretty much the same thing we just have to access the value in order to fix all this okay so that's almost all the errors now an important thing is since over here on the update we made it so that only the server runs this code just like this only the server is going too far off these events we need to modify where we are firing this since we also want the clients to listen to these events so let's listen when the network variable changes so let's go up here and as usual let's first of all make an override for the on network spawn so we have this one and then let's go into that one so that's the state so state DOT on value change let's make a function called State on value changed and let's use Visual Studio over here to Auto generate the function okay so here it is with the previous value and the new value and when the value changes when the state changes then we fire off this same event so just like this and get rid of all of these instances yep only this one just like this okay so modify the network variable and all the clients are going to listen to this event which in turn fires off this local event so just like this all of the clients should have all these states synchronized now we can go down here to when we are sending deploy ready so if all the clients are ready if so let's modify the state.value and let's begin the countdown so let's go into not waiting to start but into the countdown to start okay so just like this it should work so it says so here we are and on the host I'm going to set as ready and there you go it's waiting for players now down here I'm going to press and it should start the countdown so let's press and there you go all of them are ready and we've got our nice countdown okay so that's great however if you notice down here the client down was stuck on the countdown timer of three and we also noticed that the timer over here is not being synchronized with that one so let's synchronize both these as well basically we have the countdown timer and the game playing timer we need to synchronize both these so let's make them as Network variables so this is one and this one is another one for the countdown timer let's do a new let's start off on 3F and for this one do a new and start off on zeroth okay now let's clean up all of these errors so let's see down here this is the server code so let's just do value in order to test that one and same thing for here and same thing on this one pretty much just have to modify to access the value like that and down here to get the countdown timer get the value and over here same thing get the value okay so that fixes all the errors and let's also go up here in order to also test out the game over State let's go for the game playing timer Max let's put this one just antenna just for testing okay so let's test all right so up here let's connect the host then on all of these let's make them coins okay great now if I ready let's say on this one if I ready you better go waiting for players now you're going to this one ready yep still waiting for players now I go into this one ready and yep still waiting they're on waiting for the last one and as I ready this one yep it started playing the countdown the countdown timers are all synchronized and the game starts yep and over there we can see the timers yep those are also being synchronized and as soon as they reach the end let's see if they all synchronize the game over Saint as soon as they reach yep there you go we have the game over all right awesome okay so here we synchronize the main game State waiting for all the players to be ready synchronizing the countdown timer the game timer and finally the game over now just one more thing there's a minor bug that only noticed right now if instead of setting ready first on the host if we set it first over here on the client and then set it as ready on the host if there go this one say stuck on the wedding for players so let's fix this this is a super simple fix basically the issue is that when this event is fired that's when that window becomes active but when we set the player ready server RPC that one if only coins are ready is going to trigger this start countdown so basically when this one happens that window hides itself but then this code runs and that window shows itself so just a minor issue and The Simple Solution is just make sure to fire the event before we set the server RPC to send the ready so if you didn't like this now here on the client let's go ready on the host already any up there you go everything works okay great now before we end this lecture let's just go over here to the game playing timer Max and let's reset this back to the normal value of 90 seconds okay so with that the game State The Zone working perfectly one thing we still don't have synchronize is the pause date so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to synchronize the pause state so here we have our game where we already have tons of stuff already perfectly synchronized however if I pause the game on this one and if there go now this one is not playing and everything still works and if instead of pausing on the server if now I pause over here on the client so the client is paused with the server is still moving and we can see over there the countdown timer is still moving so we need to sort this out some way and for the pause multiplayer games can handle it in different ways the simplest option is simply to not allow pausing at all adding that ability is super easy we're handling the pause over here on the kitchen game measure so we have over here we have a toggle pause game and when we pause we set the time scale to zero and when unpause set it back to one so the simple option to not allow pausing to modify the M state would be just to not do this so we don't modify the time scale that's the simplest option with that basically the local player can check the settings and so on but for everyone else the game will keep playing just the same so this is the simplest option that a lot of games implement the main reason for that is usually to keep things Fair if you have for example a shooter game you don't want one player to pause just as the other player is winning so in those games pause usually doesn't happen but on a co-op game like the one we have here usually you do want to allow pausing just because it's a useful feature to have and in Co-op it's not much of a problem as it is in PvP games so let's go back to our code and let's also Implement some simple power syncing meaning that any player can pause the game and the other players will need to wait for the game to be unpaused how we do this is actually pretty simple we're going to do pretty much exactly the same thing that we did for the player radian logic we're going to have a dictionary if one of the players are unpaused the game is going to unpause and if at least one of them is paused then the entire game for all the clients will be paused so first of all we need to tell the server if you want to pause so let's use a server RPC so a private world let's call it pause game server RPC this one will be a server RPC with require ownership as phones okay then just like we did with the ready the server needs to know which client paused the game so let's receive the server RPC params and as usual let's put it as default okay so we have a pause function and we're going to have another one pretty much exactly the same for the UN pause okay we have these two and up here when we do this let's trigger a pause and Trigger the unpause so now for starting the prostate let's use the dictionary just like we saw so let's go up here and let's make another dictionary it's going to be exactly the same so we're also going to have a young long for the client ID and then a volume for is player paused or unpause so let's call this the player pause dictionary and let's initialize it so up here let's do a new dictionary okay so we have this and then down here pretty much the exact same thing so let's go into the dictionary let's use the server RPC params on the receive let's grab the sound sender client ID and for pause let's set this one to true so this one is paused and this one won't be unpaused okay so with this now the server knows which players are paused and which are unpaused then let's make a function to see if any of them are paused so let's make a product Droid call it test game pause state and over here let's cycle through all the client ID so let's do the usual for each you'll own for the client ID in and let's go into the network manager let's go into Singleton and let's grab the list of client connected client IDs so we have this now let's see if any player is paused so if the player pause dictionary contains a key with this client ID so faraziki and the player pause dictionary on this client any if that one is true that means this player is currently paused so this player is paused if so then we're going to want to pause the entire game and if we get down here so we do that and then let's return we don't need to go through the 4H anymore and if we do get down here then at least all the players are unpaused so all players are unpaused and of course we're going to run this function after we set one of these so after a player pauses or unpauses we run this code to test if the entire game should be paused or unpaused so now let's leave this to tell the clients to either pause or unpause their game we can do that either with a client or PC or we can use a network variable for this one let's use a network variable so up here let's go and we have the is game paused let's rename this to be more accurate this one refers to the unlock comp player so let's rename this and instead let's name it is local game post and then we're going to have a network variable for the actual Network set so private Network variable of type bone for is game pause so we have this one and start off as phones so the game starts off on pause then we can go down here into the function testing the percent so at least one of them is paused let's go into this one that value and set it to true and if all of them are unpaused let's set this one into false okay so that's really it now we can listen to the event when this network variable changes so let's go up here to our on network spawned let's go these game paused and let's listen to the on value change so is game pause on value change and let's use Visual Studio to write out this function so here it is okay now when this one changes now here we can set the actual time scale so if is gamepause dot value so if the game is pause let's set the time dot time scale into zero f because the game is paused and if not let's set the time.time scale into one app okay so with this the pause State and the time scale won't be synchronized across all the clients let's just go down here because we don't want to make sure to modify that somewhere else so down here let's get rid of the time scale and this time scale now for these events we're using these events in order to show the pause window so these are still useful let's just rename them to make them a bit more accurate these are only going to be fired based on the unlock on pause date so let's rename this to on local game pause and this one on local game unpaused now let's rename also The Listener functions so it's over here on the game plus UI so we have these functions let's rename them quickly so on local game pause and over here for this one on local game unpause okay so just like this the game pause window should be working correctly so the unlock on pause should be working with a nice visual but we also want the visual to reflect the synchronized State we need something to say that it is waiting for all of the players to unpause so back in the editor let's go inside the canvas and let's begin by duplicating the game pause UI so let's duplicate this one let's name this the pause multiplayer UI then inside let's keep the background keep the pause tags just get rid of these buttons and for the pause text let's just say waiting for all players to unpause let's put it a little bit smaller okay so like this then for the soaring order let's put this one behind the game pause so let's put it right above there okay great now let's make sure to remember to get rid of the script and we're going to make a script to run this so let's go into our scripts create a brand new one with the same name so pause multiplier UI and let's attach a script so the pause multiplier UI and let's open here let's begin making the usual show height function so proud void show and they approach void hide and game objects at active either into false or up here into true okay now we need to know when to show this one so we need to know when the global game state is paused so back here on the kitchen game manager let's just make some more events let's call it on multiplayer game pause and on multiplayer game unpause so we have these two events and for these we're going to fire them when the network variable changes so over here is game pause on value change so on this one invoke so this one is going to be paused and on this one it is going to be on pause so the on multiplayer game unpaused okay so we have these two events and now back in the script let's just listen to them as usual so make a proud void start don't start go into the kitchen game manager and listen to the on multiplayer game paused and unpause let's just rename this to give it a proper name so kitchen game manager and then the other one so same thing on the instance on the multiplayer game unpause let's rename this one as usual okay we have our two events so when the multiplayer game is paused let's show and when it is unpaused let's hide and on start after win listen let's hide okay so that's it pretty simple Let's test okay so here we are I have the hosts and two clients now if I pause in the host if there go all of these are waiting for on players to unpause and if I unpause on the host if there you go the game is back to normal now if I pause on this one yep there you go the game is indeed paused and we can see over there the timer is now counting down so yep everything is indeed paused and if I try moving also doesn't happen because the game is paused now let's go into this other one and let's pause this one so now two of them are paused now up here if I unpause this one if there goes still waiting until I go down here I unpause and you have to go everything back to normal the timers are running everything is working all right awesome okay so here we implemented some nice pause syncing this way our Co-op game is very friendly to people who might have to pause an online game for any reason now one scenario would still haven't handled is what happens when a client disconnects so I sort that out in the next lecture hello and welcome I'm your code monkey in this lecture we're going to handle player disconnects and this is actually going to be super simple okay so our multiplayer game is really coming along now in single player we don't really need to worry about the player randomly quitting but in multiplayer we need to make sure that the game actually keeps working correctly if a player does decide to leave so for example if down here on this client if I just close this window and right away we can see that it does work very well so the player object was removed from the world so it looks like it already Works basically when the player disconnects all of the network objects that player own are destroyed with them so the player prefab is destroyed automatically really the only issue we have is if that player is holding something so if down here on this player I just pick up some meat and now I quit and if there you go now we have some meat holding along in midair that's the issue that we have to solve the player object is destroyed automatically but we need to make sure to manually destroy the kitchen object the player is holding so for that let's go here on to the player script and first we need to know when a player disconnects and for that we can access a comeback so let's go over here onto the on networks Bond and we're going to go into the network manager next to see Singleton and over here we've got a comeback on claim disconnect compact so let's listen to this one let's rename this to network manager on client disconnect come back okay great and for the you along over here this is going to be the client ID so the client ID of the client that was disconnected and we can see over here on the documentation this comeback will be ran both on the server and on the local client that disconnects now in this case for the client that disconnects we don't really want to worry about them so we really just want to listen to this on the server so we can just add here if is server and if so we're going to listen to this also remember that the is server here this one refers to the state of this build and not this specific player so this one will still touch on listener on the server side even on players that aren't actually the host okay so with this comeback now the server knows when a player disconnects with the client ID that we have here we can check if this is the one that was disconnected so let's check if this client ID so the one that disconnected does match the owner client ID so if so then it was this one then next thing we want is to check if this player is holding any catch an object so if it is this one and has kitchen object if so then we want to destroy it so as usual let's use the kitchen object and destroy the kitchen object and pass in this dot kitchen object we can only destroy the server but over here we already attach The Listener only on the server so yep this should be working okay so just like this let's test okay so here with the client let's pick up something and now let's quit on the client and if there you go the object is indeed destroyed alright awesome so just with this we already have the entire game logic working perfectly with disconnects there's nothing else the player can do that could affect the gameplay itself if they disconnect in the middle of cutting or frying an object that doesn't cause any issues the one thing that can cause issues is if they pause the game and then disconnect so here are both and down here on the client I'm going to pause the game and then I'm going to quit and if there go this one did clean up the player but now this one is stuck waiting for unpause now thankfully the way that we handle the power synchronization we made it over here here by cycling through the network manager connected client IDs meaning this is actually only going to test the state for the external connected clients so because of that this here isn't actually a game breaking bug if on this remaining client I just pause and unpause and you better go another player now the game is back to normal but obviously it should automatically unpause if the only pause player quits so let's fix that this is also going to be a pretty simple fix so let's go over here onto the kitchen game manager this is the class where we're handling of the pausing so on this one just like we did on the other one let's listen to the disconnect comeback so we're here on the onet respond let's check if is server so on the server let's listen to it so network manager the Singleton on disconnect convex and let's listen to it and as usual rename this keep things clean so network manager okay so we don't listen to this and over here for the parameter this is the client ID although right now we really don't need the client ID because afterwards we really just need to run the function test The Game Pass State this will then test all of the clients and see if any of them are dollars and if the one that disconnected was the only one that was paused and this one will unpause the game however this won't actually work the reason is because when this comeback is fired when this happens the client is still going to be on the connecting list so if it Cycles through this it's still going to cycle through the client that is just disconnecting so basically to solve this we need to wait one frame to make sure that this list is updated so it's basically making a Boolean and then after that update then we're going to run this function so up here let's make a private bone call it auto test game pause State we're going to test that automatically so then when we have our disconnect let's set this one into true and over here we are not going to run this function all right then let's go down and we're going to make late update so let's go over here a private void late update and on late update let's check if this one is true if so then first of all let's set it to phones and over here we run the test Game Pass State okay so like this it should work so let's test okay so here we are and on the client down here let's pause and now let's quit and if there you go that One automatically unpauses and everything works okay great so the pause disconnect logic is working now let's see basically the opposite which is what happens if the host quits so with the host appear and the client down there if on the host I stop playing and if they're going like that everything shuts down all the players get destroyed the network manager automatically stops running so in terms of logic it already works so the game definitely stopped working but obviously there's no visual for the players so let's make one let's go inside our canvas and over here let's begin by duplicating the game over UI let's name this one the host disconnect UI and let's put it on the Sorting just before the game pause UI so just like that okay then over here for the text let's rename this to just say text and inside let's just say host has disconnected let's put it a little bit smaller move it a little bit down and we don't need these other ones so let's get rid of these two just like that and we can leave the play again button okay now let's make the script to run this so with the same name let's go ahead create a brand new c-sharp script for the host disconnect UI over here let's get rid of the game over UI and had the host disconnect UI okay let's open now on this one let's first of all add the reference to the button so a serialized filmed private button for the play again button okay like this back in the editor let's drag that reference on right so now let's make the usual show and height functions so private void show and a proud void hide just set game object set active into false and over here into true okay we have our functions then for showing it we need to know when the host has shut down and for that we can actually listen to the same callback so let's make a private void start on start let's go into the network manager the Singleton and let's listen to the on disconnect comeback so let's add a listener to this one network manager okay so we have this one and again over here we have the client ID and now to know if the server was the one that shut down we can basically just compare this client ID to the server ID so let's check if this client ID equals the one on the network manager dot server client ID this is a constant the server is always on ID of zero so let's do this so if it is then this means the server is shutting down and if so then let's show this window and on start let's start off hidden okay that's it a simple script okay so up here is the host and the client and if on the host I quit and if there go host has disconnected all right awesome so with this we have handled pretty much every single possible scenario except perhaps the more obvious one which is enabling the player to minimally quit out of the game right now if I'm here in the editor let's say I start off as a host then I go into the pause menu and go back into the main menu yep here I am in main menu and if I look in the hierarchy you have the network manager yep it is still running we still have an active connection obviously we don't want this to happen so let's go over here onto the Game Pass UI and this is where we have the main menu button so we unload the main menu scene but before we do that let's go into the network manager the Singleton and let's call the shutdown function so this is going to shut down our connection really we just need to do this in every place where we hit the game so that's over here on the game plus UI and the other one is over here on the game over rewind so we unload the main menu and before we do that let's shut down the network manager okay so let's test here we are let's host and let's go back into the main menu any up in the inspector we can see network manager no longer has an active connection alright awesome so here we have hand on every single disconnect scenario the players can disconnect and the server handles everything gracefully so now that the disconnects are working let's think about the opposite which is what do we do to handle client rejoins let's talk about that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to talk a little bit about the concept of late player joins okay so here's our game which is actually pretty small each session of this game is only a few minutes long so because of that we're not going to allow light joints doing so adds quite a bit of complexity so for a game like this one we're going to make it so that everyone joins in the very beginning and they all play until the very end if someone drops in Middle they can simply just restart the session but still I want to talk about the topic of light training because for other game genres this is indeed extremely important now the reason why handling that is so complex is YouTube potential problems with data desync there are two main methods we have for synchronizing data we have rpcs and we have Network variables the one big difference between both of them is that when a client joins linked they won't receive the current state of a network variable but they will now receive all the rpcs that have been sent since the very beginning of the game in here in this game we use rpcs quite a lot to synchronize tons of stuff we use them because they are quite simple to use and very easy to understand like for example on setting the kitchen object parent so let's do a quick test okay so with the two builds down here I'm going to connect the host but I'm not going to connect the client just yet so I'm going to start playing with host County countdown timer now I'm going to pick up something let's say I pick up some meat okay and now if I connect with a client and now actually we have the thing where we synchronize this window so let's manually just hide this so I'm just going to find the window the tutorial UI and just hide it and if there you go look at that we can now see the desync basically this second player joined late so this one knows that an object will spawned so that object is indeed spawned but it does not know that the first player is actually the one holding the object so we have a data desync the second line did not receive which one is the kitchen object parent for this game object again this is the difference between spawned objects and rpcs the kitchen object itself that one was indeed synchronized but for the apparent data that one is only synchronized through an RPC so the second player doesn't know what happened there and now if over here on this one if I just drop it somewhere there you go now everything is indeed synchronized because this one is now connected so this will now receive the new RPC so in this case it's not necessarily a big issue since it does end up sorting itself out but another thing we have synchronized through rpcs are the recipes so I'm going to start again on this one down here I'm going to connect as the host and start playing and there you go this one is now going to generate some recipes and if there go generate one so now on this one connect on the client let let me hide that UI and if I'm looking there nope it did not receive the very first recipe so now they have different amounts of recipes again that is because we used an RPC in order to send the new recipes Bond so this one joined late so it missed the spawning of the very first recipe so now the two clients have different data for what recipes are waiting also same thing over here on the plates counter again this one is using an RPC so you can see over there the plates come to his phone but that one missed the message spawning the first plate so this is the main tricky thing if you want to make a game where you want to allow only joining then you need to design your game in such a way that all of the important data is synchronized in a way that is automatically synced one option like I said is using network variables those are synchronized automatically when someone new joins so even though this second player this one joined late you can see over there the actual timer for the game that one is being synchronized correctly even though this one joined late that is because that one is using a network variable so if you made the waiting response Network variable it would synchronize correctly however the reason why I used rpcs is because we cannot directly put a script mode object inside a network variable so over here on the delivery manager it would require a different code in order to synchronize this list you could either make a network variable with a list of hints to hold the index for each recipe so or you could implement the inetwork serializable to teach NGO how to serialize this specific script note object I cover that in the netcode video so it's definitely possible it just requires a different approach another option would be to keep using rpcs just like we're doing here but when a new player joins you would have the server send the player all the data they need to synchronize so for example over here on delivery manager you could add a convex listener when a client connects you can listen to that through the network manager the Singleton and here is the client connect comeback so you couldn't listen into this on the server then when this happens you could have the servers and a client RPC just that client to tell them all the recipes that have already been spawned then from that point on everything would already be synced so adding support for only joiners adds a bit of complexity but it is certainly doable as to whether you need it or not really depends on the game you're making if it's a quick session game like the one that we have here then I think it's not really worth it to add that extra complexity but if you have a game with longer sessions then of course that one is a must so keep that in mind when building your game from the very beginning and deciding whether to use rpcs or network variables so here for this game let's not allow only joiners and how we do that is actually very simple if we look over here on the network manager game object if we scroll down down here there's a toggle for connection approval right now every client that connects gets automatically accepted we don't want that so let's instead enable this and then let's go here on to the kitchen game multiplayer script and on this one we can listen to a comeback however one very very important thing is we need to listen to The Comeback before we currently start host so let's make a start host function over here on this class let's make a public void start host and then we're going to have a public void start client and over here we have the testing netcode UI so these are the two testing buttons that we using instead of directly going to the network manager and calling it let's go into the kitchen game multiplayer the instance and use that function so the start host and then the start client okay so we go through those functions then over here on these let's do the same thing so network manager the Singleton start the client and on this one network manager Singleton and Starkey host and now here before we start the host let's go into the network manager the Singleton and let's listen to the connection approval comeback let's add a listener to this delegate now this isn't an event so visual studio isn't going to automatically run this so let's call this network manager connection approval comeback and now let's use the visual studio automatic things to generate this method okay so here it is so we take an argument for the connection approval request and then another one this one is for the connection approval response and now here how we either approve or disapprove of a connection is very simple we just go inside the connection approval response and over there there's something called approve that is a Boolean so we can set it to true to allow our phones to not allow so for right now let's make sure we only approve connections when we are in the waiting to start state so over here on the kitchen game manager let's just expose the waiting to start state so let's go down here where we have a whole bunch of functions so let's go a public ball is waiting to start and just return if the state.value equals the state that waiting to start okay so then over here let's check so check if the kitchen game manager instance is waiting to start if so then we are going to approve the connection and if not we are going to disapprove the connection now actually in a bit we're going to refactor this to make it so that the connection is actually established in the lobby but for now this testing code should work so let's try it okay so over here first let's create a host all right and now this one let's join right away alright so both of them are on waiting to start so if I click on client this one is going to connect but instead of that let's start this one okay waiting for players this one start and if there you go it starts the countdown and actually here we see one thing that I forgot you can see that the players weren't automatically spawned that is because when you enable this connection approval you need to manually tell it to create a player object so over here when we approve we also need to go into the response and over here set create player object into true so this will now revert the same behavior we had previously where the player object won't be spawned automatically okay so let's try again over here create the host over here join as the client all right now let's start this one waiting for players this one's starting there you go the game has turned these two players are connected so now it shouldn't be accepting any more players so down here if I try to join and if there you go it does not work the host has disconnected so that one can no longer join our clients alright awesome okay so here we talked about whether you want to allow only joining or not and the various challenges that come with adding that feature and we also limited how the players can join our game with that our entire game logic is now working in multiplayer what's left is really handling of the other scenes but before we build those scenes let's actually set up the entire connection flow so let's do that in the next lecture hey again here's another quick intermission good job on syncing with the course by now I really hope you've already learned a ton from the course almost all of the core multiplayer logic is already done by now although the following lectures and also actually some of the more important ones handling the connection scene flow the character selection Lobby relay and so on they can be a bit tricky so definitely do take your time I hope you've been following the website as you go through the lectures and I hope reading the frequently asked questions has helped you in some way if you enjoy my teaching style then check out my other course after finishing this one especially the turn-based strategy course that one would be an excellent follow-up to this one alright let's go to the next lecture hello and welcome I'm your code monkey in this lecture we're going to handle the connection scene flow meaning we're going to hand on the changing of scenes and set up where we're going to actually create the netcode connection in order to prepare for the future and Lobby and character select scenes we're going to start from the main menu with no connection then the in lobby scene handles the unlocking list as soon as the player joins the lobby it automatically creates a netcode connection and goes into the character select scene on that scene the player will then select the character and set as ready when all players are ready the game will load the final game scene and start the game okay so let's handle the connection scene flow let's begin by making the scenes so let's go into our scenes folder and let's create a brand new scene let's name this one the lobby scene and let's duplicate this one to make the character select scene okay now let's first go inside the lobby scene and over here let's create a brand new canvas and let's set it up as usual so screen space overlay then over here scale with screen size reference resolution of 1920 by 1080 and match with the height so the usual setup now inside the canvas let's create an empty game object come with the testing Lobby UI let's put the width and height both on zero again for this lecture we only just want to handle the connection foil so we're just going to make some testing buttons we're going to set up the proper Lobby in the enlightened lecture inside this game object let's create a simple button call this the create game button inside let's put create game on the text let's put it a bit in bold a bit bigger and on the button itself also a bit bigger okay great then let's make another button so duplicate this one put it down this one is going to be the join game button and inside for the text for this one join game okay we have our buttons now let's make a script to run this so let's go into our scripts folder inside the UI let's create a brand new c-sharp script with the same name so testing Lobby UI let's wait for it to compound and over here let's add the testing lab UI okay great let's open now this one first of all let's add some references for the buttons so a serialized field private of type button first we have the create game button and then we have the join game button so we have these two here in the editor let's drag the references so the create game button and the join game button all right and over here let's see pretty much exactly what we were doing on the testing UI on the game scene meaning we're just going to start either a host or a client so let's see if I would awake let's go into the create game button the on click let's add a click listener on this one we go into the kitchen game multiplayer the instance and call start host and then for the other one for the join game button on this one we start as a client okay so we have these and this is going to start a host or a client which also means we need to create a network manager in the lobby scene and not on the game scene so let's save the scene and let's go inside the game scene then over here and let's find the network manager okay great so let's copy this so Ctrl C let's go back into the lobby scene over here control V okay we have the network manager let's go back into the game scene and over here let's make sure to delete the network manager remember that the network manager works as a Singleton that does not get destroyed on scene changes so we need to make sure we only spawn it once and we're going to do that just over here on the lobby scene okay great also for the settings we're not going to want to spawn the player right away since there is no player object over here on the lobby so let's click to select the player prefab field and then press on delete in order to clear it okay great so just like this we should have this button which creates a host and this one which joins as a client but if we test right now nothing will actually happen since we just have a connection being established and nothing else according to our connection flow once we connect we want to load the character select scene so let's do that over here on the create game button we first start the host and then afterwards we're going to download the next scene so we're going to loader.com load and let's pass in the next scene so let's actually add them to the list so over here on downloader script let's set our two scenes so don't want to be seen and then we have the character select scene again here make perfectly sure the names perfectly match the actual C names so be very sure the names are perfect and over here we're going to download the character selecting okay like this however this part is actually extremely important for unloading the scenes we're actually going to use the network manager itself to handle scene management that way all the clients are going to be synchronized automatically so in order to do that we need two things first one is over here on the editor on the network manager let's scroll down and over here we do see enable scene management so let's make sure this one is enabled this makes it so that when you change scenes in the server all of the clients will automatically unload that scene as well and the second important thing is that we need to load through a different method so over here on this load function we are going through the regular scene manager in column load scene in order to make it work with the network manager we need to do it through a different function if you don't do it if you just use this function then the objects on new scene will not automatically spawn personally I found this out the hard way while making the Prototype I had no idea why the objects on the game scene weren't being spawned and that is because I was using this using the scene Venture instead of going through the network manager so if you have issues where you're changing the scene and the objects are not spawning on the network double check to make sure you're changing scenes using the scene network manager so over here let's make a function to do exactly that let's make a public static Point call it load Network and we're going to receive the same scene for the Target scene and over here instead of going through this inventure let's go through the network manager the Singleton let's access the scene manager and in there we can now call load team and let's pass in the same scene so the target scene and as usual this one takes these strings so let's do A2 string and then for the unload scene mode you can load as additive but in this game in the simple game we're always using just single so let's go with single okay so that's it so we need to make sure we always use this function and not this function now one note here note how with this we're actually bypassing the unloading scene that we made in the Xeon Player version I'm doing that just because handling that would be quite a bit complex and this connection flow and lecture is already a bit too long basically we would need to wait until all the clients load the unloading scene before the server starts loading the funnel scene so it's definitely doable just requires a bit more complexity here to keep things simple let's leave it just like this in multiplier so it's going to load the scene right away so back here in our testing Lobby why instead of using download let's use the unload Network and also over here on the client on this one we do not need to add it because the client will automatically load to match the scene that is loaded on the server okay so with this we're almost ready to test we just need two more things first of all over here when calling start host or start client in the end we're going through the network manager but right now we're actually going through the kitchen game multiplier so we also need this object on the lobby scene just like we have the network manager so let's save the lobby scene let's go inside the game scene let's find over here the kitchen game multiplayer let's copy this back in the lobby scene paste it and back in the game scene save the changes and clean it up from here okay great so we have it just over here on the lobby scene however we have another sneaky issue like this this object won't be destroyed when you unload the character selecting we don't want that we want this object to persist for as long as the network connection is active pretty much just like the network manager so over here on the kitchen game multiplayer on the awake we can simply do don't destroy and load and pass in this game object that will make sure that this game object does not get destroyed when the scene loads okay great so one more thing it's over here on the connection approval comeback in the lobby we don't have any waiting to start state so for now let's just always accept the connection and then a little bit will handle the proper logic so just set this one as approved as true and let's get rid of the rest okay we're almost done just one final thing which is let's go into file into the bond settings and over here in the build list we need to make sure to add our new scenes so let's go ahead find the lobby scene drag it and the character select scene drag it and also for testing we're going to need to make sure to start from the lobby scene so let's just drag it over to the top so that one is on index 0. okay so we can now test so let's make a regular build and over here in the editor make sure you are on the lobby scene when you hit on play okay so here is the editor in the building both running both working great so there are no errors if you have some errors in your game go check the error chances are you possibly forgot to copy one of the objects onto this scene so with this everything is already working correctly and now on this one I can press the button to create a game and if there go it goes into the character select scene and then on the build down here I'm going to join the game and if there go it also unloads that scene alright awesome so the first part is working we're going from the lobby scene to the character select scene with no errors now let's handle the transition from character select onto the game scene let's go into the character select scene and over here as usual let's make the canvas and set it up so a brand new canvas screen space overlay scale with screen size with 1920 by 1080 and let's match probably with a height okay great now inside let's create an empty game object for the testing character select UI inside let's create a new UI create a new button call this the ready button inside make it say ready okay we have the button now let's make a script to run this so let's go into our URI folder and create an easy sharp script let's add the script so the testing character is like UI okay let's open over here and let's begin by adding a reference to our button so a serialized film private button for the ready button okay let's save back here in the editor let's drag the reference all right and now the goal here is to pretty much use exactly the same logic that we made for the kitchen manager over here on the main game manager script we have the radiant logic so the game would only start when all of the players were ready so the logic is exactly the same so let's actually copy the exact code so let's copy first of all the playwright dictionary except we don't want to run that logic directly over here on the UI script so let's make a proper script let's create a brand new game object for the character select ready and let's make a script with the exact same name so the characters like ready let's reset the transform and add the character select rating okay now this one let's actually paste that code so first of all let's copy over here the playroom dictionary and over here let's paste it okay we have the dictionary then we need to initialize it on awake so on awake the playwright dictionary let's make a brand new one then let's see what other logic we're using with this one and it's down here we have an RPC in order to set it as writing so let's just copy this entire function and over here let's paste them and when you do make sure you add using entity.netcode up here Visual Studio should do it by default but make sure you do it okay so this is really going to do the exact same thing so go through the play around dictionary and see if they are already and if so then it's over here instead of setting the state over here we're just going to load the final scene so going to downloader and again remember to use the unload Network function and we're going to load the game scene okay so that's really it super simple then for calling the server RPC and let's expose a function set player ready and over here we call the set play ready with the server RPC so we just need to call this function from that button in the DUI so let's go up here make a public static character select ready in order to make our static instance they get any private set and over here on the Wake set instance equals this okay great so now back here on the testing character select UI let's make a simple awake let's go into the ready button the unflick let's add a listener and on The Listener let's just go into the character select ready the instance and let's set the player as ready okay so that's it this should be working let's just do one more thing let's go into the game scene so let's first of all save this scene go inside the game scene and over here on this one on the canvas we no longer need the testing netco device and let's just disable this one like this and actually just one final thing that I forgot over here in order for the server RPC to actually work we need to make sure this one is not a Model Behavior but rather a network Behavior then back in the other turn let's go into the character slide scene select the object and yep let's add Network object that way it should work okay great so we're ready to test let's go back into the lobby scene again this is important we always need to start from the lobby because this is where the network manager is created so with this let's make a building test okay so here we are so up here let's create a brand new game and you put on the character select scene now this one down here and let's join the game and yep there you go it does work so both of them are on the character select scene now this one up here I'm going to click on ready and there you go this one is ready but it did not load the game scene it is still waiting for this one down here to be running and as soon as I set ready on this one it is going to tell the server that it's ready and if there you go the server automatically unloads the final game scene and this one loads with it alright awesome so everything is working great now over here we are waiting for players and there you go it works however obviously you might be noticing one issue right now since we removed the automatic spawn player prefab we have nothing over here so we need to manually spawn the player let's do that let's do that over here on the kitchen game manager this script only exists on the game scene and for spawning we only want to spawn when all of the players have loaded so for that let's go down over here onto the on network spawn let's go in the network manager and if we go inside the Singleton and then inside the scene manager over here we have a function on load event complete this one is triggered when all of the clients have loaded the final scene again it's important it's this one not this one this one up here is triggered on a perk like basis whereas this one down here is when all of the clients have loaded so let's go with this one let's listen to this one and over here it's pretty simple we just want to spawn all the players so let's cycle through all the connected clients so you loan for the client ID and the network manager Singleton the connected Client List okay we have all the connected clients then we need to spawn the employer prefab so we need a reference let's add it up here so we serialize filmed private transform for the player prefab so we have this then the editor let's go inside the game scene and let's go into the kitchen game manager and let's make sure to drag the player prefab there it is also one important thing since we are spawning the player let's go into the lobby scene let's make sure to save and on this one on the network manager in order to spawn the player prefab dynamically we need to make sure we add it up here since we removed it from the player prefab up here we need to add it onto the network prefabs so let's add brand new one and drag the player prefab okay great back in the code here we have the employee prefab so down here in let's just call instantiate instantiate the player prefab so this is going to return our player transform so we have this then on this one let's see we get component to grab the network object and on network object we can call the function spawn as player object so not to spawn but the spawn is player object this one takes a client ID so let's press in this client ID and then for the story with scene we do want the player prefab to behave as a regular game object so we do want to destroy the scenes so let's go with true alright so that's it this will spawn the player prefabs and after that the rest of the game should work perfectly okay so let's test and again as always in order to test make sure you test from the lobby scene okay so on this one up here let's create the brand new game alright here we are then down here let's join okay it works now let's set us ready so I'm waiting for this one this one goes as ready and you both have loaded the final game scene now as I start playing and there you go each of them now has their own player controller and now yep all the rest of the game all of it is perfectly synchronized alright awesome next let's handle the connection accept logic so over here on the kitchen game multiplayer we modify this combat in order to always approve now we only want to accept while we are on the character select scene so what it says if the current scene is the character select scene so let's do a simple if let's go into the scene manager let's get the active scene and let's get the scene name then we compare let's compare with unloader.scene and check if we are in the character selecting now we need to compare string with strings so let's use the two string okay so we compare if we are on the character select scene and basically if we are not on the character selecting then let's approve as funks so cannot connect then let's return a reason so on the reason let's just say the game has already started okay so that one we don't approve and then let's return to stop the rest of the execution the next validation is checking the max number of players we only want four players maximum so over here we can do an if let's go into the network measure the Singleton get the connected client IDs and we check the account and we compare it against something so for defining the maximum let's actually go up here and make it a constant so a private constant for the max player amount and let's say we want to maximum of just four players okay with this and now down here we can compare if we already have way too many then once again same thing let's not approve and let's say game is full okay and if it's neither of these then we do accept it okay so that's in logic now let's add a visual the connection starts here on the lobby scene so let's add the visual here let's go inside the canvas and create an empty game object let's call this the connection response message UI let's make it stretch occupy everything and put 0 0 on everything okay then inside let's create a new UI image call this the background and again let's make it stretch to occupy everything and let's put this one on black with a little bit myself okay great then let's also add a text so a new UI text call this the message text and here we're going to say some message so let's put it the usual setup so width and height of zero let's disable wrapping put it down Center down the middle in bold and lift it up by a little bit okay then let's also have a button so a new UI button call this the close button and inside let's say close let's put the button text in bold put it in white and for the parents for this one put it in a dark gray and just like this we have a simple nice button on X of zero okay great we have both elements on this window we're going to show the disconnect reason message now let's duplicate this one for another window which is saying connecting so let's duplicate this window call it connecting UI and on this one get rid of the close button we just have a message and for the message let's just say connecting okay just like this now here obviously you could merge both these windows into just one but let's keep them separate to keep things a bit more clean so we have our UI setup now we basically just need to know when the player tries to connect and when that connection fails so we're here on the kitchen game multiplayer let's make a bunch of events so let's make a public event event handler and let's call it on trying to join game another one on fail to join game okay then let's go down here and the first one is when trying to connect for that one let's fire over here before we call this dark Lane so let's invoke with the usual this event RX dot empty okay and then for the disconnect failure for that let's also go up here where before we call this our client let's listen to the disconnect comeback so the network manager the Singleton on disconnect convac so let's listen to this one let's give it a proper name so the network manager okay so we have a disconnect comeback and here we've got the client ID and on this one let's fire off the event so on failed to join game so let's invoke with this in event arcs.empty okay we have both our events now let's make these scripts for our windows so let's make first over here the connecting UI so let's create a brand new UI script over here let's attach it and open okay now let's make the usual show and hide function so private void show and then we have a private void hide and same thing as always so set active as false or as true okay now let's do a private void start and on start we're going to listen some events and then we hide it so for the events this one let's listen when we try to connect so the kitchen game multiplayer the incense on we are trying to join the game so when this one happens so let's rename this kitchen game multiplayer so when this event happens let's show this window and then let's also hide it when that one does fail so on fail to join game let's add this listener so when it fails to connect let's sign okay great now let's make the other script so the connection response message UI let's build this one over here let's attach the script and let's open okay so here we're going to have pretty much exactly the same thing so let's have the usual private void show and hide then let's add references to the text and the button so let's add a serialized film and first for the text this one is text mesh Pro ugly for the message text and then we have another one this one is a button and this is going to be the close button okay let's save this and here in the editor let's drag the references so the message text and the button all right then let's add our listener so on private void awake let's go into the close button on the on click let's add in listener and this one is going to be just the hide function so that is just going to hide the window then let's do our private void start and on start let's listen so kitchen game multiplayer the instance when it fails to join a game let's listen to this one so on search we'll listen and then we hide by default and when it does fail to join the game let's show this and then let's set the message text and for the disconnect text we can grab it from the network manager the Singleton and we grab the disconnect reason so if that's it just like this both our script should be working however here let me point out one very very important thing one question that I got a lot in the single player course is with regards to unsubscribing from events you might have noticed that we pretty much never unsubscribe to events that is because you only need to unsub if the objects have a different lifetime if both the publisher and subscriber have the exact same lifetime then you don't need to manually unsub however over here these objects do have a different lifetime these UI Windows these only exist on the lobby scene as soon as we change scenes they won't be destroyed but the kitchen game multiplayer this one will live through all the scenes so we need to make sure to unsub because this object is going to have a different lifetime than the kitchen game multiplayer and how we end sub is very simple let's just make a proud void on destroying so this one is a monobehavior function which is called when this object is destroying so on this one we really just unsub so just go into that one and do minus equals so we do it over here and on the connecting UI same thing private void on Destroy let's unsub to both of these so just do minus equals okay great so now we can test all right so here I've got one two three four five coins so on this one up here let's create a game and there you go it did work then on this one let's join a game and yep it did work connected joined on this one join yep it worked this one joined yep it worked so now we have all four clients connected so the game should be full now so on the fifth one if I try to join any up there you go the game is currently full okay great so that worked now let's actually quit one of these so let's quit this one so technically now we do have one slot available so let's not connect right now instead let's set this one is ready this one is ready and this one is ready and if there you go all of them are unloading the final scene so here we have our three players okay great but the game is now playing so on this one if we do try to join and nope the game has already started alright awesome so this logic is working perfectly there's just one more possible connection scenario that is simply if the connection just times out if that happens then the same event won't be fired the only difference is the disconnect reason will not have have any text so we can just check if the disconnect reason is empty so if we have no disconnect reason then let's just set this one to just fail to connect okay so that's the text and also by default it won't take a bit too long to timeout so over here on the lobby scene on the network manager if we scroll down yep over here on DNT transport we do see a bunch of settings so we have the connect timeout milliseconds so meaning after a thousand milliseconds so one second it won't wait one second until that connection times out and then it will try to connect for a maximum of 60 times this seems like a bit too much so let's put it on just 10 tries so if it fails after 10 tries then after 10 seconds it should say fail to connect okay so let's test here we are and without creating a host let's just try to join the game and there you go it is trying to connect but there's no game so it should fail so after 10 tries after 10 seconds if there you go we have our failed to connect message okay great so with that we have almost our entire connection flow working we start from the lobby we can create the game and we can join the game we go into the character select scene and then when all of the players are ready when that happens yep the server loads the final game scene and over here we can play as normal so everything is working great all that's left is the main menu save over here on the host if I go back into the main menu there you go that one disconnects so that's great and I'm back on the main menu so it looks great but if we look in the hierarching up over there and look at that the network manager and the kitchen game multiplayer these objects are still active so if we now went into the lobby scene we would end up with duplicated objects and tons of problems so basically we need to clean up these objects and let's do it when we go back over here on the main menu so let's go into the main many scenes so let's open this and over here let's make a simple script to clean this up so let's create a new one let's call it main menu cleanup let's make a script to run this let's attach the script and open it you know here really all we need to do is just clean up both objects so that's super simple let's make a private void awake and on a wink let's just test if the network manager the Singleton if this one exists so if this one is not known if so then let's really just call destroy on the network manager Singleton game object and same thing for the other one so the kitchen game multiplayer if this instance is not null if so then let's destroy this instance Dot Game object okay so that should work with this the objects should always be cleaned up whenever we go back into the main menu just one more thing let's make sure this play button goes into the lobby scene and not the game scene so on the canvas let's open up the main menu UI and over here let's use the unload because over here we have no connection so let's use the single player load and set the game scene let's just go into the lobby scene and finally we can go into debunk settings and now we can make sure that we start from the main menu scene okay so let's test all right so here let's play we're in the lobby and let's create a game then on this one let's play let's join the game set is ready set is ready any of both of them start playing so even here we are both playing the same game now this one I'm tired of playing so go back into the main menu and if we're looking the hierarchy and if they go no more objects we have everything cleaned up now on this one I can play again I can create another game then on this one go back to the main menu and let's join again ready again ready again and if we are back in a brand new game instance alright awesome so here we handled our complete Game connection flow we start from the main menu in single player then on the lobby we have a button to create the connection in turn downloads the character slicing where more players can join then on that scene each player can set the ready to True when all of the players are ready the normal game scene loads and then the game continues as normal so yep we have all of that working now that's left is actually building out the lobby and the character slight scene so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to build a nice character select scene where the player can select their player color okay so here on let's build a character select scene this is actually one of the more common questions I've seen in my netcode video lots of games have this sort of thing so let's build it let's go to the character select scene and first of all let's just make some proper buttons so inside our canvas let's create an empty game object call it the character select UI let's make it stretch to occupy everything okay so now inside let's add a UI button call this the main menu button let's anchor it on the top left corner and let's move it a little bit like that okay let's make it a little bit bigger let's make this in a dark gray and inside for the text let's say main menu let's put it in bold in white something like this okay that's the button now let's duplicate this make this the ready button and for this one let's anchor it on the top right and let's put it over there okay then inside just say ready okay now let's make a script run this with the exact same name so let's go into the UI folder create a new c-sharp script let's select the object and let's set the script so the character select UI okay now here first of all let's grab the buttons so as usual a serialized film private button for the main menu button another one for the ready button okay here in the editor let's drag our references so that one and the ready button alright and over here let's add our click Behavior so let's make a private way to wake on awake the main menu button on click let's add a listener in order to go back into the main menu first let's shut down the network manager since on this scene we do have an active connection so let's go to the network manager the Singleton and Kong shutdown and then afterwards we can use in order not load so that's the regular load because right now we have shut down the network connection and let's load back the main menu okay great and then for the other button so the ready button on click add in listener for this one we just want to do the exact same thing we did on the testing script so here the testing character select UI we're running this so let's run the exact same thing so back in this script just run that function okay so that's it let's do a quick test before we do let's just make sure to disable that one all right and again as always for testing let's make sure to start from the lobby scene so not from this one let's go into the lobby okay let's make a build and test okay so on this one let's create the game there you go created then on this one let's play let's join the game yep we have joined now this one set is ready and nope nothing happens just yet now on this one set as ready and after a little bit yep they both load okay great so far so good now let's go back into the character select scene and let's build a proper visual sectionally for that let's first go into the main mini scene and over here let's copy some objects so let's pick up the main camera let's also pick up the virtual camera pick up the floor the global volume and the directional light okay so let's copy all these Ctrl C let's go into the character selection and let's destroy the main camera and directional light so delete these and press Ctrl V and there you go we have our objects okay so with this we have the basic visual let's just zoom in over here all right now let's position the virtual camera so let's put it on position 0 1.4 and minus 3.7 with rotation on two zero zero okay now here let's create a brand new empty game object name this the player zero let's reset the transform and now inside let's add the player visual so inside the S is a prefab here is the player Vision let's drag it on there and there you go there's the player let's just make them rotate to face the camera okay so we have one player now let's just position four players fractionally before that let's make this one a prefab so let's drag the player 0 in order to make it a prefab let's name this the character select its player now here let's make all our four players so the zero the one D2 and play three okay now let's position them let's position them not perfectly so a bit more off just to make it look a bit more interesting so player one player two alright so here we have all of our players now let's make the script to run this so let's create a brand new c-sharp script let's name the same thing so the character select player and now let's make sure to add the script onto the prefab itself so let's open up this prefab and in here let's attach a script okay now let's open it and over here let's add the usual show and hide functions basically we're only going to show as many as we have players connected so a pro void show and a pro void Hind and the usual thing game object set active into either false or true okay great now we need to handle the number of players that are connected so we know which one of these we should show or hide and then afterwards we're also going to need to sort the player data like for example the color or the player name so for that let's go into the kitchen game multiplayer over here on this script and the data type that we're going to use is going to be a networking list so it's kind of like a network variable except obviously it supports a list and for the type let's actually make a custom type this is a great way to learn how to serialize custom types so first for the type connection we're working let's make sure to save the profile go back outside okay and for the time let's create a brain c-sharp script and call it the player data okay so this is where we're going to store all of the data for the player so for this one let's make it instead of a class let's make it a struct since we're just going to hold some data and this one does not extend Model Behavior now for that over here right now let's just Begin by storing just the client ID so a public even long for the client ID so just like this and now back here on the kitchen game multiplayer on this one let's go ahead and make a film so this is going to be a network list of type player data and we have the player Data Network list okay there it is and right away we do see we have an error in order to use a type inside a network list it needs to implement I equatable so let's do that so back in our player data over here we need to implement I equatable with a t of this type so player data now let's use Visual Studio topless implement this so let's implement this interface and just requires us to implement the equals function so let's just return this client ID equals the other document ID okay great and back in here now we do not see any more errors okay so far so good now for initializing this list for a network variable usually we would initialize it right here except you actually can't do it up here if you do it you won't get an error and you also cannot initialize it on a network spawn so in order to initialize a networking list it has to be done over here on the awake so player data equals a new network list okay so now that we have this list let's populate it when a player connects so let's listen to that convex over here on the start host let's go into the network manager the Singleton and let's listen to the on client connected comeback so let's listen to this and let's rename this so the network manager okay great so when the player does connect this parameter in here is the client ID what it does let's go into the player Data Network list and let's add new entry let's create a new player data and inside for the client ID let's just use this client ID okay great so now when the player connects we're going to update this list with new player and over here on the character select player in order to show or hide we need to know when the list changes meaning when a player either joins or quits so over here let's make an event to notify that let's make a public event event handler let's call it on player Data Network list change so when that list change let's fire it off and for knowing when it changes we can either manually turn it off over here or we can also just listen to this so listen with the let's change the event so when this happens we have this and over here we fire off the local event so on the player Data Network has changed let's invoke this okay great so now we have this event and now back in here we can listen to it so on a private void start let's listen to this event so that's on the kitchen game multiplayer the instance let's listen to this event let's rename this as usual when this event happens we want to basically show or hide this character select if this one is meant to be shown or hidden so for that we really just need an index to know which player this object represents so here let's add a serialized film private a simple and and colleges player index then back in the editor let's just assign it so this one start off on Index 0. this one let's give it index one this one index two and this one index three okay great and over here let's make a function to update the player so private void update player and on this function business let's check if this player index is connected so for that let's ask the kitchen game multiplayer so over here on this script let's make a function to do just that let's make a public return Napoleon and just call it is player index connected and we're going to receive an end for the player index and over here we basically just need to know if the player Data Network list if that one has this index inside of it so we just return this player index is under the player.networklist dot count if so then this player index is connected so back in the script we just check if the kitchen game manager the multiplayer if this one is player connected and we pass in this player index so if this one is connected then let's show and if not then let's hide okay great so then for update individual we just update first of all over here on start and then of course over here when the list changes okay so that's it let's test and see if the correct number of players are shown again for testing as always let's make sure the test from the lobby scene okay let's see okay so here on let's create a game and nope right away we do see an error in order to use a custom data point just like we saw we need to implement I network serializable if not then we have this error so over here on the point of that and let's make sure to implement that so Implement I equatable and then I Network serializable so let's implement this one and let's use Visual Studio to help us Implement so we just need to implement this function and actually this is super simple we just go into the serializer so that's this parameter over here and we just call serialize Value and just pass in the reference for all the values in our struct so in this case we only have the client ID so we pass it in although importantly this one is a ref parameter okay so that's it just like this here we are serializing the client ID so we are serializing everything on the player data so like this it should work so it says okay so here let's create a game and if there you go right away we don't see any errors and we also see only one player connecting okay so that is correct now on this one then here if I hit on play and then join and if the regular player 2 is now connected alright awesome so now that we have the visual showing let's show the ready state so for that let's go inside one of these prefabs and over here let's create a new let's go into 3D object and let's create a worm text let's put the width and height on zero this is going to just say ready let's make a much much smaller font size lift it up by bit and as usual let's put it down Center down the middle wrapping disabled okay there it is we have our simple ready marker now this one is actually reversed as you can see that is basically how text works usually for text you see it from behind instead of front ahead but that's super similar to changes over here on the scale let's put just -1 on the X and there you go now it faces perfectly okay so let's name this our ready text and let's go in the character select player and over here let's just add a reference to a serialized film private let's just use a game object because all we want to do is enable I want to show it for the ready game object and back in the editor let's write the reference exit the prefab and save the changes okay so now we have these ready counters all we need to know is when this player is running so for that let's go into the characters like writing this is the one that we made in the previous lecture this script has a dictionary and over here the server is handling on the state so whenever a player set is ready it says that is true however the one issue is that over here this dictionary is only synchronized on the server note how this isn't a network variable or anything it's just a regular normal dictionary meaning that all of the clients have this variable but only the server is actually setting The Ready Set over here in order to show the radiation on only clients we also need the clients to know who is ready so this is pretty simple let's just make a client RPC to tell the clients so a private void let's call it set player ready client RPC let's make this a client RPC and as a printer let's receive a yolong for the client ID then over here we really just access the player ready dictionary on this client ID and we set this one to true so that's it very simple and we just regularly coined RPC up here so on the server the server broadcasts the same message to all the clients so passing the same standard client ID okay so that's great so now all the clients know all the clients that are running all we need is to fire off an event to know when this changes so here let's make a public an event event handler call this on ready change so we have this event and then over here after setting it let's invoke the event so this event Tower is not empty okay so now back in the character select pointer script over here let's listen to that event so that's on the character select ready on the instance let's listen to the on ready changed event let's rename this as usual keep things nice and clean so the characters select ready and when this happens let's call our usual update on your function and over here on this function so we show the player and then for the ready game object we're going to set active based on if this player is true or not so for that let's make a function to get the ready state so back in this script let's make a simple function down here so if I'm like boom just is player ready I'm going to receive a year long for the client ID and simply Returns the player ready dictionary on this client ID okay that's it very simple and over here we're going to access that function so the character select running Let's test if is play Ready except over here an obvious question is we need the Yong long for the client ID so over here we need to somehow get the client ID based on the player index so let's go into the kitchen game multiplayer to get that over here let's make a function to get a certain player data so over here let's make one so a public player data call it get player data from player index and receive an end for the player index and we just return the player Data Network list on this index so the player index okay so that's it this way we can get the player data and then from the player that we can get the client ID so back in the script let's get the player data player data we go into the kitchen game multiplayer the instance let's get the player data from the index let's pass in this player index and then from this one we can grab the client ID and we can see if this one is ready and we also need to make sure that this one has the key so contains the key on this client ID okay so here let's create a game and there you go there it is now on this one let's play let's join the game okay we have two players now on this one let's set it's raining and if there you go we have a nice ready counter and yep it is synchronized and on this one let's ready as well and you have there you go the usual Reagan logic works and the game does start playing all right awesome okay so next let's handle the player colors first let's actually start by defining the colors so let's go over here onto the kitchen game multiplayer and let's make that so let's make another serialized film let's make it a list of type color call it the player color list now back here in the editor let's assign the colors and that object is created on Lobby scene so let's go there here we have the kitchen game multiplier and yep let's add all of the colors so let's add 10 colors let's start off with a simple nice yellow as usual and again importantly over here make sure to set the alpha and one on all the colors so we have a yellow then let's have maybe a nice green after that maybe a nice orange then a nice light blue something like this after that let's go with a nice purple maybe something like this then let's go with a bit more pink then maybe perhaps a darker blue and after that let's go with some basic ones so let's go with one in Pure White let's go one a bit in the middle and let's get one almost black okay great here are all the colors again make sure you have all of them on Alpha set as one you can see the little bar down here the little white bar if the alpha is on zero then it's in Black so make sure this one is fully Alpha as one okay so we have to find all the colors now let's make a script to handle the player Visual and apply a color so let's create a brand new c-sharp script call this the player Visual and now for attaching this we want to attach it to the visual itself so let's go back into the character select scene let's save it and over here on this one we do not want to attach it just on this prefab so let's open up this prefab then we have the point Visual and let's also go inside the player Visual and now here we add it so let's add the player visual component you want to make them like this so that this script is also hatch when we go into the game scene okay let's open this script and on this one let's begin by adding a film for the body and the head mesh so a serialized film private for a mesh render for the head mesh renderer another one for the body mesh Runner okay back in the editor let's drag them so Drag The Head and the body okay great and now in order to make sure that each player uses a different color we need to make sure to use a different material for each of them so over here let's store a material for our material and now importantly let's make a part for the wink and done away for this material let's construct a new material using the current material so basically we're going to clone it so let's go into the head mesh render grab the material and this is going to clone the exact same material so we do that and then we go into the head mesh render set the material onto this material and same thing for the body so this way we are making a clone so it doesn't apply to anything else if you don't do this then changing one material won't change the visual on all the players since they would all share the same material okay so now let's make a nice function to set a color so if only Droid set player color and we're going to receive a call and over here very simple just set the material.collar into this color the material is already being used by the body and the head so just modifying the material color will already change the visual now we want to set the column right away so let's do it on a private start so let's call set player color and to do that obviously we need to know which color to use so let's go here on to the kitchen game multiplayer and let's make a function together color so down here let's make that simple function so public return a color call it get player color and we're going to receive an end and let's call this the caller ID we're going to sort the caller ID in the player that in a little bit over here we just return go into the player color list and let's grab the color ID okay so with this we have a color and over here we can go into the kitchen game manager the instance and get the color and we need a caller ID and for now let's use the player ID as the car ID but again over here we have a problem we don't have any player ID so we can either make a function to set the player and X and sort over here or we can just call it from elsewhere so actually instead of setting the player color over here instead of that let's go over here onto the character select player and let's add a player visual player visual back in the editing let's write reference and let's exit out of this prefab save the changes and on this one let's write the reference to the player Visual and on this one we do have the player index so now here we can do that so when we update the player we're already grabbing the player data so let's go into this one set the color let's go into the kitchen game multiplayer let's get the color and pass in let's pass in the player index okay that should do it so now the second player should have a different color let's test and now here if we create and there you go that one is using default color now on this one if we join and if there go we have the second color all right awesome so now that the columns are working let's make a UI to manually select a different color over here on the character select scene let's go inside the canvas and let's create an empty game object come with the character color select UI let's zoom in on it well it's okay like this now inside of it let's make a button so inside a new UI button let's call this color zero we're going to basically dynamically change the color of this button so let's put it with a width and height of 100 by 100 and inside let's get rid of the text we only want an image okay so this is our counter button but instead of a square and let's go with the circle so let's select let's say the default knobs right basically through code we're going to modify the color here in order to set the color that this one will change and now inside let's make another UI image and call this the selected and for this one for the Sprite let's go let's say over here the circle dashed let's put it to stretch to occupy everything and put it just a little bit smaller so five on all of these and that one is barely visible so let's also add an outline let's make it in full Alpha and put it maybe a little bit bigger okay so just like that this is going to be a single button and now for spawning this we can do it dynamically so just by spawning templates just like we've already done so many times before or we can just make it manually let's make it manually since when we did quite a lot of things dynamically so on the parent for organizing let's create a horizontal layout group let's put it right down the middle Center and let's add a little bit of spacing okay then inside before we duplicate this let's actually make this into a prefab so let's drag it let's rename this to a more proper name so character color select this is the single UI so it's select a single color and now let's place 10 colors okay let's give them proper names and over here on the parent let's stretch it out choose this one so it stretches on the left and the right and then for the position let's put it a bit more down there and also this is a bit way too much space so over here on the channel Force expand let's not expand on the width okay just like that those are some nice buttons now let's make these script to run this so with the exact same name let's create a brand new c-sharp script for our character color select UI and now let's make a script to run this next up we're going to attach the script to each button and now to the actual main container so on each button let's go inside the prefab and let's make a script with the exact same name so let's create a brand new sharp script let's attach it to the prefab itself so right over here so the character color select single UI all right now let's open it and over here first let's add a whole bunch of fields so it's your nice film first let's add an end for the caller ID this is going to be different on a per button basis then let's add an image so it's going to be the image that we're going to modify so that's image not image conversion so image the one inside EMT engine.edui okay we have the image and then a game object for the selected game object okay let's save and back in the editor let's drag all of our references so first of all for the image that's this one up here so let's drag the image then the color ID we're going to set it outside the prefab and drag the selection okay great so now let's go outside let's save the changes and over here and let's set the indexes so this one is on zero this one is on one this one two and so on all right we have all of our caller IDs now over here let's make a simple private void start and on start let's basically set the image color so for that let's go into the kitchen game multiplayer the instance and let's get the player color and this one takes equality so let's grab this caller ID and set the image.color on this color okay so that sets the image color then we need to know if this color is selected so let's make a private void call it update is selected and on this function basically we need to know if the unlockable player is selected or not so for that over here on the kitchen game multiplier let's make a function to get the player data for the local player so let's make a public return the player data and let's call it just get player data with no parameters and with no parameters we can basically just go into the network manager the Singleton and get the unlock client ID so now we just need to get the player data with this client ID so let's make another function to do that so public return player data call it get player data from client ID and we're going to receive a young loan for the client ID and over here it's pretty simple let's just cycle through our player data so player data in our player Data Network list so we second through that and if the player data if the player that the client ID matches this client ID then Yep this is the one that we want so let's return the player data if we get down here then we didn't get it this one is never going to reach here but so we need to return just a basic default okay so we have this one so then down here and let's get the player data with the only compliant ID and return this okay so now we have the player data for the unlocking client and now I can hear the test if this color is selected let's check if the kitchen game multiplayer instance let's get the player data for the local player so get the player data if this one dot Comer ID so we need to store the caller ID on the player data so we're here on the player data we're synchronizing the client ID and let's also store an end for the caller ID and let's make sure to update all these so this one equals if the client ID equals and the caller ID equals the other dot caller ID and for serializing we also need to do the same thing so the caller ID okay great so now back in this script we have the player data let's grab the caller ID and if this one matches the unlock caller ID if so then let's go into the selected game object set active into true and if not let's set active into false and up here on start let's go ahead and modify this and if just like this it should work by default now of course the one missing thing is when we change color but let's actually handle that first before we handle the event for change the color it's going to be by clicking on this UI button so let's make a private it awake and the button is on the subject itself so let's say we get component of type button on this one let's add a listener to the on click event so when we click on this button basically we want to tell the kitchen game multiplier to change the color so let's go into the kitchen game multiplayer onto the instance and let's call some function to change player color and we're going to change the player color onto this new color ID okay so we just need to make this function so back here on the kitchen game multiplayer let's make that function so here public void and we're going to change the player color onto this new color ID and to do that as always we're going to first run it the logic on the server so we're going to need a server RPC so A Private Ryan change player color server RPC we're going to receive an end for the caller ID and then we also need to know which player is changing color so let's receive the usual server RPC params and let's default them okay so this is a server RPC with require ownership as phones so when we change the color let's trigger the server RPC pass in the caller ID alright so here we have a nice server RPC and this player is asking to change their color now first of all let's do some basic validation just make sure the color is unused although this is a design decision if you wanted you could allow the same colors for multiple players but here I'm not going to allow that so let's make a function to check if a color is available so private ball is color available going to receive an in for the caller ID and on this one let's just cycle through all the player data and see if any of them is already using this same caller ID so let's do it for each for your data for your data in the player Data Network list and on this one if the employer data if this one does caller ID matches this caller ID then this one is not available so this one is already in use so let's return false and if we get down here then this color is available so let's return true snap here on the server PC we can check first of all if the color is not available so is color available on this caller ID so if this one is not available then color not available and if so we're not going to do anything so let's just return but if it is available then let's basically update the player data and how you do that remember that on a player network list we're using a struct so we first need to grab it then modify it then update it so in order to grab it we are going to need the player.index so let's make a function to convert a client ID onto a player that index so it's actually going to be very similar logic to this one except we'll return an INT and over here instead of four each let's do a simple four so four cycle through this list account and then we just check if this one on this index if the client ID matches this client ID if so then let's return this index and if not let's return -1 so this Returns the get player data index from the client ID okay great so we have this function and then down here let's grab that so an in for the player.index and we call that function and pass in the server RPC params let's go into the receive and the sender client ID so with that we have the player that index then let's grab the player data player data and we go in the player Data Network list on this player data index so we grab this player data now we modify it so let's modify the counter ID to the new counter ID and then we need to save it back onto the same list so we access it on the same index and we set player data equals this okay just like this when working with networking lists you need to do this if you just were to do just like this dot counter ID equals counter ID if you do it yep you have an error you cannot modify it directly so that is why we need to First grab it then modify it then upload the new changes okay so this will update the color and let's also default the color when a new player joins so if we go up here when we are creating a brand new one we are constructing a new player data so over here let's set the counter ID to something and let's set it to the first and use color so down here let's make another nice Hopper function so probably then get first unused caller ID and let's just cycle through the color array so for INT E equals zero once I go through the player colorless dot count and then just check is color available so is caller available on this color index if it is available return this one if not then we keep cycling and in the end it will never reach here because we are not going to have 10 players but so let's return just minus one okay so we have this function and then up here when a new client joins let's give them the first brand new unused caller ID okay so after all that all the clients should have a different color ID all that's left is over here on the button so we change the button in order to modify the corner ID then we just need to update it and how we're going to do that well since we're modifying the list we can just listen to that event so on the kitchen game multiplier the instance we have the event on the network list change so in this list changes when this happens then let's just update the actual visual so this one just like this okay so with this let's test just one final thing which is over here on the character select player over here we made it just using the player index but now we already have the car index someone's going to play your data grab the caller ID just like this okay so let's test okay so on this one let's create a game and yep right away we do see the whole UI with all the colors and if I click on them if you do see the player does change the color alright so that's awesome now this one down here let's join the game and there you go it does choose the first available counter so we chose the green and if I try selecting a different color and yep it works and if I try selecting the same color and nope that one does not work okay great and now if we both ready and go into the game scene any of this is the only thing that we still need to do we need to update this color so for that we have two options we could go over here onto the player script add a reference to the player Visual and set the color or we could do it over here on the player visual the only thing is we would need to modify the Model Behavior in order to make it into a network behavior that way we could know which owner owns this player visual so both options are valid let's do it over here on the player just so we don't mess up anything and add a network object onto just the visual so let's add a new one for the player visual player visual back in the editor let's go inside the player prefab and let's drag the player visual reference okay there it is and over here on search very simple just call set color so we need to pass in the player color so let's grab the player data player data go into the kitchen game multiplayer the incense get the player data and now we don't want just in local player we want it for this owner client ID so we need to make a function that takes a client ID we already have it's this different one so let's use this one to get the pointer data and then set the player color go into the kitchen game multiplier the instance get the player color and use the player data dot caller ID okay so let's test okay so here let's create the game on this one let's go with a purple then on this one play let's join on this one let's go with a light blue let's ready and on this one ready and the game is loading let's go and there you go we have two players with two different colors alright awesome okay so everything is currently looking great but here on the character selection we actually have one issue now if I disconnect this player and nope that one did not disappear and now if I try connecting a brand new one so join the game and there you go that one took another spot even though that player has now disconnected basically the issue is with our network list we need to remove the players when they leave so over here and let's listen to the other comeback over here on the host we already have one down here on the client so let's actually rename this to give it a more proper name so client on client disconnect comeback then up here let's make another function so network manager Singleton on client disconnect comeback and here let's give it a different name so on the server okay let's make this one it's over here we have the client ID of the client that just is connected so then let's just cycle through it so for end on the player.networklist.com let's cycle through it and see if it was this one so the player data player data so we check if the player data dot client ID matches the one that was disconnected then it's this one that was disconnected so now let's just remove it from the list so player Data Network list and let's call remove at and remove on this index okay and just like that everything else should be working because everything else is listening when this one changes so let's test okay so on this one let's create the game on this one let's join okay now disconnect any after you go that one is gone okay great now one more thing let's set the ability for the server to kick a player so let's go on the character select scene let's go inside this player prefab let's zoom in and look at it and on this one let's add a button so let's go into UI let's create a new UI button let's call this the kick button and for the canvas this one let's make it a warm space for time zero zero zero everything on zero let's lift it up by a little bit and for the kick button let's get rid of the text inside silent we just want an image so let's put this one really small so maybe 0.3.3 and let's lift up the canvas by a little bit okay something like this and for the image instead of this one let's go with the nice cross Sprite okay it's actually a bit too big so maybe on point 2.2 all right now on this script let's add a reference to our brand new button so the button for the kick button and over here let's write the reference to the kick button okay and now first of all we need to make sure that this one is only visible to the server so over here on certain let's put this one game object set active and it's only going to be active if the network manager.singleton.is server so this one is only going to be visible on the server then let's set the click function so private void awake on the kick button the on click let's add in listener to it and now on this one let's make a function to kick the player so let's go in the kitchen game multiplier and over here let's make a function to do just that so probably void kick player and we're going to receive a yield long for the client ID over here it's actually very simple let's access the network manager the Singleton and let's just call disconnect client and over here we pass in the client ID just like this then over here on this one we just need to know the client ID so let's grab the player data from this index and from there on let's go into the kitchen game multiplayer the incense and let's kick this player so the player data and it has a client ID okay so this is going to disconnect that client however just like this there's actually going to be no visual the client won't be disconnected but it will still look like it's still on the same server so let's add a nice visual and for that we can actually go into the game scene and over here inside the canvas we previously already made over here the host disconnect UI the logic is going to be exactly the same so let's just copy this go inside the character select scene inside the canvas and let's paste it and there you go the host disconnect UI although we just have to do one change over here on this script we are listening to the event and one thing like we saw previously on this scene the character select scene this script isn't going to have the same lifetime as the network manager this UI object won't be destroyed as the network management lives on so we need to do just like we did before we need to clean up this event so let's make a private Droid on Destroy and on Destroy and let's make sure to unsubscribe from this event so let's do minus equals like this although at the same time I'm not entirely sure what is the order of execution you know there's still one more sneaky issue for some reason when kicking a player that doesn't actually trigger the disconnect comeback so the function that we have up here to clean up the list this one is not going to be automatically triggered so let's make sure to manually trigger it so when we kick a player let's click them and then call the same function to update the list okay so let's test okay so here on let's create a game then on this one down here let's join it and now the server doesn't like me for some reason so server is going to kick me and there you go Hostess is connected play again and now I can try joining again and yep it works okay great let's just hand on one more final thing that we made quite a while ago so here I joined then I was kicked then I joined again remember that the server does not reuse client IDs so the client IDs are not sequential so actually what we have here is the server is on IDF zero and this one is on ID of 2 because the one was kicked so it's actually kicked this one a few more times so let's kick and join again so now this one has an ID of three now let's kick in and join again so now this one has an ID of zero and this one an idea four so now if we hit on ready and if there go there we have our error we can see where this area is being spawned over here on the player any outputs this code that we wrote quite a while ago so it's using the owner client ID and the spawn position list only has four positions so we're here instead of positioning the players based on the owner client ID instead of that let's use the player index so let's go into the kitchen game multiplayer and let's get the player index and pass in the owner client ID okay so let's see okay so create so this one now has index 0 and let's join and on this one instead of being kicked and let's actually leave voluntarily and let's join again so now this one has index 2 and let's leave join again that one has index three leave join again okay so now we have index 0 and 4 and if we both hit on ready and if they go it does work and they are positioned perfectly exactly where they should be all right awesome now there's just one more thing we need to clean up which is over here let's create a game over here on let's play let's join okay let's hit on ready and both start playing the game and yep okay everything seems correct and on this one I'm going to disconnect and there you go we have an error we can go and see where it is and if it's right in here so it's the same problem as previously we got an event but the kitchen game multiplayer this one is leaving longer than this one so we need to make sure to unsubscribe from these so as usual prep void on Destroy and on Destroy let's unsubscribe from this event let's see where else we are adding listeners over here on the character select player the character select already has the same lifetime but the this one we need to unsubscribe so the same thing proud void on Destroy and let's unsub from this event okay I think those are the only two so let's test so let's create the game on this one let's join set is ready and let's go inside and over here yep it's working now let's go outside and if there you go no more errors alright awesome okay so here we created the really nice character select Scene It supports joining players then each player can customize their color the server can kick the players and each player can set their ready State when they are already the game finally begins so with this done the next thing we really need is handling the lobby so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to create our own Lobby scene where the players can create games and then other players can browse the games and join them okay so here on let's build their own Lobby now this is a tool that I've covered in detail in a previous video so pause the course right now to go watch that one in there I cover pretty much everything about this tool here I'm focused mainly on using the 2 only then explain every single thing so I will assume that you've seen that video okay so first of all we need to install the package so let's open up the package manager let's go over here on dn2 registry under all and let's look for the lobby so here it is let's go ahead and install okay there it is it installed and over here in the dependencies it also installed as a dependency of the authentication package okay so that's great let's close this window and right away we see this window basically in order to start using Lobby we need to enable it in the Unity gaming services so that means we need to go on to the project settings but before we do let's make sure we are signed in so up here on the top left corner there should be a button and it should be with your account if this button is disabled then says sign in then go ahead close Unity open the unity Hub and make sure you are signed in there okay so with that then you can click on this button to go to the project settings or just manually go into edit project settings and out go into the services now over here we can create a brand new ENT project or we can use an existing one so if you already have one you can link it or you can also go to the dashboard and create one there so here I am on the NT dashboard I'm going to go and select the projects and create a brand new project I'm going to call this kitchen chaos multiplayer and nope this one does not Target children okay what's great all right the project was created great so now back here into Unity we can select the organization and then go ahead and select the project so I'm going to select the one that I just created so kitchen chaos multiplayer and just go ahead and Link the project ID alright so the project has been linked that's great now let's go back here onto the NT dashboard and we need to enable Lobby so let's make sure the project is selected and then let's go over here on the left side to multiplayer then let's go into the lobby and over here let's click the button to set up Lobby and then we've got a bunch of basic steps so first of all link DNT project and yep we already did this then install the package already did this and finally turn the lobby on so let's click and turn it on and there you go so let's go on next and if there you go we are finished okay great some Lobby is now enabled with that let's begin using it and again here I'm going to assume that you've seen that Lobby video and you have a basic idea for how the API works here we're just mainly going to use it so first over here on the lobby scene let's begin by creating a new empty game object currently the kitchen game lobbying let's reset transform and let's make a script for it so a script with the same name and let's go ahead add the script and open okay so now here on this script we're going to handle everything related to our lobby and since we're also going to need to access the lobby when we enter into the character select scene in order to get things like the unlocking and the code in order to do that let's make sure to also Mark this object as don't destroy and load so let's make a private way to wake and over here let's make sure to set don't destroy unload and don't destroy this game object okay so that's great then since we're doing this we also need to mark it for cleanup it's over here on the main menu cleanup button let's make sure to destroy it so let's also implement the Singleton pattern so if I can hear make a public static kitchen game Lobby for the instance would they get any private set on a way to set this one equals this okay so over here on this side let's do the exact same thing so let's go into the kitchen game Lobby and if this one exists let's clean it up okay great so now over here let's first begin by initializing the unity services so let's make a function to do just that so initialize Unity Authentication here we first go into Unity Services which is inside unity.services.com and let's call initialize async then as usual for these functions these are meant to be available so let's wait and since we are calling it with a weight up here we need to make sure to use async okay so that is going to initialize and we're going to come with appear on our way all right so that is going to initialize Unity services and afterwards let's go inside the authentication Service so it's this one inside Unity Services Authentication let's access the static instance and let's sign in anonymously and once again this one is also an awaitable column okay great now one thing the way we have set up this object is it won't be destroyed and then recreated whenever we go back to the lobby but you cannot initialize the services more than once if we do then we're actually going to have an error so we need to make sure we only run this once and for that we can access the unity services and over here we have a state and there's a bunch of states like for example we can check if it is not initialized so if this one is not initialized so if it is not initialized then we're going to initialize it okay that's good now one more thing which is Lobby Works based on the player ID that the authentication Service generates and if we run multiple Builds on the same PC then we'll actually all have the same player ID so if we do it just like this we can actually test with multiple builds because they're only going to have the same player ID so some of that we can basically initialize with a different profile every time so appear on the initialize async for the entity services this one takes a initialization options so let's create that let's create a new initialization options and on this object we can then call set profile and we can pass in some profile name so basically we want to pass in a new unique name every time just so we can run multiple business for testing so in order to get a new name let's just do random.range and generate a random number this one requires a string so much just do two string like that okay so now this will initialize with different name every time okay that's great so with this we can test with multiple builds so this handles the authentication part now let's end on creating and joining in lobby so over here let's make a simple function let's make it only because we're going to college from the UI script void call it create Lobby and to create on Lobby we're just going to need a string 14 Lobby name and then a Boolean for is private in order to create another pirate or public lobbys then over here the way we create we go inside in lobby service the instance and we call create Lobby async this one takes in a Lobby name so let's press in the unlocking name then it takes the maximum number of players and we actually already defined that over here on the kitchen game multiplier script we've got a content for the max player Mount let's just make this one public so now back in here we can go into the kitchen game multiplayer and grab the max player Mount okay and then for the is private we need to create some options so let's create some new create and Lobby options and over here we can set this private onto this is private okay so this function is going to actually create a Lobby and as usual this one is available and this one is going to return in lobby when it completes so let's first of all put in a weight and we want to keep track of which Lobby we are either creating or joining so let's go up here in order to Define that so let's make a private of type Lobby so it's this one inside Unity services and lobbies models so this is going to be our join Lobby so this Lobby that we have joined and as soon as we create one let's set this one equals this and since we're using a weight up here we also need to mark it as async okay great so this is going to create the unlocking and now one thing that I mentioned in the lobby video which is of these function calls all of these can throw an exception so in order to make sure our game doesn't break we need to put this inside a try catch so let's put a try and then let's see we catch we're going to catch a Lobby service exception and if we have it let's just do debug download unlock on this okay so this is going to create our lobby and following through with our connection flow after creating Lobby we want to join our game we want to actually start the host so you can inspect over here the testing buttons that we were using previously so we can't start host and then load the scene so let's do exactly this over here after creating a brand new Lobby let's see exactly this okay so this will create a Lobby and then we're going to start host and start going into the character selecting before we can test we also need some way to join in lobby so let's also make that function so a public let's call it quick join and over here we're going to use the super useful quick join function so the lobby service let's access the instance and over here let's just do the quick join Lobby async and as usual let's await this which means we need to mark this as async and this one is also going to return the joint Lobby so join Lobby and again we need to put this inside a try catch for the lobby service exception okay so with this we joined the lobby and then for externally joining all we do is start client so let's do exactly that exactly the same thing okay great so with these two basic functions we should now be able to create a Lobby and then join it so for testing that out let's make a nice UI window over here on Lobby scene let's go into the canvas create an empty game object call this the lobby UI let's stretch it to occupy everything so put zero on everything now let's make some proper buttons so inside let's create a new button and this is going to be the main menu button and let's anchor it on the top left corner so something like that push it up there and push it like this then for the button itself let's make it in a dark gray and inside for the text let's put it in bone text in white and say main menu okay that's the main menu button great now we want a button to create a Lobby and want to do a quick join so let's make those two let's simply hit this one for the create Lobby button another one for the quick join button now let's just position these buttons so let's put it over here a bit off to the side some like this and let's modify the text inside of them so this one create Lobby and on the other one let's do a quick join okay we have these buttons and we also normally need the testing Lobby y so let's hide that one okay there you go it's disabled now let's make the script to run this so let's create the new c-sharp script we'll have UI let's go ahead and attach the script and open and now here let's make the usual things so let's grab our buttons so a serialized film private button for the main menu button and another one for the create Lobby button and finally the quick join button back here in the editor let's drag our references so the main menu the create Lobby and also the quick join okay great so now here let's make our Behavior so on awake let's add some listeners so the main menu button the on click let's add a listener and for this one's very simple we just go back to the main menu so we just even loaded it up and load so we use load and upload Network because over here we still don't have an active connection so let's use load and for the scene let's go back into the main menu okay that's it now for the other two buttons so the create Lobby and the quick join for the create Lobby let's go into the kitchen game Lobby the incense and concrete Lobby this one takes in lobby name and then is private or not so for now let's just send in lobby name and then it's private let's put it as phones so we can join with quick join and on this one same thing kitchen game Lobby instance and let's just do a quick join okay great so these buttons should be working let's test okay so now on this one up here let's go ahead and create a Lobby and if there you go it does go into the character selection screen okay so that's great and on this one down here let's hit on play and now let's do a quick join and if there you go they both connected all right awesome now I should point out one very important thing here which is right now this is actually not really joining this specific game if we made a second Lobby it would still join on the exact same game the reason for that is because we are still hosting and connecting to the same IP on the same port if we look on the entity transport in order to connect to an IP you need to set it here we then set anything so we are still hosting on localhost on this board so if we made another Lobby it would still be hosting the exact same IP exact same port so exact same session in order to make an actual separate instance of a game we would need to host on a different IP and then we would need to use that IP in order to make the right connection or the alternative is to use relay which is what we're going to implement in the next lecture so I just wanted to quickly point that out right now right now this is creating separate lobbies but not separate sessions that will be handled when we set up the relay in the next lecture okay so like this we have the basic create and quick join working now let's expand upon it and make a window to Define some options when creating a Lobby so back here in our lobby scene let's create an empty game object call it the lobby create UI inside let's make a UI image let's name it the background let's make this one stretch to occupy everything let's put it in black and let's stretch out the apparent a little bit so let's size it to occupy something like this okay great let's put it on X of zero all right now inside let's also make a simple text just a nice label so for this one let's just say create Lobby let's put it in bold Center middle no wrapping and width and height on zero zero okay so the usual setup then we need some way to input the unlocking name so inside let's create an input field let's call this the lobby name input field let's move it a little bit up there and over here on the inspector we can play around the input field and let's put it on a dark gray something like that then let's go inside it inside the text area and here for the placeholder I actually don't like this so basically there's a visible intertext before you actually input something but personally I don't really like this so I'm going to delete this and for the text let's just put it on white and now if we go back into the unlocking name input field down here we can set default text so let's just say Lobby name okay let's just make it a little bit bigger something like this okay great so we have a Lobby name and then the other option is we're only just creating as either a public or a private lobby so let's make two buttons for that so let's create a new button let's call it create public button inside let's say create public let's put the usual thing so in White in bold and for the button put it in a dark gray something like this okay so we've got the public button and then let's make another one for create private so they create private button inside let's make create private okay so those are really all the settings we need in order to create the lobby and let's just make a close button just to be able to go back and close this create UI so let's create a new UI button and for this one let's put it up there so let's anchor it on the top left corner instead of using the UI Sprite let's use our nice cross Sprite let's make sure to put it on something like 44ing and get rid of the text inside and name this the close button okay so that's the basic layout we need now let's make the square to run this so let's create our script with the exact same name while we create UI let's attach the script and open okay so now here it's going to be super simple first let's grab our input field and our buttons so a serialize field for the button so we have the close button so this is actually of type button then we have another one for the create public button and the create private button and then we also have the input field so for that one the type is actually the TMP input field so it's this one here don't make a mistake we use text mesh Pro so it is not the regular input field it is not this one it is the TMP input field so this is the lobby name input field okay we have all of our fields over here let's set them so the unlocking name input field and the create public button the close button and the create private button all right great so over here the logic is going to be super simple so on private Wide Awake over here on let you send listeners so on the create public button let's unclick let's add in listener and for the listen we're going to go into the kitchen game Lobby on the instance and let's create a Lobby and for the lobby name let's use the lobby name input field let's grab the text from there and for these private this one is the public button so let's set it as false and for the other button very simple so the create private button for this one just set it as private all right then for the close button so the close button for this one we want to hide this window so let's make the usual show hide function so private void show and the product void hide and the game objects that active into either phones and appear into true then as usual in private start we're going to start off hidden and when we press the close button let's also hide it okay so that's it now for here on the lobby UI we just need to show that so let's actually make another reference of type Lobby create UI for the unlock create UI and here in the editor let's drag that reference so on the unlock UI let's write that one and then super simple over here on create Lobby let's just go into the library create UI and call show so we just need to make that one public so here just make this one public okay that's it super simple so here we just called the exact same function okay great now if we do end up creating a private lobby we need to be able to show the in lobby code so that people can actually join so for that let's actually go into the character select scene let's go into that one and over here for this one we need some element to say that science actually go into our generic character select UI and inside let's create a new text object let's call this the lobby name text and let's put the usual setup and let's actually hide this host disconnected window just so we can actually see that so we're here in the hierarchy and let's side down okay so we have the lobby name let's put it in bond maybe a little bit smaller so 24 and the usual setup so width and height of zero Put It Center down the middle disabled and appear let's Anchor It To The Top corner so let's anchor it to the top and this one is going to say something like Lobby name and then in lobby name okay so that's all we want and then let's duplicate this one and for this one down here let's name this in lobby code text and over here same thing we're going to send Lobby code and then say some kind of code okay that's good so now let's open up this script and let's first of all add our references so the text mesh Pro you're going since we're working the UI for the lobby name text another one for the lobby code text over here let's drag our references so the unlocking name and the in lobby code then all we need to do is set it up so let's do it over here private void start so on start we need to get the actual Lobby so we go into the kitchen game Lobby the instance and we need the function to get the actual Lobby so let's make this function so over here on the kitchen game Lobby recently just need something to return this joint Lobby so let's make that one so you're probably going to return in lobby get Lobby and we just return our join Lobby okay like this so over here we can grab the lobby and the lobby is actually inside this one so we grab the lobby and over here we're going to assume we always have Lobby since we only connect the scene when we have joined the lobby then on this one let's just go on Lobby name dot text and we're going to set it to Lobby name and then let's go into the lobby and grab your lobby name and then for the code same thing we just grabbed the lobby code so this is the lobby code and the lobby code text okay so that won't show both the name and the code all that's left before we can test it's basically just setting a way to join by the code so let's go back into the lobby scene so let's go back into the lobby scene and over here let's make an option to join by the code so let's actually hide over here on the inspector just hide the unlock create UI so we can log behind it so inside the lav UI on this one let's make one more button so let's push it down here let's name this one join code button and then above it let's make a nice UI input field the lobby code input field and let's set it up the same way so let's put it in Black and down here for the text this one is going to say some kind of code then let's go inside inside the text area and personally I don't like the placeholder so let's get rid of that and for the text let's put it in bold put it in white and put it down the middle okay so now let's just position it so just above there just above the join by code and on that button let's also change the text so join code like this okay now let's make this logic so over here on the lobby UI let's first of all add the reference so the join code button and then let's also add another serialized film this one is going to be once again for the TMP input field for the join code input field then here in the editor let's write the references so the lobby code input field and the join code button okay so now joining by code is very simple let's make that one on the lobby script so we're here on the kitchen game Lobby let's go ahead make a function so we probably Point let's go and join with code and we're going to receive a string for the unlock code and over here we're just going to the lobby service access the instance and call join Lobby by code async and this one takes in a library code so just add a Lobby code and as usual let's make this a weight this one is going to return our join Lobby so let's set that one and if we use a weight we need to use async okay and as usual let's put all this inside a try catch and finally after we join the lobby then it's the same thing as over here so we need to start the client finally we just need to call this function so over here on the lobby UI for the join code button let's unclick let's add in listener just go into the kitchen game Lobby the instance join lobby with code and pass in the join code input field and let's pass in the text okay so let's test okay so here on this one down here I'm going to go into play and let's go ahead create a Lobby and this time let's make it a private lobby okay it created there's the code and now on this one if I try to Quick join and hope there's an error because there are no open public lobbies but now if I go in the code and I write the same thing so wnt 4 F6 and I join with the code and if there you go it does connect and we have our connection all right awesome next let's handle one thing which is lobbies need to send out a heartbeat in order to stay alive by default they won't destroy themselves after 30 seconds of inactivity for example if here I hit on play and I create Lobby let's make it public okay the lobby has been created now let's wait 30 seconds okay 30 seconds have passed now if I click on quick join and nope there are no Hobbies open so we made this a public hobby but it passed 30 seconds so it was automatically destroying so let's make a function send a periodic heartbeat that's very simple so let's go here onto the kitchen game Lobby and let's make a function to handle our heartbeat and we're going to need to run that on our update so let's make a proud void update and we're going to have the handle heartbeat function so let's make this one so privatoid handle heartbeat so we have this function and now importantly we also only want to run the heartbeat on the lobby host so let's make a nice Humper function so private ball is Lobby host and basically it's going to be a host if well first of all we have a Lobby so the join Lobby it is not known so if we have the lobby and we go into the join Lobby and we ask it for the host ID if that one matches the authentication Service we access the instance in grab this player ID if it does matches then this one is the lobby host so we're here if we are if is Lobby host if so then let's send out the heartbeat and for now on let's just count down a simple timer so appear on let's make a private mode for the heartbeat timer okay then over here heartbeat timer minus equals time dot Delta time and if the heartbeat timer goes under zero if so then let's first reset it so the heartbeat timer let's set it to some kind of heartbeat timer Max so let's say we want to send out a heartbeat every 15 seconds okay so let's first reset the timer and then let's set out the heartbeat so go into the lobby service the instance and over here let's send the heartbeat ping async this one requires Navi ID so let's grab the giant Lobby and let's grab the lobby ID okay that's it let's test okay so here I'm going to go ahead create a Lobby create the public Lobby and now let's wait for one minute okay it has been over a minute and on this one if I try to Quick join and if there you go it does join alright awesome next let's handle synchronizing some player data like for example the player name so let's go inside our lobby UI and inside let's create a new UI let's make it an input field let's anchor it up top and put it up there let's set it up as usual so the color on pretty much a dark gray let's name this one the player name input field then inside Vortex area as always I don't like the placeholder so I'm going to delete it for the text put it in white put it in bone down Center okay great let's also increase the font size by a little bit and for the player in first field let's say player name just default text let's make it a little bit bigger okay so that's our simple player name now let's handle the script so let's go inside and Lobby y and over here let's add the field so the field for the player name input field here in the editor let's just drag the reference okay so now we have this and now we need to set it and listen when it changes so we need some way to store our player name and for that let's go over here onto the kitchen game multiplayer let's define a field for our player name so private screen for the player name in order to sort it between sessions let's also store it on employ prefs so over here on the awake let's go player name and let's set it so let's go inside the player prefs and let's get a string then we need the key so let's go up here to define a constant so a private constring call it player prefs player name multiplayer let's go let's play your name multiplier so this is the key for our player prefs then let's use it down here so get string of this and then for default value so if there's no key recording if not then let's just default to saying player name and then let's add a random number so let's go random.range so actually that's inside Unity engine.random.range let's randomize a number between 100 and a thousand so just get a random number just like this okay so that is going to either get or generate a brand new player name now let's make two functions to get and set so let's make it over here a public void or a public string rather let's call it get the player name and we're just going to return return the player name and another one so a public void set player name and this one we're going to receive a string for the new player name and just set this dot player name equals this player name so we set it and then we need to update it so on the player prefs let's set the string on this same key so let's use the content and let's set this player name okay great so with this we have a nice player name defined then we can go back here on the lobby UI so let's go ahead make a private void start and on start let's grab the player name input field and set the text let's go into the kitchen game multiplayer the instance and let's get the player name okay so that won't update the name and then we need to know when the player actually changes the input field so that is actually also pretty simple so let's just go inside the input field and over here there's a comeback the combat is called on value changed this is a Unity event so let's add a listener just like we do with a click and for the listener this one is going to receive a string which is the new text that the player wrote okay so we have this and over here just go into the kitchen game multiplier the instance set the player name to this new text okay so that will now update the current name and it will save any new name the player writes so with that the player name is being set now we just need to show it on the character select scene so let's go to that one so over here on the project let's go on to the character slide scene and over here let's go inside one of these player prefabs let's open it up okay so over there we already have something called ready and let's duplicate it to make another text object put it above name this the player name text and this one is going to say what it is the player name so let's just go into the script here the character slide player and we're going to add a reference to our player name so let's set in this case it's a text mesh Pro we're using a worm option so it's not the you going so it's this one for the player name text here in the editor let's write the reference like that okay so now we need to set this and for setting it over here we have our general update player function so it's over here that we're going to set the player named text.text and we're going to set it to something and for that something we're actually going to start a player name inside our player data so let's go here inside the player data and let's store a public string for the player name and over here we need to override all these so we do an equals on the client ID the caller ID and also the player name okay and down here on the serializer let's also serialize the player name except if you remember from the other video a string cannot be used here if you're only here in the inspector nope the player data must be a no no don't value type A String can be null so a string cannot be used and over here the alternative is instead of a string let's use the fixed string and then the number of bytes this is the length of the string and for a player name let's go with the 64 64 characters that's big enough for a player name so let's go with this one okay so we have this inside the player data and then back here on the character select player on the update we go inside the player data and let's grab the player name then this one is a fixed ring so let's just call to string to convert it to a regular string okay so that's ring so now the visual for the player should have the player name and we are having that over here stored on the player data all we need is really just to set it on the player data so for that basically we need to tell the server our name when we connect and then the server will update the player data which then is synchronized to all the clients so let's go over here onto the kitchen game multiplayer and to tell the server the name let's do it as soon as we connect so let's go down to where we are doing the start client so here we have the start client we are listening to the client disconnect and let's also listen to the client connect so the other one so on client connected comeback let's listen to this one on the server on client connected compact okay we have this one let's create this function so here it is so on this function we have the client 3D parameter so the same as usual and as soon as we connect let's tell the server what our name is so for that we need an RPC so let's make a private void set player name server RPC and this one is going to be a server RPC we require ownership as false then over here we receive a string for the player name and we receive the server RPC param so we know who sent this and as usual let's default it okay great and over here really going to do the same thing that we did down here so here when changing the color right now we're going to do the same thing so let's just copy this code let's go up here into our function and over here let's face the same code so we grab the player data index from this server RPC params okay that's great instead of modifying the color ID let's modify the player name into this player name okay so all that's left is over here when the client connects let's trigger the server RPC and pass in get player name and update it like this okay so that is going to do it for the client but then the server itself also has a name so here when we have the start host we also have this comeback so over here let's also set the player name okay so that should do it when a player connects it will send the server their name then the name is broadcast to all the clients let's just make sure to save the prefab and as always for testing let's make sure we test starting from the lobby scene okay so let's test okay so yep we do see our nice input field so on this one I can click to modify it so on this one let's say I am code monkey and then on this one down here and let's hit on play and on this one let's give it another name let's say Iron Man okay so we got the two names on this one create and Lobby let's create a public Lobby and if there go it does show the player name and on this other one let's do a quick join and joins any of their yo Iron Man and both the names are synchronized all right awesome so here we have all the names in the character sightseeing although one note here if you wanted you could also show these names on the game scene above the players so if you both go on ready right now the game just starts playing and we just have the characters no names but if you want you could also add the names up here but since the players already have different unique colors I think this scene looks best without the names okay so the next thing we want to handle is in labian Lifetime right now the lobby won't stay alive until we end the entire game session but there's really no need for that once we start the game we no longer accept any connections so we should really just clean up and destroy the lobby as soon as the game starts so first let's go here to the kitchen game Lobby and let's make a function to delete a certain Lobby so let's make a public void call it delete lovey and over here it's very simple the same thing so let's go inside the lobby service the incense and column delete Lobby async and here we pass in the unlock ID so let's just check if the giant Lobby is not known so if we are inside a Lobby if so then let's use the join lobby.id and destroy this one once again let's wait for this one then after we await let's clean up the joint Lobby since that one will now be no and in order to use the weight we also need to use async and finally we must put all this inside a nice try catch catch the Wabi service exception and just do a debug download okay that's it pretty simple now let's see what we're going to call this it's over here on the characters like ready script here we have the playwright dictionary where the player tests if all of the players are ready and if so then loads the game scene so before doing that let's just go into the lobby so the kitchen game Lobby the incense and let's delete the lobby okay so that handles the cleanup when the game starts for something similar which is going to be when we leave the unlock manually for doing that we also need to make sure that client leaves the lobby so back in the kitchen game Lobby script over here let's make another function so this one public void leave Lobby and this one just go into the lobby service the incense and this one we call remove player async this one takes a Lobby ID so that you join lobby.id and then it also takes a player ID so let's go inside the authentication Service access the instance and grab this player ID so this will remove this player from this Lobby so as usual let's do the same thing so await async okay so just like this pretty simple and as to where we're going to leave it is going to be over here on the olive UI so we have a button to go back into the main menu so when we do let's just go into the kitchen game Lobby the instance and let's make sure to leave the level okay so finally the last possible scenario for leaving your lobby is actually if the player is kicked so let's make a function to Kiki player back here on Lobby it's going to be very similar so let's actually copy this and let's call this kick player and inside we're going to receive a string for the player ID then over here we call the exact same function except instead of using this player ID let's use the one that we received over there and of course for kicking we're not leaving the lobby ourselves so let us not do this instead of testing if no Lobby is not known we're only going to be able to kick players if we are the lobby house so Islamic host then we kick this player okay so now for calling this function it's over here on the character select player script we've got our kick button when we kick we get the player data we kick the player from the multiplier so from the netcode itself and then over here we also need to kick them from the lobby so let's go in the lobby instance keep the player and now we need a player ID so the obvious question how do we get that and the obvious answer is the same thing that we did which is let's just store it over here on the player data so let's go here and the player ID is also a string so let's do also a fixed ring so player ID and let's copy all these okay just like this then on the kick function we can go inside the player data and use the player ID all right now we really just need to set this so for that let's go in the multiplayer script and over here we're only just going to do the exact same thing that we did on the set player name so let's copy this RPC except instead of set for your name that's going to be set player ID let's receive a string for the player ID and we're going to set the player data dot player ID okay so that's what we modify and let's just call it when we set the player name so when a client connects let's send this in and for the player ID let's go inside the Authentication let's go inside the instance and grab this player ID so we set it over here when we set the pointer name and same thing up here when we set down okay so let's test okay so starting off let's create a Lobby let's make it a public Lobby and first of all let's just start playing just like this and there you go here we are playing there are no errors okay so everything is working perfectly now on this one down here if I try to do a quick join and nope it does not find any lobbies that's because this one was now destroyed okay great okay now here let's try to create another Lobby then on this one let's do a quick join and on this one let's get them from the lobby and if there you go that does work and now if we try joining again and yep it also still works okay great so all the logic is working perfectly now one issue we have right now is that our lobby isn't really very responsive there are lots of actions that take a little bit of time but that is not visible to the player so let's just add some nice messages previously we already made this window the connection response message UI it shows a message and a close button so we could just make another window just like this one or we can simply reuse this one let's reuse it just so we don't end up with tons of different windows and first of all let's actually put both these windows let's put them on top of the actual Lobby UI okay so like this all right so now let's rename this one to just Lobby message UI so a bit more of a generic name and Lobby just because this object only exists over here on the lobby scene so now that we've renamed the game object let's also rename over here to the script so only so rename to Lobby message UI and obviously this is going to have some errors we need to make sure that the script name actually matches the file name so here inside let's just modify the class name like this okay the name is correct now over here we are showing this message based on these events so it simply make a bunch more we want the window to show when trying to create a Lobby so let's go over here onto the kitchen game Lobby and let's make an event to fire on that so a public event event handler and for this one let's using system okay so in this event let's call it on create Lobby starting so when we start creating the lobby another one on create Moby failed okay so we have these two events also by the way since we added using system now over here we've got a ambiguous reference between the UNT engine random or the system random so over here we can solve this by just using the complete name okay great so let's go down to where we are creating the lobby so let's see the function over here to create the lobby again remember that these are weight functions which means that this code to create and Lobby isn't instant it's actually going to contact the UNT server in order to create Lobby so this is why we need a visual for the player because this is not instant so before we try to create the lobby let's fire off the oncreate Mobby starting so envo with usual this and even arcs okay so we try to create a Lobby and then if we succeed we're going to load the other scene so there's no need to post any message but if we do fail then over here let's post a message so let's use the oncreate lobby field okay these are the two basic events so now back here on the unlock message UI and let's listen to them so let's go into the kitchen game Lobby the instance and first of all the on Lobby starting and as usual let's rename this to give it a proper name so kitchen game Lobby on Lobby starting and the other one which is the oncreate lobby failed let's listen to this one as well okay we have our events and let's also make a generic function in order to show a message so here a private void show message going to receive a string for the message and then we're just going to call show and set the message text Dot text into this message so now up here we can simply show these so do the exact same logic so if disconnect reason is none then let's call show message then let's show the general message fail to connect and if not if we do have a disconnect message then let's show that disconnect message okay great so now the code is a bit simpler so we just have the original message so over here on let's just say so this one is on the create Lobby starting so let's say creating Lobby and on this one up here fail to create Lobby okay so that's great that handles those messages the other place where we want to show some messages is on the quick join so let's do the same thing with two events so let's make an event and one let's call it on join starting so this works for both the quick join and the other ones another one on quick join fails so let's go down and do the exact same thing so let's see over here on the quick join so on join starting let's invoke this event with this and eventars.empty okay we have our event and then if we do join then we're going to download the other scenes underneath and it's over here so on quick join film like this let's also put the same thing over here on the onshine with code so on joint start and then let's make another one so on join failed we'll just go up here to Define this one so on regular join failed okay great so over here let's just listen to those events so the usual thing so the incense let's go with the on join starting let's listen to this one then the other one is the on join failed and finally we have the on quick join failed okay let's rename all these okay we have one of our events now for these messages so on join starting let's just say joining Lobby then this one up here failed to join Lobby and on this one up here on the quick joint failed could not find a Lobby to Quick join alright so that's it here we have all of our messages Let's test okay so here if we try to create the lobby let's go ahead create on public and there you go create a Lobby and it takes a little bit and we have a nice visual so that's great and now on this one let's go ahead click on play and let's go ahead with the quick join and there you go join Lobby connecting any update connects let's see the other ones for fail to join so if I exit both lobbies and if I try to Quick join and there you go it did work it simply fired off the error that's because over here in unity this one throws an exception and UNT treats that as an error so it automatically pause the game but in the build this is not a problem since it one stops over here if we hit on play going to Quick join join Lobby and nope could not finding a Lobby to Quick join and if I try to join by code it also does not find this lobby with this code alright great so just with this our lobby actions are now much more responsive okay great so finally let's do the most obvious Lobby feature that is still missing let's simply enlist all of the available Lobby so the player can choose which one to join so for that first let's go over here onto the kitchen again Lobby and let's make the function to action list of the lobbies so let's go up here make a simple function so for avoid list lobbies and in order to enlist on the lobbies all we need to do is do a query so let's go into the lobby service instance and let's call query and lovies this one takes a query Lobby's options if you don't include this and it will simply show all the lobbies but right now let's actually add a filter let's only show the lobbies that are available so let's not show the ones that our phone so we're here let's make a querying all of these options and let's construct a new object of this type and inside we've got the filters so let's create a new filters this one takes a list of query filter so now inside we can create a new query filter and for this one for the field we only want the ones with the Velma slot so let's go with the Velma slots then for the value we want all the ones that have more than zero so let's go with zero except this one actually is a string value not an end so let's just put this as a string okay and finally for the operation we only want the ones that have more than zero so let's use the GT which means greater than so this will only show of the lobbies that I have available slots greater than zero okay so just like this and over here let's use the aquarium Lobby's options and as usual let's await this and this one we can see what this returns so this section we're going to return on a query response so let's grab the query response and also since we are using a weight up here we need to mark it as async okay so we grab the query response and now inside over here we've got the results and the results is in list of Lobby okay now in order to show them on the UI we're going to fire off an event so let's do that let's go all the way up here make another event for this one let's come with on Lobby list changed and in the event we want to pass in the list of Lobby so let's make a public class online let's change event arcs let's extend event args and inside let's have a public list of Lobby and just call it the lobbying list and now the event is of this time okay great so over here when we have the enlist navies we get the query and then let's invoke this event pass in with this and create our new event arcs and inside we have the unlocking list and we pass in the query response to our results okay so just like this and as usual let's wrap this inside a try catch so try and the usual catch the lobby service exception like this and do a debug download okay so this is going to enlist our love isn't far off the event when we have new list and let's also periodically call this function in order to make it automatically refresh so for that let's go up here onto the update we're going to have another function let's say handle periodic list lobbies let's make this function so on this one we're going to count down a timer so it's called the list Lobby's timer we're going to count it down by time dot the time let's just Define the timer all the way up here just where we Define the heartbeat timer so as usual a private mode for this okay we have this timer so we count down the timer and the usual thing so if it is under zero if so then let's first reset it so put it to some timer Max let's define it in here the timer Max and let's say we want to refresh we don't need to be too specific so let's say maybe three seconds so we reset the timer and then simply call list lobbies which in turn that one is going to fire off the event which the UI won't listen Okay so that's great although here this is going to continue on listing the lobbies even when the player has already joined the lobby so that's a little bit wasteful so let's not do that so we're only going to run this if the joint Lobby equals no meaning if the player has not yet joined the lobby let's automatically refresh but as soon as they do don't bother wasting and also one more thing this is actually going to throw an error if we run it right away that is because over here the authentication this one's signing in this one is going to take a little bit of time so on the very first update it will not already be signed in so we can just simply go into the authentication Service and let's just check is signed in so this is only going to miss lobbies when we are signed in okay great so that's the function form listing of the lobbies now let's just make the UI so we're here in the editor let's open up let's just hide our message window we don't need that and for the lobby one let's go inside of it and over here let's create an empty game object call this the lobby list container and now inside it let's make a new UI button call this the template and inside for the text let's give this a better name so let's say the lobby name text and now let's set it up visually so let's make it a little bit bigger and for the lobby name let's actually anchor it on the left side just move it to the left by a little bit let's put it involved maybe something a bit smaller maybe 22. let's put it in white and for the one the background let's put it in a dark black and make it a little bit bigger so let's say 40 or 50. okay so like this we have our button and this is going to display our lobby name okay great now for positioning these let's go ahead and add a vertical layout group over here onto the container and you can also put the width and height both at zero okay so let's position it somewhere around there and basically we're going to dynamically spawn the template so something like this let's just increase the spacing by a little bit maybe 10 okay just like this let's also make a background for our UI so let's create a new UI image let's put it all the way up there and let's scale it something like this maybe put it in white but a little bit transparent okay so that's just a nice visual background also for another visual thing over here in the game the background sound looks a bit odd so you could use a solid color or let's just simply actually go into the main camera so that's what the camera can see and let's just move it up a little bit so over here on the one let's rotate it something like this just so we have a nice gradient okay so that looks good now let's go over here on to the unlock UI script and let's begin by adding references to what we need so we're going to need a transform for the lobby container another one for the lobby templates so now here let's drag our references so the unlocking list container and the template okay and now let's make a simple function in order to update that list so private void call it update lobbying list in order to know what lobbies we want to spawn let's receive a list of Lobby and it's this one inside Unity Services Lobby's model okay this is the unlocking list and on start we're going to start off with an empty list so let's call this with an empty list then we're also going to want to show it on that event so let's go into the kitchen game Lobby the instance and on the unlocking list changed when this one happens when this one happens let's call update login list and pass in the E Dot Login list okay great so now we just need to make this function and here we're going to do the usual setup that we've done so many times on the single player course so let's first handle the cleanup so let's do a for each transform child in the container so that is the lobby container so once I go through all the container let's see if this one is a template if child equals the template the lobby template if so let's skip this we don't want to destroy the template but if not let's destroy and we're in destroy the channel.game object okay so that handles the cleanup then lets you wait for each Lobby in the unlocking list so we second through these let's instantiate our template so the unlocking template and this one is going to be our lobby transform then first thing we want is to actually enable the template so on this one set active into true which also means that we need to disable this one in the beginning so up here on the awake let's set the template game object set active into false okay so then hides the template and over here we are showing it alright so now all that's left is to pass in this Lobby onto this transform so let's make a script to do that let's create a brand new sharp script for the lobby list single UI let's go ahead and select the template and let's say the unlock only single UI so right there also importantly make sure you add it to the right template basically these other ones don't matter those are just to see the positioning so if you want you can even just clean this up just make sure there are no mistakes so there's only one template this is the one that is selected over here and it's on this one that we have the script so now here on this script pretty simple we're going to have a public void in order to set my Lobby and we're going to receive a Lobby object so Lobby let's receive this one and store it so if you're a private for the lobby and do this not Moab equals this Lobby then for the single for this one we're going to want to update the text and then humbly click so for the text let's go up here at a serialized field private text mesh Pro ugly for the lobby name text okay now here in the editor let's drag the reference so the unlocking name text let's drag this reference on there all right and then for the button since we already made this template this one itself as a button what's your pride void awake and on awake let's get component of type button and when we click let's set an unclick add in listener and we're going to want to join this Lobby and also by the way up here we are going to want to update the name so the lobby named text.txt equals this lobby.name okay great and finally for joining we're going to go into the kitchen game Lobby the instance and let's join Lobby and also by the way over here we need to do it by the ID that is because for public lobbies when the enlist Lobby's function calls when that one list on the lobbies the lobby.lobby code this one is actually going to be known so you cannot join a public Lobby through that list by the code we need to join it by the ID so very simple just over here let's make a function exam like the other one so exactly like we have join with code and let's join with ID and we're going to receive a string for the lobby ID and then instead of join live by code join Lobby by ID and everything else is exactly the same then over here let's just use this function and pass in the lobby.id finally back here on the update login list when we grab the unlock transform we need to get the component of our lobby list single UI and let's best in set Lobby and pass in this Lobby also by the way up here when we instantiate we need to instantiate inside the unlocking container all right so let's test and up here we are so it only starts off as empty because there are no lobbies now in this one let's go ahead create a Lobby let's make it a name so my Lobby name and let's go ahead and make it public and it created and if there you go that one did update so we now see it on the list and now if I click on it if there go it does join the lobby okay great now it's also a test to make sure this one only shows lobbies that have available slots okay so here I have a bunch more builds so on this one let's play and you producing Lobby let's join it and if there go joined now this one let's go ahead we do see it and for this one for joining let's joint with a quick join and if there you go everything works perfectly and on this one if I go on to play and nope don't Lobby does not show up the game is now full so it does not show and just one thing that I forgot a while ago over here on the character slightly why we need to make sure to leave the lobby when we go back to the main menu so here for the kitchen game Lobby instance and let's make sure to leave the lobby so now here we are in the lobbyist phone so it does not show up over here now if one of these if we leave and if there go that one left this slot is now available so now this one can indeed join all right awesome okay so here we added yet another extremely important feature to our multiplayer game we added the lobby so that players can create games and other players can join them now like I mentioned one thing we still don't have are different sessions right now all of the lobbies are being created on the same IP same port so let's solve that by implementing int relay in the next lecture hello and welcome I'm your code monkey in this lecture we're going to set up our project to use Unity really this is how we can make our game easy to play by not requiring the players to handle anything to do with port forwarding or firewalls by using this we can easily connect any two players anywhere in the world and it all works seamlessly under the hood okay so here on let's move into relay which is actually pretty easy but before we do that let's actually fix one thing that I forgot in the previous lecture if we are playing the game and over here let's create a Lobby and then I just go into ready and go into the game State and up over here we have an error it's a missing reference exception any of it's right here on the unlock UI script for updating the 11 list once again the issue is the same that we already saw which is because the listeners basically this object is destroyed but the kitchen game will be that one continues so let's clean up the event so let's do private void on Destroy and when this object is destroyed let's make sure to unsubscribe from these events so from this one do minus equals okay great also the other one where we used events was on the messages so over here on the 11 message UI we are listening to a home bunch of messages so let's also unsubscribed from these we're already unsubscribing to that one so let's just unsub from all of these so just do minus equals on all of them okay so that handles that problem although actually this error is caused by something that is actually not supposed to happen the issue is because it was still trying to update the unlocking list even though we were in the game scene now that is not correct we should not be refreshing the 11 list when we are already playing the game so we're here on the kitchen game Lobby script let's scroll down to where we are handling the periodic list lobbies and over here we are enlisting if join Lobby is known and when we go into the actual game when we do that we're actually destroying the lobby so this one becomes no so that is why on the game scene this one is still running but we don't want that so let's make sure this one only runs if we are on the lobby scene so super simple let's just add scene manager let's get the active scene and let's compare the name and let's compare with the unloader.scene and we only want to run this on the lobby scene okay so just like this we only want to listen lobbies if we are on the Olympic scene so let's test let's hit on play Let's create a public Lobby let's go as ready and go into the game and now play any of now everything works perfectly okay great so now let's actually handle the relay again I have a dedicated video on relay you can watch that if you want although the relay is super simple so here I will uncover pretty much everything that I also covered in that video if in the future you forget how it really works you can either come back to this lecture or just watch a channel on video first thing we need is just install the package so let's go into the usual package manager on DNT registry under all let's wait for it to fetch and now let's find the relay package so here it is a really currently version 105. let's go ahead and install all right the package was installed now we need to use it so just like we did in lobbying let's go on to the NT dashboard and first of all make sure you are selecting the correct project then over here on the left side let's go into relay and let's go ahead and set up the relay link DNT project we already did that so next install the package we did that next and now here on let's turn it really on if there is done next and yep we are finished okay great so the relay is now set up we can now begin using it and basically the way we use is first we need to allocate the relay and then we need to use it before we start the net good connection so the way we set up our game is we set up the connection immediately as soon as we create a Lobby so let's go then let's go to the create Lobby function so here we are we created a brand new Lobby and we start the host right away so we need to allocate the relay before we start the host so over here let's do that let's make a function to allocate the relay so a private void let's call it allocate relay and now inside here we are going to go inside the relay service also by the way sometimes Visual Studio might not update so just go ahead close it and let's reopen it again and over here if we go inside relay service here visual studio now this thing you we need to add using Unity Services now really so let's add that then here let's access the instance and call the function to create an allocation async this one just requires an end for the maximum number of connections so in our game we already Define the max number of players so let's go into the kitchen game multiplayer and over there we have the max player Mount although importantly over here for the connections it is actually minus the host so we want four players that is what we have here on the maximum wire Mount so mine is the host let's just do minus one and then if you want optionally you can set a region or or the relay itself on the side of the region so let's just let them decide okay so this one is going to return an allocation so allocation so it's this one inside Unity Services relay modeled so this is the relay allocation and as always this one is an awaitable so it's a weight and async okay so this is going to allocator relay and now just like with the login let's put this inside a try catch just to make sure the game doesn't crash so catch and let's cash for anything relay service exception if that happens let's just do a debug download okay great then we basically want to get the allocation so when we have async we can't directly return an allocation here when working with async we must return something tight task now this has nothing to do with unity itself this is regular c-sharp code so in C sharp when using async and a weight we need to use tasks which as you can see you can inspect these functions see they also return a task and inside an allocation so this is how you work with it so over here let's make task and return allocation and then so we allocate it and we return this allocation in case we have an error let's just return the default and also up here we need to make sure to include system threading.tasks okay Sergio so we have this nice function to allocate really so now over here on the lobby let's just call the function and locate our relay and we made it async so let's also await this okay so this is going to allocate our relay and now the reason why I made it return the allocation is because we're going to need it after we allocate we need to actually generate the code in order to be able to use it another reason why I made it return an allocation is because we need the allocation in order to set the ND transport so the way we set it to use the real way is we go inside the network manager let's access the Singleton and from the Singleton let's get the transport attached to it so once you get component of type Unity transport this one right here so inside Unity netcode transport CTP then on the transport we've got a function set relay server data and this is how we can pass in data so let's make a new of this type sets relay server data so let's add this one and over here this one as you can see it takes an allocation so that is why we need over here the allocation for the Relay so let's grab the allocation and location we grab this then we use it over here and the next parameter is the connection type and by default TNT recommends using dtls so this is some type of encryption all right so that's it so now when we call start host it is going to start the host and start the connection going through this relay so this handle is over here the created host and how we join the relay is we have to join through a code so let's generate a brand new really code based on this allocation so let's make a function for that so private void let's call this get relay join code and inside we go inside the relay service grab the instance and we get the join code async and this one as you can see it takes an allocation ID so let's receive a parameter and location and location and over here we use the allocation.allocation ID okay so this one is going to return a string with our relay join code so string for the Relay join code and we get this and as usual let's await this and this one is async okay great so you have this one and then let's do it just like we did so let's return this really join code so let's make it return a task of type string and then we can just return the relay join code now as usual let's put this inside a try catch so let's try and let's catch a relay service exception once we debug download on E and we have to return something so let's just return a default okay so now this function gets us a really join code so now in here after we get the allocation let's get a string for the Relay join code and we get really join code and pass in the allocation and let's make sure to do this on no wait okay great so that's pretty much all we need over here on the create Lobby so we allocate the relay we get the relay join code we set up the NT transport to use this really and then we start the host so that's all great over here the next thing we need is some way of joining the relay through a code so let's make that function so private drawing let's call it join relay and over here let's go inside the relay service the instance and we join allocation async so this one takes a string for the join code so let's receive here this ring for the join code and we use the join code this is how we can join it really and you can note how this one returns a join allocation so that is the same type of allocation that we're going to need in order to set up the network manager UNT transport so let's also make this function return that so let's return a task of type join allocation and as usual let's make this async and on this one let's await and the usual try catch so this one returns a join allocation and we're just going to return this and over here return the default all right so that's this function we pass in a really join code and then it joins the allocation so then let's go down here to where we are joining so for example over here on quick join so we first joined the lobby okay great then afterwards let's join the relay so let's call join relay by code and over here obviously we need the join code but let's worry about that in a little bit so this one is going to return a join allocation so join allocation we await this and we get that and then with this allocation we can do the same thing that we did here in order to set up the NT transport so we just paste this function instead of using the navigation we use the join allocation okay so that's it this is all we need in order to join through the relay now the obvious thing is over here we need the relay join code so the big question is how do we get it and actually that's very simple we're going to use the lobby in order to share the relay join code so let's go up here to when we are getting the allocation getting the railing joint code and let's just set the Rimley code as part of the lobby data so over here let's just go Indian Lobby service the incense and let's call the function update and Lobby async so we're going to update the lobby data this requires nobody ID so let's use the join lobby.id and then for the update Lobby options let's create a new object of this time and over here we can update all of this type and let's update the data so let's make a new one of this time so this one takes a string and a dictionary let's add a brand new entry to this dictionary and first of all for the key let's define a key and as usual let's not Define it over here so let's go to the top of the file and make a nice constant so pure a private con string call it the key relay join code and say relay join code okay so we have this key and over here when we update the lobby let's use this key and then for the value let's just pass in the relay join code although this needs to be inside that object so let's make a new that object and for the visibility we want this to only be visible to members of this Lobby so let's go with member and for the value let's pass in the relay join code okay so this is it and this one as usual is in the weight of Hong Kong like this all right so with this we are updating the lobby to hold the data for the Relay joint code then all we need is to get it when someone joins so down here on the quick join we have joined the lobby and inside the lobby we can simply access the data and inside we can access on the same key and yep over here we have a string for the Relay join code so we have this and then we just use it over here and also by the way this one has a that object so we need to grab the value okay so that's really it really is that simple so when we create we update team Lobby data with really join code and when we join we grab that we use that to join the allocation and we join with unity transport now we need to do is we need to make sure to run this code before everything will start client so over here on the quick join we do that then on join with ID let's do the same thing and same thing down here join with code like that so you always need to make sure to set up DNT transport to use a relay before you start client or start host alright so that's really it with this it really is fully implemented so let's test also on the network manager let's scroll down to the NT transport and over here for the protocol let's swap it out for the really Unity transport all right so here let's go ahead and hit on play Let's create a brand new Lobby its name is my first Lobby let's go ahead create a public and there you go it is creating and it has taken a little bit longer since it is allocating the relay and if you look over here on the console yep we do see the messages it is indeed allocating the relay and it did decide that the best region is your request too okay so this one is now using the relay so now on this one if I hit on play and if there go I do see the lobby right away and if I click on it if there you go it did join the same session note how the player didn't have to bother with inputting any relay code or anything everything happened automatically in the background great and we can also verify that it is indeed working by trying to make another Lobby for a separate section okay so here I have two more clients so on this one let's go ahead create another Lobby I'm not going to join I'm going to create another one my other game let's go ahead create public and if there go now this one created a completely new Lobby and on this one down here let's hit on play and let's choose one let's go and join this one so my other game let's join that Lobby and if there you go note how this one did join a completely different Lobby so with this we now have two completely separate sessions we can now go into regular gameplay so on this one let's hit on ready this one down here let's also ready and yep both of these are now playing their own game there it is just like this and on these let's go into ready and let's go into ready and they're also going to start their own game and there you go now they're also playing a completely different game like this and like this so here we have two unique sessions of our game and both of them working perfectly and separately awesome we can also look in the dashboard over here and see and yep we are indeed using some data so we are indeed connected through the relay okay great so this is really it as you can see using the reality is super simple with this we can now connect any players in any location in the world the players don't have to worry about port forwarding or anything to do with firewalls everything works seamlessly in the background so with this our multiplayer game is pretty much commonly working Unity has some more interesting multiplier tools so let's talk a bit about those in the next lecture hey again quick intermission you're almost at the very end so congratulations on making it this far this one is the second secret call out so go ahead post a timestamp and a monkey emoj in the comments it will be fun to see how many people make it to this point if you've made it this far and understood everything then you already have most of the knowledge you needed to build just about any multiplayer game let me know in the comments what kind of multiplayer ideas you'd like to build maybe you're a fan of something exactly like this a casual Co-op game or maybe you're more interested in building something with some exploration in building kind of like valheim or perhaps you'd like to make some kind of shooter game with notes you can hear really all of those are possible to build so right now let me say thanks for watching the course so far and I really hope you've learned a ton there's only a few more lectures until we get everything built so let's continue to the next lecture hello and welcome I'm your code monkey in this lecture we're going to talk about the various other multiplayer tools that UNT has in order to handle dedicated servers matchmaking and Voice or text chat so here we have already implemented labian relay two great tools that are part of UNT gaming services and there are a few more that ENT provides there is Game Server hosting which also used to be known as multiplay this is how you can easily handle dedicated servers this tool is actually what Apex Legends uses to manage their server infrastructure so it's very robust the way it works is you make a dedicated server build for a game so pretty much just a regular build but with no Graphics then you upload that to the game server hosting platform and after that when a player goes to play your game it automatically spins up an instance of your dedicated server locating in some data center close to where the player is as more and more players play your game more and more servers are automatically started so as your game grows the backhand automatically scales to meet demand then for another Unity gaming Services soon you have Matchmaker with this one you can Define some rules and your players will automatically be matched with one another the most obvious use case is obviously for skill based matchmaking so you'll find some skill number for your players and you can match players with similar skills together but that's not the only case you can also simply Define a room for Ping so search through the regions and look for players under a certain Pang in order to match them or if you have a game with lots of players per server like for example in MMO you could also match players based on server density you can define those rules but then you can also Define secondary rooms that get triggered after some time so for example you can match players with a skill difference of 100 points then if none are found within 10 seconds you can relax that rule and look for players with indifference of 200 points this tool is very well integrated with game server hosting and finally you have vbox this is a tool to help you add text and voice chat to your games Apex Legends also uses this tool this is fully featured so while you could make a basic chat system with just some basic rpcs making something fully featured does take a ton of work and making voice is extremely complex so with vbox you have some high quality audio with low latency it features support for both 2D and 3D positional audio you have some easy volume and mute controls it also apparently supports Speech-to-Text which sounds interesting and you can send DMS to other players send text any group chat and many more features so with these three tools you can further expand upon your multiplayer games in many ways now I did want to include detailed tutorials on all of these three tools but I've been working non-stop for these past few months on both the single player course and now this one I'm quite a bit behind on schedule for some of my other projects like for example my steam game so I don't have the time to really research and cover these tools right now but I also don't want to delay this multiplayer course since the game is already essentially complete so what I will do is launch this multiplayer course which is why you're hearing this right now and in the near future I will do separate videos covering these three tools when I do I will add them to the video references on the course page so if you're watching this in the future pause the video right now and go look at that page so stay tuned for that or you can go read the documentation and learn how to implement it for yourself if you've managed to fully understand everything in this course then I'm sure you'll be able to learn about these tools and use them on your own so here back in this game now that we have pretty much everything working there are some built-in tools to help us debug our multiplayer game let's learn about those in the next lecture hello and welcome I'm your code monkey in this lecture we're going to look at some built-in tools to help us analyze and optimize our game okay so when it comes to the topic of analyzing and optimizing a multiplier game there's really a million things you can do what you should do really depends on a case-by-case basis there are no Universal rules that I can tell you that are going to be applicable to every single possible game so instead of anything too specific here let's just look at the tools and see how they might help the first one is actually something that we already used if we go into the network manager and we'll look down here onto DNT transport down here we have the debug simulator with this we can simulate delay which is how much time packets take to be sent and received again there are no Universal rules so if you're making a super fast paced FPS or some fighting game then for testing maybe you should test with delay up to 15 milliseconds remember the number that you get here is added on top of whatever delay you already have then if you're making a casual Co-op game like the one that we have here you can probably push that up to 150 or 200 milliseconds and if you have something like a turn-based strategy game then perhaps it's even acceptable to go up to 500 or maybe even 1000 milliseconds with this parameter you can basically set the worst case scenario and test your game if only to make sure that it works with definitely and everything soon works as expected then the other option is the Jitter this one is the rate at which the Ping changes basically packets on the internet they are independent and they don't necessarily follow the same path every time so the Jitter here represents a variation in how long each packet will take to arrive maybe one packet takes a really short route and gets a destination in 20 milliseconds and then another packet for some reason takes a much longer route and instead takes 100 milliseconds that difference is going to be Jitter this can be important especially with regards to packet ordering by default packets will arrive at the same order as they are sent so in that case if you have a high Jitter that can cause quite some issues so one option you have is for example on the rpcs over here note how this has a film for delivery which is of type RPC delivering and this one you have two options you have reliable and unreliable by default it's reliable which means the packet won't always arrive there or you can also make them unreliable which means they might not arrive in the same order as they are sent or they might not arrive at all which in turn can help reduce problems each other depending on what you're doing what type of data you're synchronizing you might or might not need ordering and of course remember making it unreliable means the packet might never arrive at all again whether that is a problem or not depends on the use case if you're sending an RPC just to trigger a minor visual effect then you probably don't care if the RPC ends up lost so related to that the last option is the packet drop rate meaning a certain percentage of packets will just be lost if you're using reliable rpcs then that means the packet won't be repeatedly sent until the receiver finally gets the packet which in turn obviously that won't slow down all of the other cute packets so drop rate can definitely cause some very strange Behavior basically it's very useful to use this debug simulator to test your game with a bunch of settings for the numbers you define here they are going to depend on your game and basically you should test your game in the worst case scenario and make sure everything still works now before we use this to test let's actually check one other helpful tool let's go and open up the package manager and over here let's look for the multiplayer tools package so here it is this package let's install it this one adds a bunch more tools for example one tool on the sides is the runtime Network stats monitor for that let's go into the game scene and over here let's create an empty game object called the runtime net stats monitor let's go ahead reset transform just keep things clean and now let's add the script runtime netstats Monitor and here we got a bunch of settings you can leave it on defaults for the position let's just put on the right side just for our game okay so that's great now let's set up our test so let's go back into the lobby in order to look at the network manager okay so down here for the values one thing is keep in mind that these values are added on top of whatever connection you have right now we are currently already using relay which adds a little bit of delay so here for this delay let's go with 50 milliseconds extra then for package editor let's also go with 50 milliseconds and for the drop rate let's say 10 so this will essentially simulate a pretty bad connection also very important is just like it says here on this tone tip this only gets applied on development builds so when making a build for testing let's go up here into file and build settings and over here we have a toggle for development build so if this one is Untold that will not run so let's make sure to turn on this and let's make a build okay so here we have the build and over here let's try to create a Lobby so let's create a public Lobby and right away you can see that it takes actually quite a bit longer so that's the deal in action now down here let's click on play and let's go ahead and quick join and once again it's going to take a little bit longer so the connection there you go takes quite a little bit let's go headset on ready and this one on ready just like this okay so here we are and right away we see a bunch of things so over there we see the runtime network sets monitor so it's actually interact not to start yep there you go we can see that so first of all over there the rtt this one is round trip time so the time to get to the server and back and this one is a server so this one has zero but this one down here note how it has 200 milliseconds and if I move around in order to make an update you can also see it going up and down so that's the generating action so it goes all the way up to 250 then down to 220 and so on so that's because we added 50 in Jitter okay great and right away with this if we look over there on the host we can see quite a big difference in delay look at that everything is quite a bit laggy perhaps this is a little bit too much but some let's just make sure the game works like this and over there we can all see a bunch of sets so you can see the number of RPC packets number of bytes will send and receive so this can be useful for monitoring how much bandwidth your game is using now so related to that is the profiler so over here on the empty editor let's go into analysis profiler and down here if we scroll down we can see a bunch of elements yep over here for the NGO messages and if we click on one of these and we drag it around we can see over here we have client one and client one is sending a network variable on danta and a Time sync with a bunch of bytes and if we scroll around we can see if we try to interact with something you know we can see a client RPC message create object message we can see a whole bunch of interesting things so basically over here we can see how much that is actually being sent either through a network variable or an RPC and who exactly is firing that so again lots of data to analyze how you might optimize your game remember bandwidth is a huge thing and it comes to multiplayer games so now that we have a light connection we can test our game and we actually do have a bunch of bugs so down here if I'm on the laggy client if I go ahead and pick up some cheese then I go into the cutting counter I place there and now I'm going to try to slice as quickly as possible so I'm going to spam the slice button so just Spam and there you go we've got an error on the server so here it is a no reference exception so let's see what this is doing any up here is the error and actually the error is because the cutting recipe is known so over here we have a known reference exception and the reason why this one is null is because we are trying to cut something but the kitchen object is actually going to be the cut object since the cut object doesn't actually then have a cutting recipe for something else it's going to return no basically the problem that we have here is that the client is trying to catch the object way too many times that is because the cutting Foundation actually happens up here on the interact alternate so this is where we decide whether we can slice or not we are running this validation only on the client so if the client has delayed then this will end up trying to slice way too many times causing an error so here even though we are okay with having a client authoritative model we still need to validate the actions of the client in this case it's actually a simple solution we just run these checks over here on the server RPC so let's just check if we have a recipe and if it can be cut then we are going to broadcast the cut object message and same thing down here on the progress done server RPC over here let's also copy the same thing so run this Foundation to make sure the player can actually cut this okay with this simple change Let's test okay so here we are let's pick up some cheese and now let's try spamming the cut like crazy and if there you go even with cutting a ton of times with a bunch of lag now it still works hasn't done now for the next possible issue is on the trash so if I pick up something and then I go and trash it and once again I spam the tracking and if there you go we have no error if unlock the error is here and once again we have the same problem the validation is client side so we're going to get tons of server rpcs in order to destroy that object and only the first one will work so the first one destroys the object and every subsequent one is going to have null in here so once again Simple Solution let's just check if the object is already destroyed if so then do nothing so over here if the kitchen object Network object if this one is already known then this object is already destroyed so if so let's just return okay super simple Let's test so let's pick up an object go in there and trash it let's spam any of their yo no error okay great now for another one it's actually on the pickup so let's go up here and pick it up once again I'm going to spam and there you go we have an err this one says the kitchen object parent already has a kitchen object basically the issue is actually here on the container counter so when we interact we are going to spawn a kitchen object and on this function to spawn it we are going to use a server PC and again if the client takes way too long to receive the message that the server has been spawned if so then they're basically going to call this function a ton of times so the server will try to spawn one object and give it to the player then spawn another object and try to give it to the player which obviously cannot happen so once again we can validate this on the server RPC we can just grab the kitchen object parent and compare it so let's grab this one first so we grab the kitchen object parent and then just check if the parent already has something so if the kitchen object parent has a kitchen object then parent already spawn an object if so let's return and not do anything okay once again let's test okay so let's go and spam to pick it up and if there go it only picks up one okay great so with that I think there are no more errors you to lag so we can spam pick up and drop and that works great we can go there we can slice them like crazy and yep everything works great although again everything that I did here was very specific to this game so you can see how there are no Universal Solutions depending on what problem you have and what your game is like you will have a different solution finally there's one more very important thing over here on the network manager here we have a film for the protocol version this is how you can make versions incompatible with one another usually you really don't want to have different players with different builds playing with each other that's probably going to cause a ton of problems so your players should always update their game and the code should only allow players with the same build to play together so for example let's say we fix some of those issues but someone out there had the old version and they didn't update so that build was made with the protocol version of zero and now if I change from 0 to 1 and now I test here so up here the editor has protocol version of one and down here the build has protocol version of zero and now if I go into test over here if I create a lobbying now this one actually does see the lobby because we didn't add any sort of Virginia on the lobby although we could easily add that in the lobby data and only show on Lobby is on the same version but even without that just like this we are guaranteed to have no connection if I try to join this one joining Lobby connecting and there you go fail to connect because we have different protocol versions so with this only the same version can connect alright so those are a bunch of tools for how you can test your game as you can see the solution is heavily dependent on a case-by-case basis so instead of memorizing these specific Solutions just learn how to use these tools to solve any problem okay so with that our multiplayer game is pretty robust finally since our game is pretty much done let's go over here on to the kitchen game Lobby and down here we have our testing code for initializing how we set the profile we did this just so we could have multiple builds at once but we don't really need this in the final published game so we can just come without this line to set a different profile every time and one last thing in my case I'm going to go over here onto the game scene and I'm going to remove the quantum console finally for testing let's also disable the runtime net sets Monitor and let's go into the build settings and make sure that our builds are not development builds okay great so everything is set up correctly now let's go into the next lecture to add an interesting option let's add the option to play the game internally in single player hello and welcome I'm your code monkey in this lecture we're going to add an option to play the game fully in single player okay so when you make a multiplayer game if it is possible with the design you should include an offline single player mode here in this game of the player units work the same so design doesn't really require multiplayer so let's have that as an option and thankfully that's actually super simple let's begin by going into the main mini scene and over here all we really need is just another button so let's take the play button let's name this play single player button and let's duplicate this and make the play multiplayer button okay let's just position them put that one there that one up there and let's not submit the text so for this one multiplayer let's scale it down a little bit and same thing on this one let's put it sing on player and also scale it down okay great two buttons now let's open up the main menu UI script and over here let's add both button references so let's rename this one to the play multiplayer button another one for the play single player button then here in the editor let's write the references so the single player and the multiplayer okay and now very simply in order to play multiplayer we do go into the lobby scene so pretty much the same as normal and then on this one we really just need to go straight into the game scene and call the start host now the one tricky thing is we don't have the kitchen game multiplayer we don't have this over here on this scene we only have it on the lobby scene so we could rework how our game is organized in order to place those objects over here on the main menu or let's just add some basic automated Logic on the lobby scene so let's go here on the kitchen game multiplayer and for this one let's make a static volume we can sense so public static ball let's go and play multiplayer so we have this standard Boeing it's bowling so we can access it from anywhere so over here on the main menu let's go into the kitchen game multiplayer and we set play multiplayer in this case to true and in this one we set it to false then we both go into the lobby scene and now over here on this one let's go and make a private void start and on start let's check if playing multiplier if so then we're actually not going to do anything so let's actually say not playing multiplayer so playing in single player if so then let's start playing right away so let's go on start host and then loader and let's load and load the usual game scene okay so honestly that's really it let's test so here we are and press on single player and goes into the lobby and immediately goes there and now if I hit play and if there you go everything is indeed working perfectly so I'm playing around I can pick up I can slice objects I can cook them everything works perfectly alright awesome now I can even shut down my internet to verify so I am not connected and over here let's go into single player goes into the lobby and goes and everything works perfect alright awesome now one thing this actually does throw an error on the lobby that's because it cannot access an external location that's obvious but this is not the problem because it's just throwing an error and the game keeps playing as normal so with this the entire game works perfectly fine everything works great all the logic is running but only locally so even though the network manager is indeed running it is only running locally in offline single player so thankfully for this type of game it is really simple to add single player so if possible definitely make sure to add it to your games with that then there's only one final thing we need to do and that is make sure that our game is playable with a Gamepad so let's test that out in the next lecture hello and welcome I'm your code monkey in this lecture we're going to go through our game and make sure everything is playable with the GamePad okay so when we made the single player game we already made it fully playable with the GamePad but now in order to add some multiplayer features we also added a bunch of extra menus so let's go through the game make sure everything is still playable with the GamePad now over here on the main mini scene everything already works so I can go up and down and select all the buttons just one minor thing which is by default the single player button is the one highlighted let's make the multiplier one to one default so very simple just go over here onto the event system instead of selecting the play single player button let's just write that one okay very simple change now from here let's click and go into the lobby scene and first of all we don't see what exactly is selecting so let's do the same thing and change the color for all the buttons so we're here on Lobby scene let's select all those like the main menu button anyways only just go over here on the slide corner and put it on a green so something like this so let's make sure to apply this to all the buttons so there's great Lobby quick join join code button let's put all of these with a slight color on my screen and same thing for the input Fields also put them as selected and finally on the lobbying list for the template let's also put it on selected then beyond that we've got the unlocking message UI so let's put that one also put it on selecton and for the in lobby create UI from these buttons same thing select all the buttons paste it selected select the input field and same thing okay so then the other thing is on the character side scene so let's go there now and over here do the exact same thing so select all the buttons and set the selected color and then down here for the buttons for changing the color for this one this one is a prefab so let's go inside the prefab and modify the entire prefab okay so that's great just one more thing which is on the event system for this one we need to replace it because by default comes with this input model we want the other one so let's defund it so change it on this one and also on the lobby scene let's also go onto the event system also replace it like this also for testing here let's just default deploy multiplier to true and let's make sure to select the default button so let's go in the unlock UI and let's say the create Lobby button put this one as the first selected then on the character select scene let's also assign one so one of these colors down here select them as selected okay let's test so here we are on the create Lobby move down to Quick join okay great and now if I move down it goes into the code input box and now if I move down and nope now I'm somewhat stuck here so I'm not sure if the automatic navigation is meant to intentionally become stuck on an input field I don't know if that's intentional but that's what happens but either way on a Gamepad we can't right now input any text so a simple solution is just make sure that the GamePad buttons do not go through those input fields so over here select the input fields and on navigation instead of automatic let's just go with none for both this one and the player name input field just like this so now if we move any of the go now we can move through all the buttons now obviously in the final multiplayer game you would make some kind of on-screen keyboard for that you would either interact with some kind of platform API like the Xbox API or the PlayStation API or something like that or you get some kind of on-screen keyboard possibly something from the sort but either way right now at least the game is playable so we can create lobbies and we can quick join we just need to also over here on the create and Lobby let's also disable the navigation on this one and when we show this window we need to show one of these buttons so same thing that we did previously when we have the show let's go let's say the create public button let's go and call Select okay so here I am and I'm going to create a Lobby and yep let's go and make it a public Lobby so it's creating any up here it is and down there the buttons are actually selected so I can change the color into this or this something like that and when I'm ready I can go into the ready and if there you go now here I'm playing and everything plays perfectly all right awesome so the game's now fully playable with a nice Gamepad and with that we have our final game completed so let's go into the next lecture and see everything that we've built hello and welcome I'm your code monkey in this lecture we're going to look at all the work we've done and have some fun playing the final multiplayer game okay so we start off on the usual main menu except right now we have an option to play in multiplayer or single player so if we just go in single player and the game starts playing right away in single player so we can play this offline just by ourselves and everything works perfectly so I can move cut deliver recipes and so on perfect then from here we can go back into the main menu and back in here now let's see the proper thing let's play multiplayer and as soon as we do we go into a nice Lobby scene so here if there were more players playing the game we could see only 7 lobbies up top we can see and customize our player name we can go ahead and create a Lobby give it a Lobby name so my awesome game Lobby and let's go ahead create a public Lobby and if there go it creates and here I am inside my character selection now I've got some other comments down here so I can go ahead and I can join Huawei with all of them so I can either join by joining the live directly or use Quick join and it will automatically join and If This Were a private lobby I could use the lobby code to join by code and if there you go all clients are now connected and for character customization now we can choose from a whole bunch of different colors and there's some logic to prevent players from using the exact same color then once everyone installs their color they can Mark as running and the game will only start when they're all ready also over here on the host the host can kick any client so let's go ahead set them all as ready and once they are all ready the host is going to load and yep all of them are going to load with it then we have our controls and we can press interact to continue and it waits for all the other players so in multiplayer all of them must be ready and there you go we get a nice counter so it counts down the time and after I go the game starts playing as I'm moving it's perfectly synchronized and all the others so I can move on any client anywhere any of everything is synchronized then I can pick up objects once again the animation is synchronized the object is synchronized all of that works perfectly I can place the object I can slice it I can pick it up do a bunch of things then on this one I can go ahead pick up some meat cook it then move away then on this one I can pick up a plate in order to grab the meat and everything is working perfectly so the stove works for definitely the container counter works perfectly the ingredients some of them work perfectly so I can pick up do everything and deliver any of all of them see a delivery success then the game set itself so the countdown timer of that was working perfectly over there the game timer that one is also being perfectly synchronized so we're handling all kinds of things we even have some object militants over there we destroy any of the objects destroyed on the network and when we pick up it gets spawned on the network so lots of things and finally as the Tamron lapses yep all the clients came into a nice game over State alright awesome so here we have a fully working perfectly synchronized multiplayer game now if you've made it this far then congratulations let's go to the next lecture where I'll give you my closing thoughts hello and welcome I'm your code monkey and congratulations you have completed this multiplayer course alright awesome that is seriously a great achievement very few people actually complete courses and if you're at the end of this course then that probably means you also got to the end of the serial employer course so really double congratulations to you I generally hope this course has helped you on your own Game Dev journey I hope you now feel capable to build whatever multiplayer game ideas you have throughout this course you'll learn about how to set up netcode for game objects to create a multiplayer connection you'll learn how to use rpcs and network variables to synchronize all kinds of data you'll learn the pros and cons about server authoritative versus client authoritative you'll learn what logic should be on the server and what can be on the client you also learn how to make a nice character selection scene to customize your players and how to handle the scene connection flow you'll learn how to use Unity Lobby and relay and most important thing of all you'll learn how to do all this while writing some good clean code so I really hope you enjoyed learning about all of that let me know in the comments what was the most important thing you want learned throughout this course I hope this was very fun and very educational if you enjoyed my teaching sound then maybe check out my other courses if you haven't yet seen my turn-based strategy course I really think that one would be excellent for you right now it Dives even deeper into some more advanced topics and since you've watched this entire course and this Empire course you know have all the knowledge you needed to follow that course it will help you really solidify all the knowledge you gained especially everything related to writing some good high quality clean code and since you use Unity check out my ultimate TNT overview course it covers lots of the tones and features of the engine so you can really use all the tools at your disposal to make any game you can think of or alternatively if you like visual scripting you also have a course on that or learn how to make a really nice Builder Defender game and definitely make sure you wishlist my upcoming Sim game Total War Liberation I won't be posting some devlogs and in those you will also see how the code that I used in my own Sim games is on the same level of quality as what you learned in these two courses okay so that's it for me both of these courses have been a ton of work so I genuinely hope they helped you a ton on your Game Dev Journey now go ahead take what you learn here and build an original game thank you so much for watching and I'll see you next time
Info
Channel: Code Monkey
Views: 284,798
Rating: undefined out of 5
Keywords: code monkey, unity tutorial, unity, game design, game development, game dev, programming, c#, software development, learn to code, learn programming, how to make a game, kitchen chaos, unity complete free course, unity free course 2023, unity free 2023, unity course, unity course 3d, unity for beginners 2023, unity complete course, unity multiplayer, unity netcode, unity netcode for gameobjects, unity netcode for entities, unity multiplayer tutorial, online multiplayer
Id: 7glCsF9fv3s
Channel Id: undefined
Length: 380min 20sec (22820 seconds)
Published: Mon Mar 06 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.