Unity 5 Network Tutorial Part 2 – Online scene setup and player movement

Welcome to part 2 of my Unity 5 basic network game tutorial. In this part we will set up the online scene, handle spawning the players in differing locations, and enable moving them based on player input.

Part 2a – Online scene setup

Before we start on the player movement it will be a good idea to re-design the Online scene so that we have a (very) basic game arena in which our players can do battle. Feel free to embellish this scene as you see fit to make it more interesting.

Go ahead and load the Online scene (double click Online Scene in the Assets\Scenes folder) and save any changes to the existing scene if prompted.

With the Online scene loaded let’s make the ground. Create a plane (GameObject->3D Object->Plane) and rename it Ground, then set it’s transform settings to these values:-

Next, let’s give our ground a bit of colour.

  • Create a new folder in your assets folder and name it Materials.
  • Double click the new folder to open it, and right click in the empty window, then from the popup menu select (Create->Material) and rename the new material GroundMaterial.
  • With the Ground material selected, in the inspector click on the colour selector to the right of the Albedo setting and change it’s colour. I went with a nice brown colour (RGB value 122,78,0).
  • Lastly, left click and drag the Ground material from the Project Window onto the Ground plane in the scene view, and you should see your new colour applied to the ground.

Now we should sort out the camera. This is going to be a top down game, so for the time being let’s move the camera into a position that better suits this (eventually the camera will be attached to the player object). With the Main Camera selected change it’s transform settings to the following:-

CameraTransform

The final thing for our game scene is to create a couple of spawn locations for our players (you can in fact make as many of these as you like). Add an empty GameObject to your scene (GameObject->Create Empty) and rename it SpawnPoint. Now add a NetworkStartPosition component to it (Component->Network->NetworkStartPosition) and set its transform settings as follows:-

SpawnPoint

Now make a duplicate of this SpawnPoint and set its transform settings as follows:-

SpawnPoint2

The network manager will use these GameObjects to set the spawn position for players when they join the game.

Your Online Scene hierarchy should look like this now:-

OnlineSceneHierarchy

At this point it’s probably a good idea to save the scene (File->Save Scene) to avoid the risk of losing all our hard work so far.

If you switch back to the Offline scene, run the game and start a host, you will see a much more obvious scene change now.

While we are at it we can make one more small change to the NetworkManager. Under Spawn Info change Player Spawn Method to Round Robin. This means that players will be spawned at consecutive spawn points rather than randomly chosen ones.

Part 2b – Player movement

Now we’ve come to the part where it gets a bit more interesting and we even need to write a bit of code! But before we do that let’s first stop to talk about a bit about how the Unity networking system works.

The Unity networking system introduced in Unity 5 (often referred to as UNET), is what’s known as a server authoritative system, which simply put means that only the server PC can make changes to networked game objects, and it then propagates those changes to all connected clients.

To give an example, if a player picks up a health pack, it sends a command to the server telling it so, and then the server can update the health (by an amount decided on the server) for that player object, on all connected clients. This prevents possible cheating, because if the client was allowed to update it’s own health it could, in the hands of an unscrupulous player, be made to add more health than it should. By having only the server handle this sort of thing it makes the game far less prone to cheating.

Hopefully that all makes some kind of sense! But in any event it leads me onto a change we want to make to our player object. With the system as I have just described it, if we want to move our player, we would have to send the new position to the server and then wait for it to send back an update before our player would actually move.
Therefore, you would be in a situation where you pressed a movement key and your player didn’t respond instantly, this can make the game feel very laggy, with anything but the lowest of latency. So ideally we would like to be able to update our position ourselves so we get instant visual feedback, and then have our new position sent to all the other players.
This is where the LocalPlayerAuthority setting of the NetworkIdentity component comes into play. By setting this to true, we can make changes to our own player without having to wait for the server to do it for us.

So before we do anything else let’s sort that out. Select your player prefab (in the Assets/Player folder) and in the inspector tick the LocalPlayerAuthority box.

LocalPlayerAuthority

