DeveloperGuidePart02RemoteProcedureCalls
Introduction to Alteruna Remote Procedure Calls.
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?
The recommended way to use RPCs is through
AttributesSync:
mark a method with
[SynchronizableMethod], then call it on other clients with
InvokeRemoteMethod or
BroadcastRemoteMethod.
InvokeRemoteMethod vs BroadcastRemoteMethod
Both methods do the same underlying thing: run a
[SynchronizableMethod] on other clients in the room.
The difference is who receives the call:
BroadcastRemoteMethod always sends to everyone in the room, including yourself. There is no way to
exclude anyone, so it is the simplest option when you want every client (yourself included) to react.
InvokeRemoteMethod lets you choose who receives it: a single user, a list of users, or everyone.
Its default target is
UserId.All, which means everyone
except yourself. Pass
UserId.AllInclusiveinstead if you also want it to run locally.
As a rule of thumb: use
BroadcastRemoteMethod for "notify everyone, including me" events (e.g. playing a
sound or effect that should also happen on your own client), and use
InvokeRemoteMethod when you need to
target specific user(s), or you are already handling the local reaction yourself and only want to tell
everyone
else.
Here is a simple audio sync script that uses
InvokeRemoteMethod. When
Play() runs, it plays the sound on
every other client, and calls
PlayRemote() directly to also play it locally (since the default target of
InvokeRemoteMethod excludes the caller):
public class PlayAudioSync : AttributesSync
{
public AudioSource MyAudioSource;
public void Play()
{
// Invoke on all other clients (default target is UserId.All, i.e. everyone but us).
InvokeRemoteMethod();
// InvokeRemoteMethod above does not include us, so call PlayRemote() directly to also play it locally.
PlayRemote();
}
[SynchronizableMethod]
private void PlayRemote()
{
MyAudioSource.Play();
}
}
The same result can be achieved with
BroadcastRemoteMethod, which always includes the caller, so there is no need to call
PlayRemote() separately:
public class PlayAudioSyncBroadcast : AttributesSync
{
public AudioSource MyAudioSource;
public void Play()
{
// BroadcastRemoteMethod always includes the caller, so PlayRemote() also runs on this client.
BroadcastRemoteMethod();
}
[SynchronizableMethod]
private void PlayRemote()
{
MyAudioSource.Play();
}
}
In the case that you want to pass arguments to a SynchronizableMethod, or target a specific user,
do the following:
public class MyAttributesSync : AttributesSync
{
public void SendRpc()
{
// 0 is the method ID of MyReceiver (it's the only SynchronizableMethod here, so its ID is 0).
// We could use nameof(MyReceiver) instead of 0, but that is slower - see GetMethodAttributeId below.
// UserId.All targets every other client; pass a specific user's ID instead to target only them.
InvokeRemoteMethod(0, UserId.All, "Hello, World!", 16.0f);
}
[SynchronizableMethod]
private void MyReceiver(string foo, float bar)
{
Debug.Log(foo);
Debug.Log(bar);
}
}
Improving performance with GetMethodAttributeId
Calling
InvokeRemoteMethod or
BroadcastRemoteMethod with a method name (a
string) works, but it has to look
through all of the object's
[SynchronizableMethod]s to find the one with that name every time it is called.
If you are calling the same method often, look up its numeric ID once with
GetMethodAttributeId and reuse it -
calling by ID skips the name lookup entirely.
public class MessageAll : AttributesSync
{
private int _messageMethodId;
private void Start()
{
// Look up the method's ID once, for example on Start.
_messageMethodId = GetMethodAttributeId(nameof(Message));
}
public void SendMessage(string msg)
{
// Invoke using the cached ID instead of the method name - faster if called frequently.
BroadcastRemoteMethod(_messageMethodId, msg);
}
[SynchronizableMethod]
private void Message(string msg)
{
Debug.Log(msg);
}
}
← Back |
Next →