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: .. code-block:: csharp public void ExampleFunction(int number, string word) { Debug.Log(number); Debug.Log(word); } You can invoke it across the network like this: .. code-block:: csharp 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: .. code-block:: csharp 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. .. code-block:: csharp clientNetwork.CallRPC("SpawnFireball", MessageReceiver.AllClientsInArea, -1, fireballPosition); 2. **Through NetworkSync** If you want the RPC to be tied to a specific GameObject. .. code-block:: csharp myNetworkedObject.GetComponent() .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** .. code-block:: csharp serverNetwork.CallRPC("StartRound", UCNetwork.MessageReceiver.AllClients, -1); **Send to a single client** .. code-block:: csharp long targetClientId = 123456789L; serverNetwork.CallRPC("SendPrivateMessage", targetClientId, -1, "You found a secret!"); **Send to all clients in an area** .. code-block:: csharp List areaIds = new List { 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: .. code-block:: 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: .. code-block:: csharp 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: .. code-block:: csharp 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: .. code-block:: +---------+ 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.