Remote Procedure Calls (RPCs)

Overview

Remote Procedure Calls (RPCs) are a way to make networking interactions feel like ordinary function calls in Unity. An RPC lets one machine (client or server) invoke a method on another machine as if the code were local.

When an RPC is invoked:

  1. The sender builds an RPC message containing the method name, the target object’s network ID, the intended recipients, and any parameters.

  2. The message is sent over the network to the server.

  3. The server decides which clients should receive it and forwards it.

  4. On the receiving machine, reflection is used to find the matching method on the correct GameObject, and the method is invoked.

RPCs are best used for discrete gameplay events such as: - Casting a spell - Opening a door - Playing an animation - Triggering a particle effect

They are not intended for continuous updates (for that, use synchronization methods).

Format of an RPC

An RPC message contains: - The function name to execute - The network ID of the object that owns the function - The recipients (all clients, other clients, server only, etc.) - Any parameters to pass

Example

Suppose you define a method on a networked object:

public void ExampleFunction(int number, string word) {
    Debug.Log(number);
    Debug.Log(word);
}

You can invoke it across the network like this:

clientNetwork.CallRPC(
    "ExampleFunction",
    MessageReceiver.AllClients,
    -1,                 // -1 means the object with ClientNetwork
    101,
    "Hello"
);

This will: - Send the RPC to the server. - The server forwards it to all clients. - Each client calls ExampleFunction(101, "Hello")

on the object that has the ClientNetwork component.

The CallRPC signature is:

override public void CallRPC(
    string aFunctionName,
    MessageReceiver aReceiver,
    int aNetworkId,
    params object[] aParams
)
  • aFunctionName – name of the method to invoke.

  • aReceiver – who should execute the RPC (see below).

  • aNetworkId – which object should run it. -1 = network manager object.

  • aParams – any arguments to send.

Defining new RPCs

You don’t need a special keyword. Just define methods normally in your MonoBehaviour. If the name matches and parameters match, the method will be invoked.

RPCs from the Client

Clients typically call RPCs to: - Request an action from the server (e.g., “I pressed a button”). - Broadcast a local event to other players.

There are two ways to send an RPC from the client:

  1. Through ClientNetwork Useful when calling functions on the ClientNetwork object itself.

    clientNetwork.CallRPC("SpawnFireball",
        MessageReceiver.AllClientsInArea,
        -1,
        fireballPosition);
    
  2. Through NetworkSync If you want the RPC to be tied to a specific GameObject.

    myNetworkedObject.GetComponent<NetworkSync>()
        .CallRPC("PlayAnimation",
                 MessageReceiver.OtherClients,
                 "Jump");
    

Here the NetworkSync component automatically supplies the correct networkId.

RPCs from the Server

The server can call RPCs to: - Notify all clients of an event (e.g., start a round). - Update a single client (e.g., give quest info). - Send area-specific events only to nearby clients.

Examples:

Send to all clients

serverNetwork.CallRPC("StartRound",
    UCNetwork.MessageReceiver.AllClients,
    -1);

Send to a single client

long targetClientId = 123456789L;
serverNetwork.CallRPC("SendPrivateMessage",
    targetClientId,
    -1,
    "You found a secret!");

Send to all clients in an area

List<int> areaIds = new List<int> { 5 };
serverNetwork.CallRPCToArea("SpawnBoss",
    UCNetwork.MessageReceiver.AllClientsInArea,
    areaIds,
    -1);

Determining where an RPC goes - MessageReceiver

The MessageReceiver enum controls who should run the RPC:

  • ServerOnly (1): Call the RPC only on the server.

  • AllClients (2): Forward to all connected clients.

  • OtherClients (4): Forward to all clients except the sender.

  • AllClientsInArea (8): Forward only to clients in the same area(s).

  • OtherClientsInArea (16): Forward to clients in the same area(s), excluding the sender.

  • SingleClient (32): Forward to exactly one client, chosen by ID.

Diagram:

Client ----> Server ----> AllClients
                   \
                    \--> OtherClients
                    \--> AllClientsInArea
                    \--> OtherClientsInArea
                    \--> SingleClient
                    \--> ServerOnly (executes locally)

Supported Data Types

RPCs support these parameter types:

  • int

  • long

  • ulong

  • float

  • string

  • bool

  • Vector3

  • Quaternion

  • int[] (arrays of ints)

These are encoded by WriteRPCParams and decoded by ReadRPCParams in UCNetwork.

If you need more types, extend these methods:

else if (arg is Color)
{
    typeString += "c";
    aMsg.Write(((Color)arg).r);
    aMsg.Write(((Color)arg).g);
    aMsg.Write(((Color)arg).b);
    aMsg.Write(((Color)arg).a);
}

and handle 'c' in ReadRPCParams.

RPCs from One Client to Another

Direct client-to-client RPCs are not supported. All RPCs must pass through the server first. This design:

  • Ensures the server can validate and control what happens.

  • Prevents cheating (a client cannot secretly change another client’s state).

  • Keeps network topology simple.

If you want to “send a message to one other client,” do this:

clientNetwork.CallRPC(
    "WhisperMessage",
    MessageReceiver.ServerOnly,
    -1,
    targetClientId,
    "Hello!"
);

Then the server receives it, validates, and uses MessageReceiver.SingleClient to forward to the intended target.

RPC Lifecycle Diagram

The following diagram illustrates the flow of an RPC:

+---------+      CallRPC()       +---------+      Forward      +---------+
| Client  | -------------------> | Server  | ----------------> | Clients |
| Sender  |                      |         |                   | Target  |
+---------+                      +---------+                   +---------+
     |                               |                              |
     |-- Build RPC message ----------|                              |
     |-- (function, object, params) -|                              |
                                     |-- Decide recipients ---------|
                                     |-- Forward RPC ---------------|
                                                                    |
                                           Invoke method via reflection
                                           on the correct object(s)

Summary

  • RPCs let you call methods on remote machines like local methods.

  • Clients send RPCs to the server; the server forwards them to others.

  • Use MessageReceiver to control who executes an RPC.

  • Only specific data types are supported (extendable in UCNetwork).

  • Direct client-to-client is not allowed; the server always mediates.

  • RPCs are ideal for discrete gameplay events, not continuous updates.