Quickstart

The goal of this section is to be short, easy to follow, and closer to a tutorial than reference documentation. If someone follows the instructions on this page, they should be up and running with an example client and server, with a bit of guidance on where to go next to start adding their own game logic.

To start, download the latest version of the Client and Server projects.

Running the Server

  1. Open the Server project and load the scene called “Server”
  2. Hit play.

By default, the server will run on port 603 (the area code for New Hampshire). The example server logic will automatically approve all connection requests.

Running the Client

  1. Open the Client project and load the scene called “Client”
  2. Hit play.

Connecting to the server

The client will allow you to enter the IP address and port of the server. If you are running the server locally with default settings, you can enter “127.0.0.1” for the IP address and “603” for the port.

The connection process starts by sending a request to the server to connect. The default server logic will automaitcally approve all connection requests, and your client will be approved. Once your client is notified that it has properly connected to the server, it will add itself to area 1 (see the section on area filtering for more information), spawn its own “Player” object and add the player object to area 1.

To test with more client connections, you should build the client project and run it outside of the Unity editor.

TODO: This should be a quickstart guide to use the networking library. A short tutorial on how to get an example client and server project, as well as set it up so they can connect to each other, as well as simple examples of RPCs and Networked Objects should be included.

TODO: What is the process of creating a custom server? What considerations are needed when developing a server?

TODO: What is the process of creating a custom client using this library? What considerations are needed when developing a client?

Project requirements

This library was updated to support Unity version 2018.2.2f1, but may work with newer versions.

Connection and Disconnection

Connecting to a server

TODO: Discuss the process of connecting to a server, including the specific messages between the client and server. Discuss requirements when connecting via IP, as well as opening a port on the server. How are other clients notified, if at all, that a client has connected to the server? Discuss the process of a server confirming or denying a connection, and an example on how a server could check with an external resource to determine if a client should connect (such as checking with a database, steam servers, etc).

Unique Client Ids

TODO: Discuss how each client is assigned a unique id. How would the game logic on the server get this id, and how would it use this id?

Disconnecting from a server

TODO: Discuss the process of disconnectng from a server, including the specific messages between the client and a server. How are other clients notified, if at all, that a client has disconnected from the server? and the server kicking a client.

From the client

TODO: Discuss the different ways a client can disconnect: Connection timing out (in case of client crashing/closing abruptly) or the client requesting a disconnection

Kicking a client

TODO: Discuss how the server can kick a client

Networked Objects

Networked objects (as well as RPCs), make up the bulk of what the networking library supports. Most full games will be built using a combination of networked objects, as well as remote procedure calls. Knowing when to use one over the other is entirely up to the developers of the game, but some best practices can guide those decisions.

In general, a networked object is a game object which is instantiated on every client connected to the server. As the object moves on one client, information about it’s transform is automatically sent through the server to the other connected clients. A simple example of this may be a game object representing a player’s main character. When the game object representing the character is instantiated, it will automatically be created on all other clients connected to the server. As the player moves their character in the simulation, the game object representing that character on all of the other clients will move as well, keeping all of their positions and rotations in sync.

Instantiating

Instantiating a network object is similar to instantiating any other object in Unity, with a few minor differences. First, use the Instantiate method found in ClientNetwork, instead of Unity’s built-in Instantiate method. The first parameter of this method is the string name of a prefab you would like to instantiate. This string name will be sent to the server, as well as any other clients which need to instantiate the object. For Unity to properly instantiate the object, a prefab with that name must be in a Resources directory.

Note: Loading objects from within a Resources directory based on their names is no longer recommended by Unity (but is still fully functional). It will be worth exploring updating this logic to instead use one of Unity’s newer systems for dynamic asset loading, like Addressables or Asset Bundles.

The server can spawn objects in a similar manner, however, please see the documentation on ownership to understand how server-instantiated objects behave.

