Client messages

Overview

Client messages are a form of commands that are used for client-to-client communication rather than client-to-entity. To achieve this type of communication a special connection entity is automatically created by the replication server for each connected client. Those entities are subject to a different rule set than standard entities. Connection entities:

  • Can't be created or destroyed by the client - they are always replication server-driven

  • Are global - they are replicated across clients regardless of the in-simulation distance or live query radius

Client messages shine whenever there's a need to communicate something to all the connected players. Usage examples:

  • Global chat

  • Game state changes: game started, game ended, map changed

  • Server announcements

  • Server-wide leaderboard

  • Server-wide events

Enabling client messages

The globality of client messages doesn't fit all game types - for example, it rarely makes sense to keep every client informed about the presence of all players on the server in an MMORPG (think World Of Warcraft). Due to this reason, client messages are turned off by default. To enable client messages:

1. Turn on the global query in the Coherence MonoBridge (the Global Query On toggle)

Global query enables querying for entities containing a global component, including a connection entity.

Disabling global query on one client doesn't affect other clients, i.e. connection entity of this client will still be visible to other clients that have the global query turned on.

2. Create a class that inherits from the CoherenceClientConnection class

Under the hood, client messages are nothing but commands sent between the connection entities. Each such entity is represented on the client side by an instance of a CoherenceClientConnection class. Implementing client messages is as simple as adding a new command to our custom connection class:

public class PlayerConnection : CoherenceClientConnection
{
    // My chat command
    public void OnChatMessage(string message)
    {
        Debug.Log($"Received chat message: {message}");
    }
}

Next, we have to create a binding:​

3. Create a client connection prefab

This step is described in detail in the Prefab setup section. In short, a prefab with CoherenceSync and our PlayerConnection must be created and placed in the Resources directory:​

For the system to know which object to create for every new client connection, we have to link our prefab to the Coherence MonoBridge. Simply drag the prefab to the Client Connection Prefab field in the MonoBridge inspector:​

Connection management

Once we have everything set up, whenever a new client joins an instance of the connection prefab will be created. The instantiated object resembles a client connection and will be kept alive for as long as that client remains connected to the replication server.

To get notified about the creation and destruction of connections we can use the following events:

public class GameManager : MonoBehaviour
{
    public CoherenceMonoBridge MonoBridge;

    private void Start()
    {
        MonoBridge.OnConnectionCreated += OnConnectionCreated;
        MonoBridge.OnConnectionDestroyed += OnConnectionDestroyed;
    }

    private void OnConnectionCreated(CoherenceClientConnection clientConnection)
    {
        Debug.Log($"Client connected: {clientConnection.Id}");
    }

    private void OnConnectionDestroyed(CoherenceClientConnection clientConnection)
    {
        Debug.Log($"Client disconnected: {clientConnection.Id}");
    }
}

The connection ID is simply an EntityID of the connection entity.

To get local connection or connection of any client by the ID use the following MonoBridge methods:

PlayerConnection myConnection 
    = MonoBridge.GetMyConnection<PlayerConnection>();
    
PlayerConnection otherPlayerConnection 
    = MonoBridge.GetClientConnection<PlayerConnection>(otherPlayerId);

A null may be returned by both methods if client messages are not enabled or the connection with a given ID doesn't exist.

The CoherenceClientConnection class exposes the following properties:

PlayerConnection playerConnection = MonoBridge.GetMyConnection<PlayerConnection>(id);

// ID of the connection (and connection entity)
SerializeEntityID connectionId = playerConnection.Id;

// True if this is connection belongs to the local client
bool isMyConnection = playerConnection.IsMyConnection;

// CoherenceSync of the connection object
CoherenceSync sync = playerConnection.Sync;

Sending client messages

Client messages are sent using the SendClientMessage method of the CoherencePlayerConnection class:

private void OnConnectionCreated(CoherenceClientConnection clientConnection)
{
        clientConnection.SendClientMessage("OnChatMessage", MessageTarget.AuthorityOnly, "This is a private message");

        clientConnection.SendClientMessage("OnChatMessage", MessageTarget.All, "This is a global message");
}

The first message will be delivered only to the player that owns the created connection. The other message will be delivered to all instances of this connection, that is, every player (including the sender) that knows about this connection will receive this message.

If the connection ID of the message recipient is known we can use the MonoBridge to send a client message:

private SerializeEntityID newestConnectionId;

private void OnConnectionCreated(CoherenceClientConnection clientConnection)
{
    if (!clientConnection.IsMyConnection)
    {
        newestConnectionId = clientConnection.Id;
    }
}

public void SendMessageToNewestConnection(string message)
{
    MonoBridge.SendClientMessage("OnChatMessage", newestConnectionId, MessageTarget.AuthorityOnly, "Hello!");
}

Last updated