05 Remote Procedure Call - Alteruna/au-multiplayer-guide GitHub Wiki

What are Remote Procedure Calls?

Remote Procedure Calls within Alteruna Multiplayer allow you to register and execute functions on other clients within the same room. These functions can be executed on a specific client, or any number of clients within the room.

How do I use RPCs?

To execute a procedure on other clients in the room, it must first be registered on the clients. When registering a procedure a method will be attached to the given name of the procedure, after which other clients within the same room can execute it by name. To supply the method to be executed on other clients with parameters, a ProcedureParameters object can be given when invoking the procedure. ProcedureParameters is a container of key value pairs supporting all common data types allowing for passing parameters to procedure calls.

To execute a method on other clients within the room, it must first be registered to Alteruna Multiplayer as a remote procedure. This can be done with the use of the RegisterRemoteProcedure method on the Multiplayer component which couples a name to any method. The only requirement is that the method accepts a ProcedureParameters parameter, a ushort reflecting the client Identifier of the caller and unique numeric call identifier.

Remote Procedures are usually registered in the Start() function, here's an example:

void MyProcedureFunction(ushort fromUser, ProcedureParameters parameters, uint callId, ITransportStreamReader processor)
{
   float myValue = parameters.Get("value", 0);
   string myString = parameters.Get("string_value", "default value");
}

void Start()
{
   Multiplayer.RegisterRemoteProcedure("MyProcedureName", MyProcedureFunction);
}

After it has been registered on all clients, the Procedure can be called by a User on any other User's client.

void CallMyProcedure()
{
   ProcedureParameters parameters = new ProcedureParameters();
   parameters.Set("value", 16.0f);
   Multiplayer.InvokeRemoteProcedure("MyProcedureName", targetUser.Index, parameters);
}

After it has been registered it can be invoked by using the InvokeRemoteProcedure method on the Multiplayer component by its registered name.

The InvokeRemoteProcedure method can be supplied with a ProcedureParameters argument allowing data to be passed to the procedure being executed on other clients. The method can also be given either a specific UserID of any user within the room to execute the procedure on that client specifically, or be given UserId.All to execute the procedure on all other clients within the room.

An alternative to ProcedureParameters

There is an alternative to ProcedureParameters. It is possible to use the Reader and Writer by implementing Alteruna.Trinity.ISerializable.

void MyProcedureFunction(ushort fromUser, ProcedureParameters parameters, uint callId, ITransportStreamReader processor)
{
   Unserialize(processor);
}

void Start()
{
   Multiplayer.RegisterRemoteProcedure("MyProcedureName", MyProcedureFunction);
}

void CallMyProcedure()
{
   Multiplayer.InvokeRemoteProcedure("MyProcedureName", UserId.All, null, this);
}

public void Serialize(ITransportStreamWriter processor)
{
   Writer writer = new Writer(processor);

   writer.Write(transform.position);
   writer.Write(transform.eulerAngles);
   writer.Write(transform.localScale);
}

public void Unserialize(ITransportStreamReader processor)
{
   Reader reader = new Reader(processor);

   transform.position = reader.ReadVector3();
   transform.eulerAngles = reader.ReadVector3();
   transform.localScale = reader.ReadVector3();
}

Procedure parameters

ProcedureParameters allows for passing an arbitrary amount of parameters to a remote procedure call. Each parameter must be given a name and a value that are assigned in the calling client, and received and processed in the called client.

The data types currently supported by Alteruna Multiplayer for a procedure parameters are the following,

  • bool
  • int
  • uint
  • short
  • ushort
  • float
  • string
  • byte
  • byte array

Parameters are assigned using the .Set methods and read using the .Get methods on the ProcedureParameters instance.

Attribute RPC

Here is a simple audio sync script made using Attributes. When Play() on the script runs, run Play() on a attached AudioSource.

public class PlayAudioSync : AttributesSync
{
    public AudioSource MyAudioSource;
    
    public void Play()
    {
        // Invoke on all other clients
        InvokeRemoteMethod();
        // Invoke localy
        PlayRemote();
    }

    [SynchronizableMethod]
    private void PlayRemote()
    {
        MyAudioSource.Play();
    }
}

In the case that you want to pass arguments to a SynchronizableMethod, do the following:

public class MyAttributesSync : AttributesSync
{

    public void SendRpc()
    {
        // Now we target index 0, but we could also use "MyReceiver" instead.
        InvokeRemoteMethod(0, UserId.All, "Hello, World!", 16.0f);
    }

    [SynchronizableMethod]
    private void MyReceiver(string foo, float bar)
    {
        Debug.Log(foo);
        Debug.Log(bar);
    }
}