Networked objects need to have the NetworkSync component. This component assists the networking system by tracking a unique id for the object, handling remote procedure calls, as well as handling object synchronization messages. If you do not feel that your object needs these features, then it may be better to call an RPC to AllClients and have them all instantiate local objects.

All networked objects have unique ids associated with them, which assists the networking system in sending messages about specific objects to all clients. One feature of UCNetwork is that local object instantiation happens synchronously, meaning it will immediately instantiate an object on your local client when you call ClientNetwork.Instantiate. In order to accomplish this, while still having unique object ids across the entire network, every client is given a pool of unique ids (default is 500). When a client instantiates an object, it picks a free id in the id pool it has been given and tells the server which id it has chosen for the new network object. The server tracks the size of each client’s pool of ids and will send additional ids to a client when it starts running low.

Destroying

When a networked game object is destroyed, it need to inform the server (which will inform the other clients) that the object needs to be removed from the simulation. As objects are destroyed, the NetworkSync calls ClientNetwork.Destroy, which will send a message to the server that the object should be removed from all clients.

Note: What happens when a client who does not own an object tells the server that it has been destroyed?

Network Sync Component Details

TODO: What does a network sync component provide? Why is it required? What callbacks does the network sync component provide to the object it is attached to, if any, and what additional functionality does it provide? How can you add additional data to the Network Synchronization Messages? What is a LiteSync message?

Remote Procedure Calls

TODO: Discuss sending remote procedure calls to a single game object. Discuss how sending a RPC to a single game object works, and why you would use it. More detail regarding RPCs will be provided in the RPC documentation.

Smooth Movement

TODO: Discuss network interpolation and extrapolation. Why is this needed? How does it account for lag? What considerations would need to be make regarding objects with physics, or fast paced action games?

Ownership

All networked game objects are “owned” by an individual client.

Default Ownership

TODO: Discuss how ownership is assigned to networked game objects as they are spawned, both from the client and server.

Ownership Transferring

TODO: Discuss how and when ownership of game objects is transferred between various clients. Discuss why we would want to transfer ownership (as clients are leaving areas, disconnecting, or based on gameplay).

Remote Procedure Calls (RPCs)

Overview

Remote Procedure Calls are a simple way to fit networking interactions into a typical game’s code structure. They can be conceptualized to work the same way as normal function calls, but initiated by a remote machine. Once communicated across the network, RPCs use reflection to find and invoke the matching method on the receiving object (indicated by the object’s network ID).

RPCs are commonly used for individual descrete actions within a game: when a player casts a spell, presses a button, opens a door, etc. Unlike the object synchronization methods, RPCs act very similarly to local function calls.

Format of an RPC

Remote procedure calls start with a message to the server. Included in this message is:
  • The name of the function to execute
  • The object that contains a component with the function to execute
  • Which clients should execute the function
  • Any additional parameters to the function

As an example: If a component on a networked game object, or the object that has the ClientNetwork or ServerNetwork component, had the following function:

public void ExampleFunction(int number, string word) {
    Debug.Log(number);
    Debug.Log(word);
}

you could call this from another machine connected to the game like this:

clientNetwork.CallRPC("ExampleFunction", MessageReceiver.AllClients, -1, 101, "Hello");

this would send a message to the server, which would then cause the server to send a message to all connected clients, which would then execute the ExampleFunction method on the same object that has the ClientNetwork script passing the parameters 101 and “Hello”.

The CallRPC function is defined in the ClientNetwork and ServerNetwork scripts as:

override public void CallRPC(string aFunctionName, MessageReceiver aReceiver, int aNetworkId, params object[] aParams)

The parameters to this function are: the name of the function to be executed, which clients should execute this function, the network id of object that should execute the function, and then any number of parameters that should be passed to the function.

Defining new remote procedure calls is easy, as they are written exactly like new C# methods.

RPCs from the client

TODO: Discuss calling RPCs from the client to the server. Examples on why you would do this.