Next, with your player prefab still selected, add a RigidBody component (Component->Physics->RigidBody). untick Use Gravity and set Constraints as follows:-

Now we need to add to the player a network component that will do the work of synchronizing our player’s position and rotation across the network. So with the player prefab selected, add a NetworkTransform component (Component->Network->NetworkTransform).

We need to check that the Transform Sync Mode is set to Sync RigidBody 3D, and we need to change the Rotation Axis to Y (Top Down 2D) as that is the only axis we will be rotating on, and it saves sending unnecessary network data. We’ll also change the Interpolate Rotation value from 1 to 10, otherwise the rotation on remote clients is very slow to catch up.

Your NetworkTransform component should look like this:-

PlayerNetworkTransform

Now comes some code, create a new script in the Assets/Player folder and call it PlayerNetworkMove and paste this code into it replacing the default code then save the file.

Now we need to add this script to the player prefab, so with the player prefab selected use the Component menu to add the script (Component->Scripts->PlayerNetworkMove) or just left click the script and drag it onto the player prefab.

This is a fairly simple script that reads keyboard input and the uses the result from the WASD key presses to rotate the player and move it forward and backwards in the direction it’s facing. Whilst this works perfectly well for a single player game, you will see if you build and run the game and run a host and client, that you have problems with it in a multiplayer game. As you move and rotate one player the other player also moves and rotates. This is because the PlayerNetworkMove script is running on every instance of the player in the scene. So we need to make a couple of changes to fix this.

Firstly we need to add UnityEngine.Networking to the list of using statements at the top of the code and then we need to change our class type from MonoBehaviour to NetworkBehaviour.

Making these changes gives us access to all the new networking features introduced in Unity 5.

Next we need to make sure that we only read the input from the local player  and only manually move the player object owned by the local player. As our script is now a NetworkBehaviour, it has a boolean property called isLocalPlayer, which will only be true for scripts that are running on the client that owns the player object. So we can check the value of that and act accordingly.

Change the Update function to this

This checks to see if the script is running on the local player, and if not it just returns without doing anything else, otherwise it gets the player input as before.

We also need to add the same check to the FixedUpdate function, as so

If the script isn’t running on the local player, fixed update will return without doing anything, otherwise it will move the player as before.

The player position and rotation for the local player is automatically synchronized with all the other clients by the NetworkTransform component we added earlier, so we don’t have to worry about that.

This is the full network aware PlayerNetworkMove script

With this script on the player object, you can build and run two instances of the game and start a host and client. You’ll see two cubes in the scene, both of which can be controlled independently of each other, and as you move a player in one client it is updated in the other client.

That’s it for part 2 of the tutorial, in the next part we will make the camera follow the player, and give each player its own name and name label.

Unity 5 Network Tutorial Part 1

Part 1

What is this tutorial?
This tutorial aims to demonstrate the basic concepts needed to create a multiplayer game. In an attempt to keep it as clear and concise as possible I will keep the game design quite simple, therefore this should be seen as a basis from which to build a game, rather than a tutorial for a complete and finished game.

Who is this tutorial aimed at?
This is aimed at people with a reasonable knowledge of C# and Unity, but little or no experience of network game programming. As such I won’t be explaining in depth basic C# programming concepts or basic Unity concepts, unless it is appropriate within the scope of the tutorial. I also won’t be delving too deeply into the complexities of networking, I’ll just explain enough to cover what we do in the tutorial which should hopefully give enough information to go on from here.

Notes
For the Unity editor layout I will be using the default Tall layout (Window->Layouts->Tall), but with the Game Window docked beneath the Scene Window, however you are free to use whichever layout you are most comfortable with.
Any names I suggest for things such as project names, scene names and gameobjects etc. are completely arbitrary, and you can change them if you wish. However if you do change them you need to make sure you also change any references to them that may come up later in the tutorial to avoid errors.
For ease of following this tutorial I would suggest you probably just go with my names for now.

Part 1a Setting up the project and scenes

  1. Start by creating a new 3D project and call it Unity Networking Tutorial.
  2. Create a folder in Assets, and name it Scenes
  3. Save the current scene into the Scenes folder, and name it Online Scene
  4. Save the current scene again into the scenes folder, but this time call it Offline Scene

