CONNECTING CLIENT AND SERVER
CONNECTING CLIENT AND SERVER
Before you can begin building a networked game, you have to determine the different computers that will communicate. It is convenient to use one server version of each scene in a Unity project and one client version of each scene. This is handy when you later on will publish them to two different computers, and you can exclude the client scenes from the server build, and exclude the server scenes from the client build.
Creating a server
The server could be a player client with the additional responsibility of hosting the game, or it could be a
dedicated server that is only used to host the game. To create the server, all you have to do is to call
uLink.Network.InitializeServer() from a server script. You must specify a maximum number of clients that are allowed to connect, before they are automatically blocked, and a local port that clients should use to connect to the server.
This single call sets up all the necessary configuration that is needed to run a game server.
Creating a client
When you want the client to connect to an existing server, you call
uLink.Network.Connect() from a client script. You must give the server address and port number, and a server password. If you don't want to use a server password, which is the default, just send an empty string.
This call sets up everything in the game client, making it ready to begin communicating with the server, sending/receiving state-synchs and RPCs.
Detailed connection sequence
During the client-server connection process, there is a sequence of events that happen in order. By understanding this sequence, you get fine-grained control over how clients are allowed to connect to the server, and what the side-effects of the connection are.
- The server procedure begins with the server calling uLink.Network.InitializeServer().
- Before anything is initialized on the server, the callback uLink.Network.uLink_OnPreStartNetwork() is invoked, with the uLink.NetworkStartEvent parameter set to Server. This can be used to set up final configuration parameters for the network. Once this callback finishes, uLink goes on to initialize the server network connection, making it ready to handle incoming client connections.
- When the initialization is complete the callback uLink.Network.uLink_OnServerInitialized() is invoked. Use this to start up any additional server logic that need an initialized network, but not a client connection.
- The client procedure is initiated by the client calling uLink.Network.Connect(), giving the server address and port, and a server password as parameters. Any additional parameters in this call will be sent to the server as login data, which could be anything the server expects to know before allowing the client to connect. For example the server might want to know the client version, player name, etc.
- Just like with the server, before the client connection is initialized, the callback uLink.Network.uLink_OnPreStartNetwork() is invoked, with the uLink.NetworkStartEvent parameter set to Client. Use this to set up client network configuration. Once the callback finishes, the client attempts to connect to the server.
- When the connection request reaches the server, uLink invokes the uLink.Network.uLink_OnPlayerApproval() callback, where the server can evaluate the login data before deciding to approve the client. The callback receives a uLink.NetworkPlayerApproval object, which can be used to approve or deny a client connection. This is done by either calling uLink.NetworkPlayerApproval.Approve() or uLink.NetworkPlayerApproval.Deny(). The login data is stored as a uLink.BitStream in uLink.NetworkPlayerApproval.loginData. If the connection is approved it is possible to send any number of parameters as approval data back to the client, by appending them to the method call. This data could be anything the client needs to know to set up gameplay, like for example which scene the server is running. If you don't implement the uLink.Network.uLink_OnPlayerApproval() callback, or if you implement it but don't call either Approve() or Deny(), the client is automatically approved. If the connection is denied, the server should give a uLink.NetworkConnectionError value that specifies the reason to the client.
- If a connection approval reaches the client, uLink invokes the uLink.Network.uLink_OnConnectedToServer() callback. This is essentially saying that the client is good to go and should initiate gameplay. If the client is denied a connection, uLink invokes the uLink.Network.uLink_OnFailedToConnect() callback instead, with the server-given uLink.NetworkConnectionError that gives the reason. This allows the client to present an error message to the player.
- If the client connection was approved, the server completes the connection setup and then uLink invokes the uLink.Network.uLink_OnPlayerConnected() callback. This is saying that the server now has a new connected player and that it should be included in the gameplay. This is a good place to instantiate player objects.
- If the client was successfully connected, and if security has been enabled for this client connection, then the callback uLink.Network.uLink_OnSecurityInitialized() is invoked on both the client and server. This signals that the connection has been secured.
- The final step in the client connection procedure, is that it receives a list of buffered RPCs from the server. Before these are executed, uLink calls the callback uLink.Network.uLink_OnPreBufferedRPCs() where the client has a chance to inspect the RPC list and decide which should be executed, and when.
Detailed disconnection sequence
The process of disconnecting the client and server from each other is simpler than the connection sequence. There are fewer callbacks involved, since disconnection is not as configurable as connection, and the main purpose of these callbacks is to let both sides respond to a shut down/lost connection.
- Disconnection can be triggered willingly by either the client or the server to terminate an open connection. The client should call uLink.Network.Disconnect(). The server can call either uLink.Network.CloseConnection() which terminates the connection to one client, or uLink.Network.Disconnect() which will shut down all open connections to clients. Disconnection is also triggered when the connection is lost, either if the client or server stops to respond or crashes, or if the network link fails. Note that if the client or server is shut down during an open connection, uLink will take care of the disconnection behind the scenes, so that both ends of the connection are properly closed.
- On the client the uLink.Network.uLink_OnDisconnectedFromServer() callback is invoked, with a uLink.NetworkDisconnection value indicating the reason. At the minimum, the client should use this callback to display a message to the player that it was disconnected from the server.
- On the server the uLink.Network.uLink_OnPlayerDisconnected() callback is invoked, with an argument saying which uLink.NetworkPlayer it refers to. This is a suitable place to clean up player resources, using the uLink.Network.RemoveRPCs() and uLink.Network.DestroyPlayerObjects() methods.
- If the server is shutting itself down, the last uLink callback it will call is uLink.Network.uLink_OnServerUninitialized(). This signals that all network-related resources has been returned to the OS and that uLink is no longer active.