By Hugo Scott-Slade, Technical Director
In the last post we covered how to setup a multiplayer game with customisation. We have all players in the lobby setup with their data. In this post we will cover the following:
- Determining when a scene has loaded with all the components we need.
- Transferring data from lobby players to game players.
- Setting up all players in the game scene.
- Clients send message to server when they have fully setup.
OnLevelWasLoaded in conjuction with the
NetworkLobbyManager to determine that the player has either entered the lobby or entered the game. Our focus is on the latter.
I was noticing an issue when I was using the
NetworkStartPosition that comes with UNet. The issue was sometimes a player object would spawn at the center of the world and not the spawn positions that were setup. After digging through the source code and running some tests it was apparent that the code that created the game player was running before the
NetworkStartPositions had registered themselves with the
NetworkManager. Even though the
NetworkStartPositions register themselves in
Awake the call to
OnLevelWasLoaded was executed before that. The code within
NetworkLobbyPlayer that tells the server that the scene was loaded was running before the scene was ready to be used.
There are certain objects within the scene that also need to be loaded and setup in our game before the
SendSceneLoadedMessage funciton should be run. That will be different from game to game but I created a solution that I think we will work for most cases.
All objects that are required to be setup before running the code for the new scene either implement the
ISceneDependency interface or extend the
SceneDependencyBehaviour class. Additionally a
SceneDependencyManager must exist in the loaded scene already. The manager keeps a reference to all
ISceneDependency objects and will run
OnSceneWasLoaded when all dependencies have reported that they are ready. Full source code is available here on Github.
Here is our version of the
NetworkStartPosition which I’ve called
NetworkSpawnPosition which extends the
Transferring data to game players
In part 1 we covered getting the player data for everyone in the lobby and now we are ready to create the game player. The next challenge is passing the data between the lobby player and the game player. UNET has a simple method the is called with both the lobby and game player objects allowing us to setup players for the game easily. However this is only called on the server so any setup the client needs to do has to be handled another way. A simple way to handle this is to create a
SyncVar on the lobby player and copy that value into a
SyncVar on the game player.
Setting up the player
Now when the game player calls
OnStartClient the client can take the shared identifier (we use
m_PlayerNumber) and find the matching lobby player. With that they have access to all the data we syncronized in part 1 and the players will have the correct name and color for every player.
A benefit of this system is that any time a new game player needs to be made the data needed for their setup doesn’t need to be sent again. Players can return to the lobby, change the map and play again without having to transmit some potentially sizeable data. UNet has a bandwidth limit of 4kbp/s before it will disconnect players but the limit for the first 2 minutes is 40kbp/s to allow for any expensive setup.
Starting the game
It’s important that the server starts the game when all the connected players have fully setup their instances of the game. We know that the scene is setup correctly as we did this earlier and we know that was can setup each player in each game instance correctly but theres some more we need to setup before the game can begin. Let’s consider just one instance of the game for ease of understanding.
When you are setting up your local instance of the game the instructions won’t always arrive from the server in the same order. When you first start with developing games over the network this can be one of the toughest realities to wrap you’re head around. The server can send instructions to create Player A, B and C but your game could process them in any order – remote players could be created in your game before you are.
Here is a snippet of code from our
NetworkLobbyManager that our
Player class invokes methods on. This code will only run on clients and is called from
The server will do a similar thing and keep a record of all clients that have send their ‘game scene ready’ message, then once all players are ready the server will send the message telling all players to start their games.
This concludes the game setup with lobby and player customisation. Using the HLAPI for UNET is a great way to get started in networking with Unity and I hope these posts could help you understand a possible way to get started with a real world game example.