Master Server
The Master Server is a meeting place for games that are actively seeking clients, and player clients who want to connect to them. Its purpose is also to hide IP address and port details and perform technical tasks around setting up network connections which might otherwise not be possible, like firewall handling and NAT punch-through.
Each individual running game server provide a Game Type to the Master Server. All games with a matching Game Type are gathered together so that compatible clients can easily view them. When a player connects and queries the Master Server for their matching Game Type, useful information on the server is displayed for the player to see. This helps the player decide which server to connect to. This includes the Game Name, player count and whether or not a password is needed. The two functions used to transmit this data are MasterServer.RegisterHost() for the Server, and MasterServer.RequestHostList() for the player client.
When calling RegisterHost(), you need to pass three arguments - gameTypeName (which is the previously mentioned Game Type), gameName and comment - for the host being registered. RequestHostList() takes as an argument the gameTypeName of the hosts you are interested in connecting to. All the registered hosts of that type will then be sent to the requesting client. This is an asynchronous operation and the actual host list can be retrieved with PollHostList() which returns the list when it has arrived.
The NAT punchthrough portion of the Master Server is actually done by a separate entity called the Facilitator. The central Unity Master Server is also running a Facilitator in addition to being a game lobby so it is OK to think of these functionalities as simply Master Server functionalities in that context.
The Game Type you set for your game should be unique for your game. This is to prevent clients running a completely different game from seeing your servers and trying to connect to them. So don't use "Game1" or anything generic like that as the gameTypeName. Be specific and unique. If you have different versions of your game out, you could use the comment field to relay that information. That way the client will know if their version is incompatible with some servers in the host list. The comment field can also be used to relay any information you desire. It is a binary data field and can store objects, you just need to cast them properly yourself.
More advanced functionality can be done by using the comment field and customizing the Master Server so that it will use that information itself. For example you could reserve the first 10 bytes of the comment field for a password and then extract the password in the Master Server when it receives the host update. It can compare and reject the host update if appropriate (password check fails). Of course this would require editing of the Master Server source code itself, but this can be downloaded and modified. For more information about this, skip down the page to the Advanced Section.
Registering a game
Before registering a game it is important to set the NAT functionality properly by setting useNat parameter for Network.InitializeServer to true or false depending on the networking capabilities of the host. The user hosting the game should know if he has a NAT address or not and if the game port is connectable on the public internet, so before hosting the game he will indicate if NAT assistance is needed or not.
A server might be started with code similar to this:
function OnGUI() { if (GUILayout.Button ("Start Server")) { // Use NAT punchthrough if no public IP present Network.InitializeServer(32, 25002, !Network.HavePublicAddress()); MasterServer.RegisterHost("MyUniqueGameType", "JohnDoes game", "l33t game for all"); } }
Here we just decide if NAT punchthrough is needed based on if the machine has a public address or not. There is a more involved function available called Network.TestConnection() which can tell you if the host machine can do NAT or not. It also does connectivity testing for public IP addresses to see if a firewall is blocking the game port. Machines which have public IP addresses always pass the NAT test but if the test fails then the host will NOT be connectable to NAT clients. In such a case the user needs to be informed that in order to host a game he needs to set up port forwarding if possible. Usually people with cheap broadband connections will have a NAT address and not be able to set up port forwarding (as they don't have a personal public IP address at all). In these cases, if the NAT test fails, the user should be informed that running a server is inadvisable as no one but clients on the same local network will be able to connect.
If a host enables NAT functionality without needing it, no harm is done and it will still be connectable, however, client which cannot do NAT punchthrough will think they cannot connect to him as he has NAT enabled.
Connecting to a game
The host information, HostData, object sent during host registrations or queries contains the following information:
boolean | useNat | Indicates if the host uses NAT punchthrough. |
String | gameType | The game type of the host. |
String | gameName | The game name of the host. |
int | connectedPlayers | The amount of currently connected players/clients. |
int | playerLimit | The maximum amount of allowed concurrent players/clients. |
String[] | IP | The internal IP address of the host. On a server with a public address the external and internal addresses are the same. This is an array as when connecting internally, all the IP addresses associated with all the active interfaces of the machine need to be checked. |
int | port | The port of the host. |
boolean | passwordProtected | Indicates if you need to supply a password to be able to connect to this host. |
String | comment | Any comment which was set during host registration. |
String | guid | The network GUID of the host. This is needed when connecting using NAT punchthrough. |
This information can be used by clients to see the connection capabilities of the hosts. When NAT is enabled you need to use the GUID of the host when connecting. This is automatically handled for you when you connect to the HostData struct directly. The connect routine might look something like this:
function Awake() { MasterServer.RequestHostList("MadBubbleSmashGame"); } function OnGUI() { var data : HostData[] = MasterServer.PollHostList(); // Go through all the hosts in the host list for (var element in data) { GUILayout.BeginHorizontal(); var name = element.gameName + " " + element.connectedPlayers + " / " + element.playerLimit; GUILayout.Label(name); GUILayout.Space(5); var hostInfo; hostInfo = "["; for (var host in element.ip) hostInfo = hostInfo + host + ":" + element.port + " "; hostInfo = hostInfo + "]"; GUILayout.Label(hostInfo); GUILayout.Space(5); GUILayout.Label(element.comment); GUILayout.Space(5); GUILayout.FlexibleSpace(); if (GUILayout.Button("Connect")) { // Connect to HostData struct, internally the correct method is used (GUID when using NAT). Network.Connect(element); } GUILayout.EndHorizontal(); } }
This example code prints out all the relevant information of the hosts returned by the Master Server. Other useful data like ping information or geographic location of hosts can be added to this.
NAT punchthrough
Bear in mind that NAT punchthrough will not work 100% of the time so certain machines are not suited to run as servers as some clients can connect to them and certain client might have trouble connecting to any NAT server.
By default NAT punch through is done with the help of the Master Server but this functionality does not need to rely on the Master Server. The Facilitator is the one who is actually used for the NAT punchthrough routine. If two machines are connected to the Facilitator, one can directly connect to the other if as long as it uses the external IP and port. The Master Server is used to provide this external IP and port information which is otherwise hard to determine. That is why the Master Server and Facilitator are so tightly integrated. The Master Server and Facilitator have the same IP address by default, to change either one use the MasterServer.ipAddress, MasterServer.port, Network.natFacilitatorIP and Network.natFacilitatorPort
Advanced
The Master Server is a completely separate entity from the Unity editor itself. It can be deployed on Windows, Linux and Mac OS, and anyone can have their own Master Server. Unity Technologies has a dedicated Master Server available for anyone to use which is the default server used.
There might be cases where you want do modify how the Master Server handles information and how it communicates. Maybe you need to do some optimizations of how the Master Server handles host data information from the individual game servers. Maybe you need to limit how many hosts the clients will receive when they request the host list, either numerically or through some kind of filter like location. This would mostly be bandwidth optimizations but anything can be done as long as it communicates properly with the Unity player.
To perform any of these modifications, you must build, deploy, and host your own Master Server. Information about how to do this can be found on the Master Server Build page.
Page last updated: 2010-09-25