SaveScene

Now add the Offline and Online scenes to the build settings, if we don’t do this we will be unable to use them with the NetworkManager in the next step.

BuildSettings

Part 1b Setting up the NetworkManager scenes

Now we’ve got the empty scenes saved and added to the build settings, we need to start populating them with gameobjects. The first thing we need is a Network Manager, which fairly obviously manages the network, so we’ll add that now.

With the Offline scene open (it should already be open, if you followed the above instructions), create an empty gameobject (GameObject->Create Empty) and rename it NetworkManager. Now with the NetworkManager gameobject selected in the hierarchy use the Component Menu to add a NetworkManager and NetworkManagerHud component.

ComponentMenu

NetworkManagerComponentsOnce you have added these components your NetworkManager gameobject should now look like this.

The NetworkManager component will handle the nitty gritty of the network connection between all the players, and has various settings exposed in the inspector, only some of which we need to worry about for this tutorial.
I’ll cover these as we go along and explain what they do.

The first thing we need to look at in the NetworkManager is the Offline Scene and Online Scene settings.
The Offline Scene is where we will show the menu that will allow players to host or join a game, and the Online scene is what will load when the player joins a game (either as a host or client). This switching of scenes is handled automatically by the NetworkManager.
Strictly speaking there is no need to have separate scenes for this, however by doing so you will save yourself some possible headaches later.

So with that in mind, go ahead and drag the Offline Scene from the scenes folder in the project window and drop it onto the Offline Scene entry in the NetworkManager, then do the same for the Online Scene and drop that into the Online Scene entry in the NetworkManager.

The NetworkManagerHUD is solely for the purposes of displaying a basic menu that allows hosting and joining of game sessions. I intend to make another tutorial at a later date that shows how to implement your own UI instead.

Part 1c Setting up the player prefab

Now we have set the scenes up, we need to create a gameobject that will be our player in the game. For this tutorial we will just use a 3d Cube which we can create using the menu option GameObject->3D Object-> Cube.
Once you have added the cube to the scene, rename it to Player and set it’s transform and rotation to 0,0,0 if it isn’t already.

PlayerSceneHierarchyYour scene Hierarchy should now look like the picture to the left.

Before your player object can be used in a network game it has to have a NetworkIdentity component attached to it. The NetworkIdentity component controls an object’s network identity, and it makes the networking system aware of it.

Attach a NetworkIdentity component to your player by selecting the player and then using the menu item Component->Network->NetworkIdentity.

Your player should now look like this…

PlayerNetworkIdentity

Now we need to create a prefab of the player object, so firstly create a new folder under Assets and name it Player, then drag your player object into this folder to create a prefab of it there. You can now delete the original from the Hierarchy.

Now we need to tell the NetworkManager about your player, so it can spawn you into the game when you start a host or join a game.
To do this, find the Spawn Info section of the game manager and if necessary, expand it by clicking the small triangle to the left of the words Spawn Info.
Under Spawn Info you will see an entry for Player Prefab. Drag the player prefab you just created into the Player Prefab slot in the NetworkManager.

Your NetworkManager should now look like this

NetworkManagerPlayerPrefab

At this point, we’ve got the bare minimum needed to run the game and host or join a session.
You can test this now if you like. If you run the game you will be presented with a menu (courtesy of the NetworkManagerHUD component) that allows you to host a game, join a game or start as a server (ignore the matchmaker option for the time being).

NetWorkHUD

If you build the game you can run two instances of it and host a game in one, and join the game in the other.

For now all that will happen is that the menu will change to show the connection status and a disconnect button, and you’ll see a cube in the centre of the game scene (both player objects spawn exactly on top of each other). Not so obviously, the active scene will have also changed to the Online scene you created at the start of the tutorial.

That’s everything for Part 1 of the tutorial, without writing a single line of code we have the basic framework of a multiplayer game up and running!

In the next part we will set up the online scene, handle spawning the players in differing locations, and enable moving them based on player input.