FULL TUTORIAL! Create Unity Multiplayer Games with Netcode for Gameobjects

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone in today's video we will talk about the net code for game objects the new Unity multiplayer system and we will create a simple prototype to make you understand the foundations and the basics of this multiplayer system so by the end of this video you will learn how to install netcode for game object how to synchronize the movement and the animation of the players how to create network variables and communicate them between the clients and the server how to spawn on these spawn game objects and all those Concepts will be the base foundation for creating any multiplayer game this video is sponsored by unity netcode for game object is a higher level networking Library built for Unity for you to abstract networking logic it enables you to send game objects and World data across a networking session to multiplayer players at once with netcode you can focus on building your game instead of low level protocols and networking Frameworks and check the link for the full documentations about net code for game objects down in the description [Music] so before we start building the multiplayer game of course there should be some single player aspects so let me show you briefly what I did to create this simple prototype I used Pro Builder to create the scene it's very simple scene using one plane and three boxes and for the player I used a capsule then added to it a cube resize it to be as sunglasses player have two main scripts the player movement to move the player and shoot Fireball to shoot Fireball projectiles and it has two main animations the idle and running animation so for the player movement let's go briefly through the code so we have two floats one to control the movement speed and one for the rotation we have a reference to the animator then in the update function we store the input in the horizontal and vertical floats then we store those in movement Direction Vector 3 then we do a translate toward the vector 3 Direction then we rotate the player to face the direction we are moving toward it and finally we update the float on the animator to change between the two animations the idle and run based on the value of that float so if the value is zero we go to the idle animation if it's above zero or below we are moving so we move to the Run animation the other manuscript is shoot Fireball script which responsible for instantiating this Fireball and then there is another script which attached to each firewall that moves it toward the direction of shooting and when we collide with something we instantiate the hit particle effects at that location if you are interested in learning how I created this Fireball it's a part of the ultimate 2D and 3D Shader graph course which has been released on udemy and you can grab the chance to get a discount code which I placed down in the description now let's make this project a multiplayer game so we go to window package manager and we install net code for game objects then we can create a new empty game object and name it network manager then we add to it the network manager component and immediately you will see a notification message saying that the multiplayer tools package is needed so let's search for that and install it from the package manager the first thing we need to do in the network manager is to choose the network transport and for now we can choose the unity transport we keep all the values to the default values next we need to set the player prefab which will be spawned each time a client connected to the server so we click and drag the player into the prefab folder to create a prefab of it then we set it as the player prefab on the network manager but before we proceed any item that should work with the network should have Network game object component and also any prefab should be instantiated in the network should have been listed inside the network prefab list so let's add also the player to that list let's hit play and from the network manager we can click host to see that the player prefab has been instantiated and functioning correctly now in unity editor we can click on those buttons from the inspector but when we create a standalone build we should create a UI to represent those buttons so let's create a new canvas and add a buttons that simulate clicking on start host and start client so the Standalone version be able to create the host and able to accept clients connected to it so let's create new canvas inside that we can create a new image to represent the UI that holding the buttons then let's create two buttons one for the host and another for the client for this example we are using the host client structure so one of the clients is also a server that is the host and the other clients connect to the server which is the host so we don't need a server button for now we only need a host and a client now let's create new script and name it Network UI to code what happens when we click on those buttons we want them to simulate clicking on connect host or connect client so for this we need two buttons we set them as a serialized private fields then let's remove the start function and on the awake we can subscribe or add listeners to the on click event so when we click one of those buttons we should decide what will happen and we use Lambda to execute the desired function so for example for the host button on click we add a listener to call the network manager dot instance Dot start host to create the host for our Network we copied this to do the same for the client we just change the host button to client button and we change the function we want to call to start client instead of start host now you need to go back to Unity and drag the two buttons into the inspector to give references for them let's hit play and test the host button and see that it's working perfectly as expected but now we need to check also the client so we need to create a standalone version of our game now let's go to the build settings you can go to there from the file menu or by clicking Ctrl shift b as a shortcut you can set here the private parameters for your player your company name the product name and make sure that you select the full screen mode to windowed and set the resolution to something lesser than your full screen resolution so you're able to see the build and unity at the same time now let's click client to check if we can connect perfectly and yes from the editor you can see that we have created a second instance of the player which represents the client and if you want to to move around you'll see a lot of problems that we will fix one by one so first thing if we move one player we are moving both players on host and on the client at the same time to show you that clearly as you can see both of the instances of the player having the same values for the position and rotation and if I move one far away from each others we can see both of them moving in the same direction as if we controlling both of them with one code and since we can't check the console in the Standalone build we can do this as optional step which is downloading the in-game debug console to your scene then drag the prefab of that to your scene that will allow you to have a console in your Standalone build so you can check the error messages that you get there and since we have the UI on the left we can enable horizontal resizing and set the resize from right to have a comfortable View so now we can debug and keep tracking of what's happening in the console if we start the Standalone build we can see that we started the host and when we connect the client from the unity editor we will get a message that client has been connected now let's assume we need to know how many players are connected to the server to do so first we need to set up the UI by adding to it a text using text mesh Pro component so right click on the buttons holder and click UI then text resize it to be in the middle and reposition it to be below everything we can change the font size to be suitable Maybe something like 24 is good set it to middle and let's type here players and set the value for now to zero we need to control that by code now let's go back to the network UI script and we need to add two things the first one is a reference to our text in the UI so we create a private text mesh Pro ug UI and name it players count text and we need a network variable which will communicate the variable we setting in it between all the key lions that connected to the server so let's create a private Network variable type of int integer and name it players num and we need to instantiate any Network variable immediately by clicking or typing equal to new network valuable type of integer then in the update function we store inside the network variable its value we store inside it the connected clients count by calling the network manager dot Singleton dot connectedclient.count so now we have the count of the players connected inside the value of the player's num then simply we need to assign that value to the text on our UI so we say players count text Dot text equals to the player num value but we need to convert it into string to be acceptable by the text component if we play the game now we get this error message saying that the connected clients should only be accessed on the server so let's adjust the code to make that happen first we need to inherit from Network Behavior instead of monobehavior to be able to access the network properties then before we start the update function lines we set this if so if we are not the server then we return so this only will be executed on the server which is in our case the host now if we hit play we get this message saying that any script that contains Network Behavior should contain a network object component so we'd like to add that of course yes we so we forgot to add Network object to the network UI because it contains Network Behavior so now if we run the game and start the host we get that we have one player but seems I forgot to write the string players before the number let's double check that when we connect both the host and the client so as you can see now we're getting two players when we connect both the host and the client but on the host only while on the client we're still getting zero players and that's because we didn't give read permission to the clients to read this network variable so let's fix those two things first we need to set the default value for the players to be zero since we don't have anyone connected so we say players zero then we give read permission to everyone that means all the clients can read this network variable not only the host and the second thing is that we need to add the string pliers before the value of the number of players connected and now if we do another test we are surprised that we're still getting the correct number on the host but not on the client and that's because we called the line of getting the number of the connected players after setting the if is not server so the client is not reaching that line and the simple solution to solve this is just to move that line to the beginning of the update before the if is not server so the clients can still read this variable so let's do a final test and hopefully this is working perfectly as expected so yes we can get now we have two players connected on both the host and the client now we need to solve the issue of moving only the player that we controlling so now we need to solve the issue that we controlling both the host and the client with the same control script removing both the client and the host at the same time with the same code so we need to tell the code that we want to move only the player that owns this code first thing we need to do is to add the network transform component to the player to allow us to synchronize the movement of the player between the server and the clients then we need to inherit from the network Behavior but make sure you add using unity.net code at the top of your script then at the beginning of the update function we add this if so if this is not the owner we return we stopped continue executing the script that means we will only control the player that owns this script so each user only move the related player okay let's test this with the host and the client so let's create a host on the Standalone version and let's connect the client on Unity editor so if we try to move the player on the client we can see it's not moving at all while if we move the player in the host it's moving perfectly synchronizing the movement but not syncing the animation so first let's try to solve moving the client problem then we'll move to syncing the animation issue so after checking the documentations of netcode for game object I found that the network transform only synchronize the position from the server to the clients and not the opposite but to solve that there is a client Network transform which allows synchronizing the position of the owner client to the server and all other client allowing for client authoritative gameplay and we can get that script by installing the multiplayer samples utility package from the package manager by copying the link provided and adding it to the package manager now we can go to the player prefab and remove the network transform and replace it with the client Network transform and now if we test the results everything working perfectly as expected the client movement is synchronized also the host movement but we still have two issues first one we're not synchronizing the animation we will deal with that later the second one the server when instantiating the player it resets the values to zero so both the client and the host are at the same position and not facing the camera so first let's solve the animation synchronization issue and that can be done easily by adding the network animator component and linking the player animator to it if we test it and try to move the client we see that the animation is not synchronized while if we move the host the animation has been synchronized to the client and since it's like the network transform all is a server is allowed to synchronize the animation or transform to the client but not the opposite so let's go to the documentations and see what we can get there so if we go to components the network animator we found a section called owner authoritative mode and that allows the clients to synchronize their animations with the server it's a very simple code that inherits from the network animator but disable the server authoritative so that makes the client also authorized to synchronize the animations so let's create now a new script and name it owner Network animator and copy the script from the documentation to here now save go back to the scene replace the network animator on the player prefab with the owner Network animator then assign the player animator to the field there and now we can synchronize the animation between the clients and the server now let's check the next issue if we check the prefab you can see that I have rotated it 180 degrees on the Y to face the camera but the problem is when we instantiate the game object by the server it reset all the values to zero so first it's not facing the camera and secondly all the clients has been instantiated also at the same position so we need to fix the rotation and give a random position when we spawn a player in the game so let's go back to the player movement and do some adjustments to that first we need a float to control the position range of the players now if we inspect the network behavior and search for spawn we can find a function that's called on network spawn which is responsible for spawning a player or a prefab in the network and when that happens we can now override that to execute some codes this is the best and the only way to issue commands when a player instantiated so we don't need to use the start or awake function when we create a multiplayer game we should use on network spawn so we override on network spawn and we tell that we need to randomize the position of each player we spawned using a random range with the value we choose so we say transform position equals to new Vector 3 and we randomize the value on the X using the range we created so we say random range the position range we specified up in the float and the second value is minus the same value so in our case the X will be between 5 and -5 a randomized value between that and for the Y we want to keep it 0 for the Z we repeat the steps for the X so it's a random value between the position range and minus position range so for the rotation we say transform dot rotation and it's equal to new quaternion and we set the rotation on the Y to 180 while keeping all other values to zero and now as you can see we are spawning the players at different random locations and also they are facing the camera correctly we fix all the issues related to syncing the movements of the players between the client and the host now let's solve the problems that's arising when we wanna instantiate and destroying the game objects for multiplayer games so if we test now to see what problems we might face we can see that when we shoot both the client and the host shooting at the same time and those projectiles are not synced between the host and the client so if we shoot at the client or in the client we only see the projectiles in the client window and if you shoot in the host we only see the projectile in the host window so what we need to solve first is to give the ownership for shooting so only we shoot from the player that owns the script and the second matter is we need to sync those spawning or instantiating of the game objects and destroying the game object between the host and the client the first thing we need to do is to add the network object component to the projectile which is in our case the fireball then we need to add that to the prefabs list in the network manager as we agreed we should do the same for any object that will be used in the network now let's do some adjustments to the shoot Fireball script which controls instantiating the Fireballs when it comes to netcode for game objects there is a command that we can use to tell the server to sync the projectiles or the game object between the server and the clients so we simply when we instantiate any game object we give a reference to that so let's give a reference to the firewall by writing cam object and name It Go game object then we get component Network object which we added to the prefab of the Fireball and we call spawn function let's save and test that so simply just by this code you can sync spawning the game object between the host and the players but we still have this problem that when we shoot we shoot for both the host and the client at the same time because we didn't give ownership to the players and simply to fix that we change the inheriting from monobehavior to network behavior and we add a new if at the beginning of the update checking if the player is the owner of this script so we type if this is not the owner we return and not executing the script so let's test the game if we shoot from the client we can see that the projectiles are not synced with the host while if we shoot from the host it's synced with the client so let's check the error message that we're getting in the console and it says only server can spawn Network objects let's solve that so only the server can instantiate Network objects in that case we need to find a way for letting the client requesting from the server to instantiate the game object for it and after checking netcode documentation the way to do that is using server RPC which a request or a call from the client to request from the server to do something I think it's worth a minute to stop and talk about the differences between server RPC and the client RPC because it's essential when it comes to working with multiplayer games so the server RPC let's check here the server RPC we call or request to execute something from the client and it will be executed the server side so there is no execution at the client side while when we go to the client RPC we not executing anything at the server side otherwise we executing the methods on each client so we request to execute the function from the server and they will be executed on each client separately so in our case since each player one request instantiating its Fireball in this case we need a server RPC so let's create a private void and name it shoot server RPC make sure you type server RPC at the end of each server RPC function without it it will not work then let's move the codes from the update function and place them in the shoot server RPC function then we call that function from the update Let's test the game and yes now everything working perfectly as expected we can shoot projectiles on the host and they are synchronized in the client and we can do the opposite we can fire the projectiles add the client and they are synchronized in the host now we need to deal with destroying game objects in a multiplayer game so as you can see in the error message it says destroy a spawned Network object on a non-host client is not valid we can call the destroy or despawn function only on the server so to solve this issue we need to keep tracking of all the instantiated fireballs I know this is not the optimum way but I'm showing you this so you learn the basics of net code for game objects the best way of course by pulling which let me cover later in further tutorials but for now let's create a list of Game objects to hold the references for all the instantiated fireballs because once the game object has been instantiated it's totally a separate entity that we don't have control over it and to keep tracking we created this list then in the shoot server RPC and before we spawn the network object we add the fireball to the list by writing spawned Fireballs dot add the game object which is the current Fireball then we need to give a reference to this Fireball to know who is its parent or owner since there are a lot of players we need to know each Fireball to which player related then we move to the move projectile script that attached to each Fireball and we create a public shoot Fireball as a parent to know who is the owner of this Fireball we go back to shoot Fireball script and we get the component move projectile and we set the parent to this player which is this script now the same way we created a server RPC for shooting we need to create another RPC for destroying the projectiles so we create a new game object and we give it a reference for the first Fireball that has been shot because we first in first out I mean the first Fireball we shot we need to destroy it the first so we create a new game object and name it to be destroyed or to destroy and we give it a reference to the first Fireball in the list then we get the component Network object to call the function this Pawn to remove this game object from the network before destroying it and we remove that item or object from the list by calling the list dot remove to destroy and finally we destroy the game object or the projectile now we go to move projectile script and let's for now disable the lines related for instantiating the particle effects and focus on destroying the fireball itself so when we collide with something else so on trigger enter we call the function destroys server RPC from the parent and of course we set the ownership to the current player by setting an if if this is not the owner then we return to avoid destroying other players projectiles so let's test it and yes now we can spawn and despawn projectile perfectly on both the client and the server but we're still getting an error message on the console only the owner can invoke server rpcs that requires an ownership because we gave an ownership to destroying the projectile so we need to fix this by adding a simple parameter which is require ownership equals to false Let's test and now we can spawn and despawn projectiles perfectly without getting any errors in the console now we can redo everything again for instantiating the particle hit effects it's the same concept so we need to create a new server RPC and in it we request from the server to instantiate the hit particle prefab on the clients so let's enable the lines responsible for spawning the hit particle prefab so when we collide with something else whether it's a wall or another projectile or the player we instantiate the hit particle effects so let's start by adding the server RPC attribute then creating a new private function and call it instantiate heat particles but as you notice I forgot to add server RPC at the end of the name of the function so we'll get an error soon then let's copy or cut and paste the codes responsible for instantiating the particles prefab and give it an instance so we say game object hit impact we instantiate the prefab of the hit particles add the transform and the position of the hit location then we gain access to the network object to spawn the particle P far in the network and as we agreed any game object or pfab needs to be used in the network we need to add to it a component Network object and also we need to add it to the prefabs list on the network manager so we instantiated the heat particles and we need to destroy them later somehow so for that I created an auto destroy script that auto destroys the prefabs after 5 Seconds we need to change the script from mono Behavior to network Behavior to be able to work with the uh Network system then we create another server or PC to destroy the hit particles so let's start by a server RPC attribute and set a property requires ownership to false because we don't need an ownership then we create the server RPC for destroying the particles so destroy particles server RPC as a private void then we move the destroy line to that server RPC and before it of course we get the component Network object and we call the despawn function and before we forget let's go back to the move projectile script and add server RPC at the end of the function name since it's required for any server RPC function and also we need to call this instantiate hit particle server RPC function from somewhere and it's on trigger enter so we will collide with something we need to trigger that Let's test and now yes we can synchronize instantiating and despawning the hit particle effects perfectly on both the host and the client before we proceed I noticed that I made a mistake related to the player movement since we created a random position for each player we did it seems locally but we didn't propagate these values to other clients or to the server and that's because we didn't use the server or PC that causes the player to jump when we try to move it because we instantiated the player at a random position but we didn't tell the server that we did that so when we move we start again from the zero location then start moving that cause a jump in the player movement at the beginning of the game which is annoying to solve that we simply create another server RPC and we name it update position server RPC then we move the lines related to randomizing the start location and the rotation then we call that RPC server RPC function from on network spawn of course don't forget to set the attribute with the property required ownership to false to avoid getting an error related to the ownership of this code okay we're done with everything related to the movement and spawning and the spawning let's now move to some more interesting stuff let's assume now we need to create or show the player name above each player because for now all the players are the same same color and we can differentiate we can't differentiate them so let's create a new UI by dragging the player prefab into the scene and creating a new canvas let's name it player hunt and change the render mode from screen space overlay into a world space let's add an image to that canvas and make it stretch to fill all that canvas by holding alt shift and clicking on the stretch button then changing the width and height of the player HUD to be two on the width 0.5 on the height and reposition it to be 2.5 on the Y now it's well positioned above the head of the player let's set the color of the background to Black and make it semi-transparent so now let's add the text as a child for the background let's name it two player zero for now and keep adjusting the properties of the text to be visually clear for the player now let's create a new script and name it player settings to manage everything related to the player so let's delete everything inside the code and add using unity.net code at the beginning so we can be able to inherit from Network Behavior then let's create a new private serialized field with the type of text mesh Pro ug UI as a player name to give a reference to the text that we created in the player HUD then let's create a new private serialized field a network variable with the type of fixed string 128 bytes and if you ask me why I added that and not adding a simple string because the network variable cannot be nullified and if we put it as a normal string the normal string can be with the null value then let's instantiate this network variable with a type fixed string 128 bytes and give it a default value with string named player 0 and give the read permission to everyone so all the players or the clients be able to read this name and finally we give the right permission only to the server then we override the on network spawn to decide what will happen when we spawn a new player so we simply store inside the network variable which is the network player name the player string then we add to it the number of the player which is the owner client ID that gives the current player ID we add to it 1 to give a logical number because the first player is player 0 we add to it 1 to become 1 and so on and then we simply store that Network variable name inside the text that we created in the player HUD save the script and go back to Unity and let's add the text mesh Pro and drag it to the player name to give a reference to that to be assigned when we log in with a new player and actually the network variable should not be serialized because we don't need to change it or see it in the inspector so we simply can remove the serialized field attribute to avoid showing it in the inspector now let's test the game and see what we get we connected the host and yes we have player one we call negative Z client and yes we have player 2 as expected but it's not nice to rotate the player HUD with the player so let's fix that let's drag back the player to the scene and let's add a new code and name it UI look at camera this is a very simple code that runs at late update after updating everything in the scene so we say we wanna the transform of this UI to look at from the current position toward the main camera transform those forward is the z-axis of the camera save the code apply the changes to the player prefab then deleted from the scene and let's test if we got the desired results hit play and yes now the player HUD always looking at the camera so we always can read the player name clearly and as an extra additional step for today's video let's make the game more interesting by giving colors for each player to do so let's open again the player settings script and add to it to New parameters the first one is the private serialized field called mesh renderer to be able to access the mesh renderer of the player and be able to access the material there then inside it we access the color the other parameter we need a list of colors to determine each player color and I made it public so we can choose the colors accurately then in the awake function we give a reference for the mesh renderer by getting the component mesh render and finally on network spawn we set the color on the material to equal the color in the list that matches the player number so for example player 0 which is Player 1 will be for example blue player 2 will be red whatever you choose the colors from the list so we say the color on the material will equal the color on the list based on the player number save and go back to Unity and now we can add colors to match the number of the players desired so if we gonna play with only two players we need to set it to two colors let's assume the first one cyan and the other one is orange so let's test the host and see if we get this iron color no we didn't get it because we have an error saying that there is no mesh renderer and that's because the mesh renderer is in the capsule not the player prefab so we need to search or to get the component inside children so if we simply go back to the script and change the reference to the mesh renderer from get component to get component in children and that will solve the issue let's apply all the changes we did to the player prefab and test the game now voila the player one color is cyan and now when the player 2 connected is orange and that's what we want it to do let's expand this and test it if it work with four players so I added two more colors one purple and the final one is a reddish one so I launched four instances of the Standalone executable file of the game and here is the final results we have four players with different four colors and each one named with its proper name player one player 2 player 3 and player four and we can control any of them and we see the movement has been synced with all other clients the projectile are shot properly and we instantiating even the hit particle effects and all of those has been synchronized over the network I know this was a very long tutorial but if you kept watching till now so congratulations you learned the basics of multiplayer games so let me know down in the comments which type of video games would you like to see me creating in the next video so if you found this video useful don't forget to hit like subscribe and the notification Bell and this way you can keep supporting our channel to keep producing high quality tutorials and that's it for today's video thanks for all supporters on patreon and till next video see you soon [Music] [Music]
Info
Channel: Binary Lunar
Views: 58,531
Rating: undefined out of 5
Keywords: unity multiplayer, unity netcode for gameobjects, unity netcode, unity netcode tutorial, netcode for gameobjects, devlog, unity, unity tutorial, coding, multiplayer, networking, unity netcode for entities, unity multiplayer tutorial, unity boss room, unity galactic kittens, unity game tutorial, unity tutorial for beginners, unity 3d, game development, game dev, game development unity, unity 3d tutorial, programming, c#, code, learn to code, learn programming, unity tutorials
Id: HWPKlpeZUjM
Channel Id: undefined
Length: 48min 14sec (2894 seconds)
Published: Sat Nov 19 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.