Calling RPCs from a client can be done in two ways. The first is using the CallRPC method found in ClientNetwork. The second is using the CallRPC method found in the NetworkSync component on a networked game object. Both methods have the same results and parameters, with the version within the NetworkSync component assuming that the game object is the one that should be executing the funtion on remote machines.

RPCs from the server

TODO: Calling RPCs from the server to the clients (or single client). Examples on why you would do this.

Determining where an RPC goes - MessageReceiver

TODO: Discuss the different options for the MessageReceiver parameter for the CallRPC function. What does each of them mean, and why would you use each? (ServerOnly = 1, AllClients = 2, OtherClients = 4, AllClientsInArea = 8, OtherClientsInArea = 16, SingleClient = 32)

Supported Data Types

TODO: Discuss the data types that the networking library allows you to send. Discuss how to add additional data types (WriteRPCParams and ReadRPCParams).

RPCs from one client to another

TODO: Discuss how and why clients would call RPCs that arrive to a single other client. Discuss why this isn’t natually supported by the networking library.

Area Filtering

The concept of “area filtering” allows the networking library to send data to specific groups of clients. For example, if client A, B, and C are in a dungeon while client D is back in town, you probably don’t need to send the data relating to what is going on in the dungeon to client D.

Examples

Rogue

TODO: Describe why this system would be used for a character who could hide themselves from other players

Team Chat

TODO: Describe how this system could be used for handling something like team chat, where a specific group of players should be able to communicate with each other

Virtual Areas

TODO: Describe how and why this system could be used for supporting different locations in a larger game, such are multi-floor dungeons, and clients who have completely different scenes loaded

Using Area Filters

TODO: Describe how to use area filtering, including adding clients and networked game objects to areas, removing them from areas

Synchronizing Game State

TODO: With clients in different areas, describe how clients are told the current state of an area when adding themselves to an area which already has networked game objects, etc.

Voice Chat

Getting Started

TODO: How to get started with online voice chat

Voice Chat: A Primer

TODO: Describe how voice chat communication over the internet works in a general sense, which includes recording microphone data, compression, serialization, and playing the audio on a recieving client at the proper location.

Using Voice Chat

TODO: Details on this voice chat integration, which was initially built by FHolm. The original voice chat library can be found here: FHolm Old Unity Assets. Describe any changes and modifications from the original version

ThreadedJob - Multiple Threads in Unity

TODO: How does the ThreadedJob functionality work? Examples on how it could be used elsewhere

Additional Features

TODO: Describe any additional features the library supports? What features are these, how do you use them, why would you use them?

Client Development

TODO: Describe best practices for developing a client. This section may include any topics relating to client development that don’t fit in with the rest of the documentation, including pro-tips, guidance, or other recommendations.

Server Development

TODO: Describe best practices for developing a server. This section may include any topics relating to server development that don’t fit in with the rest of the documentation, including pro-tips, guidance, or other recommendations.

Example Projects

Tactics Server

Example of the gameplay

How the server is developed

Post the challenge of developing the client

Tic-Tac-Toe

Overview

This is an overview of Tic-Tac-Toe, and how this example has been developed. Example RPCs and diagram on players. Support for spectators and different players reokacing

Server

Client

License

MIT License

UCNetwork Network

Overview

This is an authoritative client-server networking library for Unity3D, built using Lidgren.

Features

  • Online multiplayer!
  • Real-time messaging and object synchronization for Unity3D
  • Authoritative, dedicated, and standalone server support
  • Support for clients with different codebases, and asymmetrical experiences
  • Message filtering based on logical “Areas”
  • Open world games, or simulations where clients are in different scenes
  • Networked object ownership transfer
  • Easily hook up your own functionality for:
    • Storing game state when clients disconnect
    • Authorizing player connections based on external systems
    • Server-side gameplay logic
  • …and more!

Additional Help and Contact

This library was developed by David Carrigg, with contributions from the rest of the development team that worked on the now cancelled game, Upsilon Circuit. You can find various ways to contact me on my website.

Can I use this library for my project?

Probably! This software is licensed with the MIT License.

Have fun!