Remote Procedure Calls
Introduction
RPCs (Remote Procedure Calls) are ideal for sharing punctual game events; in contrast [Networked]
properties are the go-to solutions for sharing state between network clients that are undergoing continuous change.
For example when a player wants to perform a rare complex interaction with an object that it does not have Input Authority over such as using a specific key from their inventory to open a locked door. Although the actions can technically be achieved by including additional fields as part of the input, it would clutter the Input Struct and make it unwieldy.
Furthermore, Input Structs are sent as unreliable messages, i.e. packets may be lost. This is rarely noticeable for things requiring continuous input (e.g. character movement), but will be harmful to player experience when this affects single one-time actions which players expect to be guaranteed. In this situation a Remote Procedure Call is the best practice.
Creating an RPC
To define an RPC on any NetworkBehaviour
on a NetworkObject
simply follow these steps:
- Declare a regular CSharp method of return type
void
orRpcInvokeInfo
(Documented below); - Pre- or post-fix the method name with "RPC" (case insensitive);
- Add the
[Rpc]
attribute in front of the method declaration; and, - Configure the
RpcSources
andRpcTargets
parameters to control where the RPC may be called from and where it gets executed.
C#
[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color){
playerName = name;
playerColor = color;
}
RPCs must have a "RPC" pre- or post-fix in the method name to work.
Static RPC
Static RPCs follow slightly different rules, they:
ignore the
RpcSources
andRpcTargets
parameters; andrequire the first parameter of the method to be
NetworkRunner
.can be implemented on any
SimulationBehaviour
(not justNetworkBehaviour
), as the callback receiver is not bound to a particularNetworkObject
.
Because there is no source and target filter, static RPCs can be called from any client and will be sent to all clients. Do note that you can still target the RPC to a specific PlayerRef
(See "Targeted RPC") to control who will receive the call.
C#
[Rpc]
public static void Rpc_MyStaticRpc(NetworkRunner runner, int a) { }
RPC Attribute Parameters
Sources and Targets
RpcSources
and RpcTargets
are filters. The RpcSources
define which peers can send the RPC, whereas the RpcTargets
define on which it is executed.
All
: can be sent / is executed by all peers in the session (including the server).Proxies
: can be sent / is executed by a peer who does not have either Input Authority or State Authority over the object.InputAuthority
: can be sent / is executed by the peer with Input Authority over the object.StateAuthority
: can be sent / is executed by the peer with State Authority over the object.
IMPORTANT: RPCs do not have an explicit state. Clients who late-join and clients who disconnect & reconnect will forget it ever happened. It is therefore crucial to ensure an RPC is either:
- truly transient without any state (e.g. a chat message); or,
- has its effect indirectly recorded in a
[Networked]
property.
C#
public class Player : NetworkBehaviour {
[Networked] public string playerName { get; set; }
[Networked] public Color playerColor { get; set; }
[Rpc(RpcSources.InputAuthority, RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color) {
playerName = name;
playerColor = color;
}
}
Optional RPC Attribute Parameters
In addition to the RpcSources
and RpcTargets
properties, the [Rpc]
attribute offers several optional parameters.
Channel
(defaultReliable
): Set toUnreliable
if the RPC can be lost in transmission.InvokeLocal
(default true): True indicates that the RPC will be invoked on the local client.TickAligned
(default true): Set to false if you do not want the receiving end to delay execution of the RPC until at or after the tick in which in was sent.
C#
[Rpc (RpcSources.All, RpcTargets.All, InvokeLocal = true, TickAligned = false )]
void RpcStartBoost(){
m_BoostAnim.StartBoostAnimation();
}
RPC Method Parameters
RPC are serialized at runtime. It is therefore recommended to use the regular CLR types (e.g.: bool
) over the Fusion specific ones (e.g. NetworkBool
).
Allowed Types
The following types are supported by RPCs
- Primitives
- byte, sbyte
- Int16, Int32, Int64
- UInt16, UInt32, UInt64
- float
- double
- float
- double
- Unity struct types (defined in ILWeaver.cs)
- Vector2, Vector3, Vector4
- Quaternion
- Matrix4x4
- Vector2Int, Vector3Int
- BoundingSphere
- Bounds
- Rect
- BoundsInt
- RectInt
- Color, Color32
- System.Guid
- User Defined INetworkStructs
- Fusion Defined INetworkStructs
- NetworkString<IFixedStorage>
- NetworkBool
- Ptr
- Angle
- BitSet64, BitSet128, BitSet192, BitSet256
- PlayerRefSet
- NetworkId
- NetworkButtons
- NetworkRNG
- NetworkObjectGuid
- NetworkPrefabRef
- NetworkObjectHeader
- NetworkPrefabId
- SceneRef
- TickTimer
- IFixedStorage (_2, _4, _8, _16, _32, _64, _128, _256, _512)
- Fusion Types
- NetworkObject (serialized as
NetworkId
) - NetworkBehaviour (serialized as
NetworkId
and theNetworkBehaviour
index) - PlayerRef (serialized as
PlayerRef.PlayerId
)
- NetworkObject (serialized as
- Strings
- Arrays of any of the types listed above
RpcInfo
RPC method declarations can take a optional parameter of type RpcInfo
, which exposes the following meta information about the RPC:
Tick
: at which tick was it sent.Source
: which player (PlayerRef
) sent it.Channel
: was it sent as anUnreliable
orReliable
RPC.IsInvokeLocal
: was it the local player who originally invoked this RPC.
C#
[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color, RpcInfo info = default){
playerName = name;
playerColor = color;
}
The parameter is always declared as RpcInfo info = default
.
Server vs Host Source
When using Fusion in ServerMode
, an the RpcInfo.Source
included with an RPC sent by the Server will be set to PlayerRef.None
as the server is not a player.
When using Fusion in HostMode
, however, the host-client runs both a server and a player. By default any RPC sent by the Host will function identically to the Server and set RpcInfo.Source
to PlayerRef.None
. To include the Host's local PlayerRef
instead, the HostMode
attribute has to be set to RpcHostMode.SourceIsHostPlayer
.
The HostMode
can be set to one of two modes:
RpcHostMode.SourceIsServer
(default): theRpcInfo.Source
is set toPlayerRef.None
.RpcHostMode.SourceIsHostPlayer
: theRpcInfo.Source
is set to the localPlayerRef
when Fusion is running inHostMode
.
To include the host's PlayerRef
in the RpcSource.Info
the previous snippet can be adjusted as follows:
C#
[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority, HostMode = RpcHostMode.SourceIsHostPlayer)]
public void RPC_Configure(string name, Color color, RpcInfo info = default){
playerName = name;
playerColor = color;
}
RpcInvokeInfo
RPC methods may optionally define RpcInvokeInfo
as a return value. When the RPC method is invoked, the RpcInvokeInfo
return value will contain information about the RPC invoke and send operations.
LocalInvokeResult
:RpcLocalInvokeResult
enum value indicating success or cause of failure of the local invoke action.SendCullResult
:RpcSendCullResult
enum value indicating the success or cause of failure of the RPC invocation for remote peers.SendResult
:RpcSendResult
struct containing meta information about the RPC send operation.Result
:RpcSendMessageResult
result flags for this RPC message send operation.MessageSize
: Size of RPC package.Receivers
: A collection of thePlayerRef
s included as receivers for this RPC operation.CulledReceivers
: A collection of thePlayerRef
s which were culled and excluded as receivers from this RPC send operation.
Note: that this is NOT information about delivery success or failure, but rather only the results of the invoke and send operations.
C#
[Rpc]
public RpcInvokeInfo RpcFoo() {
// RPC action
return default;
}
public override void FixedUpdateNetwork() {
var info = RpcFoo();
Debug.Log(info);
}
Targeted Rpc
When an RPC is meant to be exclusively executed on a specific player's machine, targeted RPCs are used. Both Instance RPCs and Static RPCs can be turned into targeted RPCs by adding a PlayerRef
parameter prefaced by the [RpcTarget]
attribute. A typical use-case is team chat where a message is only meant for the specific players on one's own team.
Passing PlayerRef.None
for the [RpcTarget]
parameter will target the server!
C#
[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.All)]
public void Rpc_TargetedInstanceMessage([RpcTarget] PlayerRef player, string message){}
Or
C#
[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.All)]
public static void Rpc_MyTargetedStaticMessage(NetworkRunner runner, [RpcTarget] PlayerRef player, string message) { };
The [RpcTarget]
attribute used within the method the declaration is DIFFERENT from the RpcTargets
parameter inside the [Rpc]
attribute placed in front of the method declaration.