Skip to main content

Sending/Receiving Messages

After setting up your Unity Scene as instructed on Getting Started, you are now ready to start sending/receiving messages.

Concepts

There are four protocols that developers can use to send messages from one client to other clients connected in the same game session.

Host Message

Host Message can only be sent by the host, and no other. If a player other than the host tries to send a Host message, an error will occur. The message will be broadcasted over the network to all connected clients including the host itself.

Player Message

Player Message can be sent by any clients. The message will be broadcasted over the network to all connected clients except the sender itself. Do note that the callback for receiving the message will still be called locally on the sender. This is only a measure to lower the network traffic.

Player To Host Message

Player To Host Message can be sent by any clients. The message will be sent only to the host.

Host To Player Message

Host To Player Message can only be sent by the host. The message will be sent only to one specific client that is specified from the input parameter.

Defining a NetworkMessage

In order to send/receive a message, developers need to define a network message.

// Networking SDK uses MessagePack to do serialization.
// Read more about MessagePack here:
// https://github.com/neuecc/MessagePack-CSharp
using MessagePack;
using PretiaArCloud.Networking;

// NetworkMessage is an attribute used to turn a class/struct to a NetworkMessage.
[NetworkMessage]
// MessagePackObject is an attribute used for setting this as a serialization target
// The SDK will automatically generate the serialization code for all classes/structs
// that have this attribute based on the key attribute.
[MessagePackObject]
public struct NetworkInputMsg
{
// The key attribute is applied to any fields/properties
// that needs to be serialized.
[Key(0)]
public float HorizontalAxis;

// The key attribute requires an int index for every fields/properties.
// The keys need to be unique from each other.
[Key(1)]
public float VerticalAxis;

public NetworkInputMsg(float horizontalAxis, float verticalAxis)
{
HorizontalAxis = horizontalAxis;
VerticalAxis = verticalAxis;
}
}

Sending/Receiving a Network Message

After defining a NetworkMessage. We can start sending a message of that type.

using PretiaArCloud.Networking;
using UnityEngine;

public class NetworkInputController : MonoBehaviour
{
private IGameSession _gameSession;

private async void OnEnable()
{
// Get an instance of IGameSession.
_gameSession = await NetworkManager.Instance.GetLatestSessionAsync();
// Register a callback when receiving a message of type NetworkInputMsg.
_gameSession.PlayerMsg.Register<NetworkInputMsg>(ApplyInput);

// It is a good practice to register callbacks meant for the host
// only if the client is appointed as a host.
// This can be done by using OnHostAppointment event.
_gameSession.OnHostAppointment += RegisterHostCallbacks;
}

private async void Start()
{
// Wait until we have a working IGameSession instance before sending messages
await _gameSession.WaitForConnectionAsync();

// Send messages!
_gameSession.PlayerMsg.Send(new NetworkInputMsg(0f, 1f));
_gameSession.HostMsg.Send(new NetworkInputMsg(0f, 1f));
}

private void OnDisable()
{
if (_gameSession != null)
{
// Don't forget to Unregister the callback!
_gameSession.PlayerMsg.Unregister<NetworkInputMsg>(ApplyInput);
_gameSession.HostMsg.Unregister<NetworkInputMsg>(Host_ApplyInput);
_gameSession.OnHostAppointment -= RegisterHostCallbacks;

// Unregister host callbacks.
if (_gameSession.IsHost)
{
_gameSession.HostMsg.Unregister<NetworkInputMsg>(Host_ApplyInput);
}
}
}

// Register host only callbacks here.
private void RegisterHostCallbacks()
{
// We can register different callbacks for the same message type, but different protocol type.
_gameSession.HostMsg.Register<NetworkInputMsg>(Host_ApplyInput);
}

// This function will be called every NetworkInputMsg that is received from the PlayerMsg protocol.
// The user ID of the sender can also be accessed from PlayerMsg and PlayerToHostMsg callback
private void ApplyInput(NetworkInputMsg msg, uint sender)
{
// Do something important
}

// This function will be called every NetworkInputMsg that is received from the HostMsg protocol.
// Note that the user ID of the sender cannot be accesed from a HostMsg callback.
// As a convention, HostMsg callbacks should have a "Host_" prefix.
private void Host_ApplyInput(NetworkInputMsg msg)
{
// Do something important
}
}

It is also possible to queue messages first before sending. This helps reducing the load of network traffic in the network.

_gameSession.PlayerMsg.Enqueue(new NetworkInputMsg(0f, 1f));
_gameSession.PlayerMsg.Enqueue(new NetworkInputMsg(0f, 1f));
_gameSession.PlayerMsg.SendQueue();

// This can be done with any of the protocols.
// e.g:
// _gameSession.HostMsg.Enqueue(..);
// _gameSession.HostMsg.Enqueue(..);
// _gameSession.HostMsg.SendQueue();

Congratulations! You have managed to send and receive your first network message.