Skip to content
This repository was archived by the owner on Jul 23, 2025. It is now read-only.

Commit 4090aa0

Browse files
authored
Develop into main (#1258)
2 parents 46bcd8e + 9051e4c commit 4090aa0

File tree

9 files changed

+91
-152
lines changed

9 files changed

+91
-152
lines changed

docs/advanced-topics/message-system/rpc.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,20 @@ title: Rpc
55
import ImageSwitcher from '@site/src/ImageSwitcher.js';
66

77

8-
Any process can communicate with any other process by sending an RPC. Starting in version 1.8, the `Rpc` attribute encompasses Server to Client Rpcs, Client to Server Rpcs, and Client to Client Rpcs.
8+
Any process can communicate with any other process by sending an RPC. Starting in version 1.8, the `Rpc` attribute encompasses server to client RPCs, client to server RPCs, and client to client RPCs.
99

1010
<figure>
1111
<ImageSwitcher
1212
lightImageSrc="/sequence_diagrams/RPCs/ServerRPCs.png?text=LightMode"
1313
darkImageSrc="/sequence_diagrams/RPCs/ServerRPCs_Dark.png?text=DarkMode"/>
1414
</figure>
1515

16-
17-
1816
<figure>
1917
<ImageSwitcher
2018
lightImageSrc="/sequence_diagrams/RPCs/ClientRPCs.png?text=LightMode"
2119
darkImageSrc="/sequence_diagrams/RPCs/ClientRPCs_Dark.png?text=DarkMode"/>
2220
</figure>
2321

24-
25-
26-
2722
## Declaring an RPC (Remote Procedure Call)
2823

2924
You can declare an RPC by marking a method with the `[Rpc]` attribute and including the `Rpc` suffix in the method name. RPCs have a number of possible targets that can be declared at both runtime and compile time, but a default must be passed to the `[Rpc]` attribute. For example, to create an RPC that will be executed on the server, you would declare it like this:
@@ -58,7 +53,7 @@ While client-to-client RPCs are supported, it is important to note that there ar
5853

5954
## Invoking an RPC
6055

61-
You can invoke an RPC by invoking the function directly with parameters:
56+
You can invoke an RPC by invoking the function directly with parameters. The following code is a heavily simplified example of a server to client RPC and a client to server RPC, with additional logic removed to display only the most basic features of an RPC.
6257

6358
```csharp
6459
[Rpc(SendTo.Server)]

docs/advanced-topics/serialization/cprimitives.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ id: cprimitives
33
title: C# primitives
44
---
55

6-
C# primitive types will be serialized by built-in serialization code. These types include `bool`, `char`, `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `float`, `double`, and `string`.
6+
C# primitive types are serialized by built-in serialization code. These types include `bool`, `char`, `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `float`, `double`, and `string`.
7+
8+
You can also serialize [arrays](serialization-arrays.md) of C# primitive types, with the exception of arrays of `strings` (`string[]`) for [performance reasons](serialization-arrays.md#performance-considerations).
79

810
```csharp
911
[Rpc(SendTo.Server)]

docs/advanced-topics/serialization/serialization-arrays.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,27 @@ id: arrays
33
title: Arrays and native containers
44
---
55

6-
Arrays of [C# primitive types](cprimatives.md), like `int[]`, and [Unity primitive types](unity-primitives.md), such as `Vector3`, are serialized by built-in serialization code. Otherwise, any array of types that aren't handled by the built-in serialization code, such as `string[]`, needs to be handled through a container class or structure that implements the [`INetworkSerializable`](inetworkserializable.md) interface.
6+
Netcode for GameObjects has built-in serialization code for arrays of [C# value-type primitives](cprimitives.md), like `int[]`, and [Unity primitive types](unity-primitives.md). Any arrays of types that aren't handled by the built-in serialization code, such as `string[]`, need to be handled using a container class or structure that implements the [`INetworkSerializable`](inetworkserializable.md) interface.
7+
8+
## Performance considerations
9+
10+
Sending arrays and strings over the network has performance implications. An array incurs a garbage collected allocation, and a string also incurs a garbage collected allocation, so an array of strings results in an allocation for every element in the array, plus one more for the array itself.
11+
12+
For this reason, arrays of strings (`string[]`) aren't supported by the built-in serialization code. Instead, it's recommended to use `NativeArray<FixedString*>` or `NativeList<FixedString*>`, because they're more efficient and don't incur garbage collected memory allocation. Refer to [`NativeArray<T>`](#nativearrayt) and [`NativeList<T>`](#nativelistt) below for more details.
13+
14+
## Built-in primitive types example
15+
16+
Using built-in primitive types is fairly straightforward:
717

8-
## Built-In Primitive Types Example
9-
Using built-in primitive types is fairly straight forward:
1018
```csharp
1119
[Rpc(SendTo.Server)]
1220
void HelloServerRpc(int[] scores, Color[] colors) { /* ... */ }
1321
```
1422

15-
## INetworkSerializable Implementation Example
16-
There are many ways to handle sending an array of managed types.
17-
The below example is a simple `string` container class that implements `INetworkSerializable` and can be used as an array of "StringContainers":
23+
## INetworkSerializable implementation example
24+
25+
There are many ways to handle sending an array of managed types. The following example is a simple `string` container class that implements `INetworkSerializable` and can be used as an array of "StringContainers":
26+
1827
```csharp
1928
[Rpc(SendTo.ClientsAndHost)]
2029
void SendMessagesClientRpc(StringContainer[] messages)
@@ -42,11 +51,12 @@ public class StringContainer : INetworkSerializable
4251
}
4352
```
4453

45-
## Native Containers
54+
## Native containers
4655

47-
Netcode for GameObjects supports `NativeArray` and `NativeList` native containers with built-in serialization, RPCs, and NetworkVariables. However, you cannot nest either of these containers without causing a crash.
56+
Netcode for GameObjects supports `NativeArray` and `NativeList` native containers with built-in serialization, RPCs, and NetworkVariables. However, you can't nest either of these containers without causing a crash.
4857

4958
A few examples of nesting that will cause a crash:
59+
5060
* `NativeArray<NativeList<T>>`
5161
* `NativeList<NativeArray<T>>`
5262
* `NativeArray<NativeArray<T>>`
@@ -59,6 +69,7 @@ To serialize a `NativeArray` container, use `serializer.SerializeValue(ref Array
5969
### `NativeList<T>`
6070

6171
To serialize a `NativeList` container, you must:
72+
6273
1. Ensure your assemblies reference `Collections`.
6374
2. You must add `UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT` to your **Scriptiong Define Symbols** list.
6475
1. From the Unity Editor top bar menu, go to **Edit** > **Project Settings...** > **Player**.
@@ -71,8 +82,7 @@ To serialize a `NativeList` container, you must:
7182
When using `NativeLists` within `INetworkSerializable`, the list `ref` value must be a valid, initialized `NativeList`.
7283

7384
NetworkVariables are similar that the value must be initialized before it can receive updates.
74-
For example,
75-
`public NetworkVariable<NativeList<byte>> ByteListVar = new NetworkVariable<NativeList<byte>>{Value = new NativeList<byte>(Allocator.Persistent)};`
85+
For example, `public NetworkVariable<NativeList<byte>> ByteListVar = new NetworkVariable<NativeList<byte>>{Value = new NativeList<byte>(Allocator.Persistent)};`.
7686

7787
RPCs do this automatically.
7888
:::

docs/learn/rpcvnetvar.md

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,99 +5,99 @@ sidebar_label: RPC vs NetworkVariable
55
---
66
import ImageSwitcher from '@site/src/ImageSwitcher.js';
77

8-
Choosing the wrong data syncing mecanism can create bugs, generate too much bandwidth and add too much complexity to your code.
9-
Netcode for GameObjects (Netcode) has two main ways of syncing information between players. `RPC` ([Remote Procedure Call](../advanced-topics/messaging-system)) and replicated state [(NetworkVariable)](../basics/networkvariable). They both send messages over the network. The logic and your design around how they send messages is what will make you choose one over the other.
8+
Choosing the wrong data syncing mechanism can create bugs, use too much bandwidth, and add too much complexity to your code.
9+
Netcode for GameObjects (Netcode) has two main ways of syncing information between players: RPCs ([Remote Procedure Calls](../advanced-topics/messaging-system.md)) and replicated states [(`NetworkVariable`s)](../basics/networkvariable). They both send messages over the network. The logic and your design around how they send messages is what will make you choose one over the other.
1010

11-
## Choosing between NetworkVariables or RPCs
11+
## Choosing between `NetworkVariable`s or RPCs
1212

13-
- Use `RPC`s for transient events, information only useful for a moment when it's received.
13+
- Use RPCs for transient events, information only useful for a moment when it's received.
1414
- Use `NetworkVariable`s for persistent states, for information that will be around more than a moment.
1515

1616
A quick way to choose which to use is to ask yourself: "Should a player joining mid-game get that information?"
1717

1818
<figure>
19-
<ImageSwitcher
19+
<ImageSwitcher
2020
lightImageSrc="/sequence_diagrams/NetworkVariable/NetworkVariables_LateJoinClient.png?text=LightMode"
2121
darkImageSrc="/sequence_diagrams/NetworkVariable/NetworkVariables_LateJoinClient_Dark.png?text=DarkMode"/>
2222
<figcaption>Network Variables allow to seamlessly catch up late joining clients by sending the current state as soon as the tick happens.</figcaption>
2323
</figure>
2424

2525
Using the Boss Room's door as an example. A player's client needs to receive the information that the door is open to play the right animations.
2626

27-
If we sent an `RPC` to all clients, then all players connecting mid game after that `RPC` are sent will miss that information and have the wrong visual on their clients.
27+
If we sent an RPC to all clients, then all players connecting mid-game after that RPC is sent will miss that information and have the wrong visual on their clients.
2828

2929
<figure>
30-
<ImageSwitcher
30+
<ImageSwitcher
3131
lightImageSrc="/sequence_diagrams/NetworkVariableVSRPCs/RPCsLateJoin.png?text=LightMode"
3232
darkImageSrc="/sequence_diagrams/NetworkVariableVSRPCs/RPCsLateJoin_Dark.png?text=DarkMode"/>
3333
<figcaption>Sending state with RPCs won't be transmitted to late joining clients.</figcaption>
3434
</figure>
3535

3636

37-
In that case, it's preferable to use `NetworkVariable`s like shown here.
37+
In that case, it's preferable to use `NetworkVariable`s as show below:
3838

3939
```csharp reference
4040
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/SwitchedDoor.cs#L10-L26
4141
```
4242

43-
It uses a `BoolNetworkVariable` to represent the "IsOpen" state. If I open the door and a player connects after this, the host will replicate all the world's information to that new player, including the door's state.
43+
It uses a `BoolNetworkVariable` to represent the `IsOpen` state. If one player opens the door and a second player connects after this, the host replicates all the world's information to that new player, including the door's state.
44+
45+
`NetworkVariable`s are eventually consistent. This means not all value changes will be synced, contrary to RPCs, where five calls to an RPC will produce five RPC sends on the network.
4446

45-
NetworkVariables are eventually consistent. This means not all value changes will be synced, contrary to RPCs, where 5 calls to an RPC will produce 5 RPC sends on the network.
4647
<figure>
47-
<ImageSwitcher
48+
<ImageSwitcher
4849
lightImageSrc="/sequence_diagrams/NetworkVariable/NetworkVariables.png?text=LightMode"
4950
darkImageSrc="/sequence_diagrams/NetworkVariable/NetworkVariables_Dark.png?text=DarkMode"/>
5051
<figcaption>Network Variables can be updated multiple times between ticks, but only the latest will be synced to other peers.</figcaption>
5152
</figure>
5253

53-
NetworkVariables will save on bandwidth for you, making sure to only send values when the data has changed. However, if you want all value changes, RPCs might be best.
54+
`NetworkVariable`s will save on bandwidth for you, making sure to only send values when the data has changed. However, if you want all value changes, RPCs might be best.
55+
56+
## Why not use `NetworkVariable`s for everything?
5457

58+
RPCs are simpler.
5559

56-
## Why not use NetworkVariables for everything?
60+
If you have a temporary event like an explosion, you don't need a replicated state for this. It would not make sense. You would have an "unexploded" state that would need to be synced every time a new player connected? From a design perspective, you might not want to represent these events as state.
5761

58-
`RPC`s are simpler.
62+
An explosion can use an RPC for the event, but the effect of the explosion should be using `NetworkVariable`s (for example player's knockback and health decrease). A newly connected player doesn't care about an explosion that happened five seconds ago. They do care about the current health of the players around that explosion though.
5963

60-
If you have a temporary event like an explosion, you don't need a replicated state for this. It would not make sense. You would have an "unexploded" state that would need to be synced everytime a new player connected? From a design perspective, you might not want to represent these events as state.
64+
Actions in Boss Room are a great example for this. The area of effect action (`AoeAction`) triggers an RPC when the action is activated (showing a VFX around the affected area). The imp's health (`NetworkVariable`s) is updated. If a new player connects, they will see the damaged imps. We would not care about the area of effect ability's VFX, which works great with a transient RPC.
6165

62-
An explosion can use an `RPC` for the event, but the effect of the explosion should be using `NetworkVariable`s ( for example player's knockback and health decrease). A newly connected player doesn't care about an explosion that happened 5 seconds ago. They do care about the current health of the players around that explosion though.
63-
64-
Actions in Boss Room are a great example for this. The area of effect action (`AoeAction`) triggers an `RPC` when the action is activated (showing a VFX around the affected area). The imp's health (`NetworkVariable`s) is updated. If a new player connects, they will see the damaged imps. We would not care about the area of effect ability's VFX, which works great with a transient `RPC`.
65-
66-
`AoeActionInput.cs` Shows the input being updated client side and not waiting for the server. It then calls an `RPC` when clicking on the area to affect.
66+
`AoeActionInput.cs` Shows the input being updated client side and not waiting for the server. It then calls an RPC when clicking on the area to affect.
6767

6868
```csharp reference
6969
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/Input/AoeActionInput.cs
7070
```
7171

72-
`AOEAction.cs` Server side logic detecting enemies inside the area and applying damage. It then broadcasts an `RPC` to tell all clients to play the VFX at the appropriate position. Character's state will automatically update with their respective `NetworkVariable`s update (health and alive status for example).
72+
`AOEAction.cs` has server-side logic detecting enemies inside the area and applying damage. It then broadcasts an RPC to tell all clients to play the VFX at the appropriate position. Character's state will automatically update with their respective `NetworkVariable`s update (health and alive status for example).
7373

7474

7575
```csharp reference
7676
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/AOEAction.cs#L8-L-40
7777
```
7878

79-
The following snippet of code is triggered by an `RPC` coming from the server
79+
The following snippet of code is triggered by an RPC coming from the server
8080

8181
```csharp reference
8282
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/AOEAction.cs#L77-L82
8383
```
8484

8585
:::tip
86-
If you want to make sure two variables are received at the same time, `RPC`s are great for this.
86+
If you want to make sure two variables are received at the same time, RPCs are great for this.
8787

88-
If you change `NetworkVariables` "a" and "b", there is no guarantee they will both be received client side at the same time.
88+
If you change `NetworkVariables` "a" and "b", there is no guarantee they will both be received client side at the same time.
8989

9090
<figure>
91-
<ImageSwitcher
91+
<ImageSwitcher
9292
lightImageSrc="/sequence_diagrams/NetworkVariable/NetVarDataUpdates.png?text=LightMode"
9393
darkImageSrc="/sequence_diagrams/NetworkVariable/NetVarDataUpdates_Dark.png?text=DarkMode"/>
9494
<figcaption>Different Network Variables updated within the same tick aren't guranteed to be delivered to the clients at the same time. </figcaption>
9595
</figure>
9696

97-
Sending them as two parameters in the same `RPC` allows to make sure they will be received at the same time client side.
97+
Sending them as two parameters in the same RPC ensures they will be received at the same time client side.
9898

9999
<figure>
100-
<ImageSwitcher
100+
<ImageSwitcher
101101
lightImageSrc="/sequence_diagrams/NetworkVariableVSRPCs/ManagingNetVarData_RPCs.png?text=LightMode"
102102
darkImageSrc="/sequence_diagrams/NetworkVariableVSRPCs/ManagingNetVarData_RPCs_Dark.png?text=DarkMode"/>
103103
<figcaption>To ensure that several different Network Variables are all synchronized at the same exact time we can use client RPC to join these value changes together.</figcaption>
@@ -112,5 +112,4 @@ darkImageSrc="/sequence_diagrams/NetworkVariableVSRPCs/ManagingNetVarData_RPCs_D
112112

113113
`NetworkVariable`s are great for managing state, to make sure everyone has the latest value. Use them when you want to make sure newly connected players get an up to date world state.
114114

115-
`RPC`s are great for sending transient events. Use them when transmiting short lived events.
116-
115+
RPCs are great for sending transient events. Use them when transmitting short-lived events.

0 commit comments

Comments
 (0)