Please note that this feature is still under development and breaking changes may occur in the future.
RPC serves as a mean to perform a directed reliable one-time action. What does it mean?
- directed – an action can be scheduled by the server instance to be run by all players or by a player to be run on the server; the action is run only on the target and not on the instance that schedules the RPC,
- reliable – the action is guaranteed to execute as long as the connection is not severed,
- one-time – RPCs are neither scheduled nor executed again on clients during reconciliation.
RPC-enabled methods have to be marked with the
[ElympicsRpc] attribute. Any method is suitable as long as it meets the following criteria:
- it belongs to a class inheriting from
- it has
- its parameter list consists only of primitive types and strings, without
- it is an instance (non-
- it is a concrete method without
- the class it belongs to is not a part of a custom assembly; only the default scripting assembly (
Assembly-CSharp.dll) is scanned by Elympics.
Such a method can be called only from a synchronized object (i.e. implementing
IObservable directly or indirectly and being part of a game object with the
ElympicsBehaviour component attached). As RPCs are tick-aligned, a call must be performed inside:
ElympicsUpdatemethod after implementing
Initializemethod after implementing
- physics callbacks.
An RPC method call looks like any other plain method call, but Elympics modifies the compiled code so the called method is not run immediately. Instead, a message containing all passed arguments is created and then sent to the target instance. Only there the method body is finally executed.
The direction of RPC is decided by passing
ElympicsRpcDirection.PlayerToServer to the
[ElympicsRpc] attribute marking the method. Additionally, RPC methods should be scheduled only after performing
if (Elympics.IsServer) or
if (Elympics.IsClient || Elympics.IsBot) check, respectively.
It may be tempting to use
if (!Elympics.IsServer) instead of
if (Elympics.IsClient || Elympics.IsBot), however you should not do that because for example both
Elympics.IsServer are set to true for bot instances.
If you don't split the checks, you can use the
Elympics.IsClientOrBot convenience property.
RPC actions are sent to the target at the end of a tick. Received RPCs are executed at the beginning of a tick, before running ElympicsUpdate (or after applying the authoritative state on clients with prediction disabled). You can find more details in our Game loop article. Keep in mind that several ticks may pass between scheduling and executing an action as the information has to be transmitted over the network. However, we make sure no RPC executes before its associated tick.
The purpose of server-to-players RPCs is to run audiovisual effects not affecting the game state. Such an RPC serves as an alternative to the
ElympicsVar.ValueChanged callback which is unreliable and may be run multiple times during reconciliation.
Remember that client instances cannot modify the game state by themselves as all the changes would be overwritten by a server-authoritative snapshot.
That's why server-to-players RPCs (which are executed on clients) are not meant to modify the game state and only run some special effects.
If you want to modify the state, just do it directly on the server instance, without using RPCs.
The following code example demonstrates how to use a server-to-players RPC.
public class PlayerHealthController : ElympicsMonoBehaviour
[SerializeField] private PlayerData playerData;
private readonly ElympicsInt _health = new(100);
private readonly ElympicsBool _dead = new();
public void OnCollisionEnter(Collision other)
var bullet = other.transform.GetComponentInParent<Bullet>();
if (bullet == null)
_health.Value -= 20;
if (_health.Value < 0)
_dead.Value = true;
if (Elympics.IsServer) // ensuring the RPC is scheduled by the server instance to execute on all client instances
AddKillLogEntry(bullet.Owner.Nickname, playerData.Nickname); // scheduling the RPC
[ElympicsRpc(ElympicsRpcDirection.ServerToPlayers)] // specifying the direction
private void AddKillLogEntry(string killer, string victim)
// the contents of this method will be run on client instances
Bots are run as a part of the server so they don't execute server-to-players RPCs which are meant to trigger audiovisual effects. Such effects would not be visible/audible on the headless server instance.
Player-to-server RPC is a user-friendly way of sending one-time inputs (e.g. sending your nickname, choosing a team or marking yourself as ready). Using the traditional input mechanism would require additional boilerplate logic to ensure the data is reliably received only once.
Note that RPCs should not be used to replace all the inputs as they are costly to send over the network and may introduce unwanted lag when used every tick.
RPCs are not scheduled during reconciliation. Keep this in mind – with prediction enabled, RPC calling logic may be based on non-confirmed state and cannot be "fixed" (i.e. RPCs cannot be unscheduled or have their source tick number changed).
Player-to-server RPCs are executed on the server so it is safe to modify the game state with them.
Currently, there is no mechanism preventing one of the players from sending player-to-server RPCs on behalf of another player.
That means that for the time being RPCs are insecure and therefore should not be used for handling game logic e.g. in paid competitions.
Necessary security measures are to be introduced in the near future.
These RPCs may only be called after performing
if (Elympics.IsClient || Elympics.IsBot) check. The check may be split into separate
if (Elympics.IsClient) and
if (Elympics.IsBot) checks, as presented in the example below.
public class PlayerData : ElympicsMonoBehaviour, IInitializable
private readonly ElympicsString _nickname = new();
public string Nickname => _nickname.Value;
public void Initialize()
if (Elympics.IsClient) // ensuring the RPC is scheduled by a client instance to execute on the server instance
SetNickname(PlayerPrefs.GetString("Nickname")); // scheduling the RPC
if (Elympics.IsBot) // ensuring the RPC is scheduled by a bot to execute inside the server instance
SetNickname("Bot"); // scheduling the RPC
private void SetNickname(string nickname)
// the contents of this method will be run on the server
_nickname.Value = nickname; // the variable will be changed on the server and then propagated to players in a snapshot
Player-to-server RPCs scheduled by bots are executed directly without a delay as bots are a part of the server.