Skip to content

Commit d366929

Browse files
committed
Sentence casing docs
1 parent 3b6a218 commit d366929

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+332
-256
lines changed

docs/advanced-topics/client-anticipation.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ Client anticipation uses `AnticipatedNetworkVariable<T>` and `AnticipatedNetwork
1919
Games with a server-authoritative architecture often face the problem of making the game feel responsive despite [latency](../learn/ladandpacketloss.md). For example, when a user wants to change the color of an object from green to blue they click a button in the UI, an RPC is sent to the server, and the server changes the object to blue. From the client's perspective, the object doesn't change to blue until the server responds to that message, resulting in a perceived delay for the user.
2020

2121
<figure>
22-
<ImageSwitcher
22+
<ImageSwitcher
2323
lightImageSrc="/sequence_diagrams/Anticipation/ServerAuthoritative.png?text=LightMode"
2424
darkImageSrc="/sequence_diagrams/Anticipation/ServerAuthoritative_Dark.png?text=DarkMode"/>
2525
</figure>
2626

2727
Client anticipation solves this problem by allowing a separation between the visual value and the authoritative value of an object. In this example, with anticipation, when the button is pressed to change the color from green to blue, the client *anticipates* the result of the command by visually changing the object to green while it waits for an update from the server:
2828

2929
<figure>
30-
<ImageSwitcher
30+
<ImageSwitcher
3131
lightImageSrc="/sequence_diagrams/Anticipation/ClientAnticipation.png?text=LightMode"
3232
darkImageSrc="/sequence_diagrams/Anticipation/ClientAnticipation_Dark.png?text=DarkMode"/>
3333
</figure>
@@ -48,15 +48,15 @@ Anticipation systems need to be able to handle stale data. Stale data refers to
4848
Expanding the example above to include a second client that's also trying to change the color of the same object highlights this problem. If client A tries to change the object to blue, and then client B tries to change it to red, client A sees a delayed switch to blue, followed by a switch to red (which is fine because this is actually what happened). Client B, however, clicks the button to change it to red, then sees it change to blue, followed by a change to red.
4949

5050
<figure>
51-
<ImageSwitcher
51+
<ImageSwitcher
5252
lightImageSrc="/sequence_diagrams/Anticipation/ServerAuthoritativeMultiClient.png?text=LightMode"
5353
darkImageSrc="/sequence_diagrams/Anticipation/ServerAuthoritativeMultiClient_Dark.png?text=DarkMode"/>
5454
</figure>
5555

5656
With client anticipation, this scenario plays out differently: client A anticipates the change to blue, so it happens immediately, and then later sees the object change to red (which, again, is fine). Client B also sees the object change to red immediately, but because a change to blue is already in progress, that overwrites client B's anticipated value, causing it to flicker briefly to blue from client A's request before changing back to red again from client B's request.
5757

5858
<figure>
59-
<ImageSwitcher
59+
<ImageSwitcher
6060
lightImageSrc="/sequence_diagrams/Anticipation/StaleDataNoPolicy.png?text=LightMode"
6161
darkImageSrc="/sequence_diagrams/Anticipation/StaleDataNoPolicy_Dark.png?text=DarkMode"/>
6262
</figure>
@@ -68,20 +68,22 @@ There are two ways you can respond to stale data, which are determined by the `S
6868
- StaleDataHandling.Ignore
6969
- StaleDataHandling.Reanticipate
7070

71-
### StaleDataHandling.Ignore
71+
### `StaleDataHandling.Ignore`
72+
7273
If `StaleDataHandling` is set to `StaleDataHandling.Ignore`, stale data doesn't roll back the value of the variable or transform to the server value and doesn't trigger the [`OnReanticipate` event](#onreanticipate-event). `ShouldReanticipate` remains false in the event something else triggers the callback. The authoritative value is still updated, however, and for `AnticipatedNetworkVariable`, the `OnAuthoritativeValueUpdated` callback is still called. The result for our example is that, for client B, the change to blue is recognized as being sequenced before its change to red, and is thus ignored, eliminating the flickering. This is the default behavior for `AnticipatedNetworkVariable<T>`.
7374

7475
<figure>
75-
<ImageSwitcher
76+
<ImageSwitcher
7677
lightImageSrc="/sequence_diagrams/Anticipation/StaleDataIgnore.png?text=LightMode"
7778
darkImageSrc="/sequence_diagrams/Anticipation/StaleDataIgnore_Dark.png?text=DarkMode"/>
7879
</figure>
7980

80-
### StaleDataHandling.Reanticipate
81+
### `StaleDataHandling.Reanticipate`
82+
8183
If `StaleDataHandling` is set to `StaleDataHandling.Reanticipate`, stale data is treated the same way as any other server data updates. The value is rolled back, `ShouldReanticipate` is set to true, and the [`OnReanticipate` event](#onreanticipate-event) fires. In typical client prediction systems, this generally involves replaying the player's input from the time of the incoming data to now, which results in re-performing the switch to red.
8284

8385
<figure>
84-
<ImageSwitcher
86+
<ImageSwitcher
8587
lightImageSrc="/sequence_diagrams/Anticipation/StaleDataReanticipate.png?text=LightMode"
8688
darkImageSrc="/sequence_diagrams/Anticipation/StaleDataReanticipate_Dark.png?text=DarkMode"/>
8789
</figure>

docs/advanced-topics/custom-serialization.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static class SerializationExtensions
6262

6363
Additionally, you can also add extensions for `FastBufferReader.ReadValue()`, `FastBufferWriter.WriteValue()`, and `BufferSerializer<TReaderWriter>.SerializeValuePreChecked()` to provide more optimal implementations for manual serialization using `FastBufferReader.TryBeginRead()`, `FastBufferWriter.TryBeginWrite()`, and `BufferSerializer<TReaderWriter>.PreCheck()`, respectively. However, none of these will be used for serializing RPCs - only `ReadValueSafe` and `WriteValueSafe` are used.
6464

65-
### For NetworkVariable
65+
### For `NetworkVariable`
6666

6767
`NetworkVariable` goes through a slightly different pipeline than `RPC`s and relies on a different process for determining how to serialize its types. As a result, making a custom type available to the `RPC` pipeline doesn't automatically make it available to the `NetworkVariable` pipeline, and vice-versa. The same method can be used for both, but currently, `NetworkVariable` requires an additional runtime step to make it aware of the methods.
6868

docs/advanced-topics/fastbufferwriter-fastbufferreader.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ id: fastbufferwriter-fastbufferreader
33
title: FastBufferWriter and FastBufferReader
44
sidebar_label: FastBufferWriter and FastBufferReader
55
---
6-
The serialization and deserialization is done via `FastBufferWriter` and `FastBufferReader`. These have methods for serializing individual types and methods for serializing packed numbers, but in particular provide a high-performance method called `WriteValue()/ReadValue()` (for Writers and Readers, respectively) that can extremely quickly write an entire unmanaged struct to a buffer.
6+
The serialization and deserialization is done via `FastBufferWriter` and `FastBufferReader`. These have methods for serializing individual types and methods for serializing packed numbers, but in particular provide a high-performance method called `WriteValue()/ReadValue()` (for Writers and Readers, respectively) that can extremely quickly write an entire unmanaged struct to a buffer.
77

88
There's a trade-off of CPU usage vs bandwidth in using this: Writing individual fields is slower (especially when it includes operations on unaligned memory), but allows the buffer to be filled more efficiently, both because it avoids padding for alignment in structs, and because it allows you to use `BytePacker.WriteValuePacked()`/`ByteUnpacker.ReadValuePacked()` and `BytePacker.WriteValueBitPacked()`/`ByteUnpacker.ReadValueBitPacked()`. The difference between these two is that the BitPacked variants pack more efficiently, but they reduce the valid range of values. See the section below for details on packing.
99

@@ -47,7 +47,7 @@ void Serialize(FastBufferWriter writer)
4747
}
4848
```
4949
This creates efficiently packed data in the message, and can be further optimized by using `BytePacker.WriteValuePacked()` and `BytePacker.WriteValueBitPacked()`, but it has two downsides:
50-
- First, it involves more method calls and more instructions, making it slower.
50+
- First, it involves more method calls and more instructions, making it slower.
5151
- Second, that it creates a greater opportunity for the serialize and deserialize code to become misaligned, since they must contain the same operations in the same order.
5252

5353
You can also use a hybrid approach if you have a few values that will need to be packed and several that won't:
@@ -78,7 +78,7 @@ struct ExampleStruct
7878
This allows the four bytes of the embedded struct to be rapidly serialized as a single action, then adds the compacted data at the end, resulting in better bandwidth usage than serializing the whole struct as-is, but better performance than serializing it one byte at a time.
7979

8080

81-
## FastBufferWriter and FastBufferReader
81+
## `FastBufferWriter` and `FastBufferReader`
8282

8383
`FastBufferWriter` and `FastBufferReader` are replacements for the old `NetworkWriter` and `NetworkReader`. For those familiar with the old classes, there are some key differences:
8484

@@ -96,9 +96,9 @@ This allows the four bytes of the embedded struct to be rapidly serialized as a
9696

9797
A core benefit of `NativeArray<byte>` is that it offers access to the allocation scheme of `Allocator.TempJob`. This uses a special type of allocation that is nearly as fast as stack allocation and involves no GC overhead, while being able to persist for a few frames. In general they're rarely if ever needed for more than a frame, but this does provide a efficient option for creating buffers as needed, which avoids the need to use a pool for them. The only downside is that buffers created this way must be manually disposed after use, as they're not garbage collected.
9898

99-
## Creating and Disposing FastBufferWriters and FastBufferReaders
99+
## Creating and disposing `FastBufferWriters` and `FastBufferReaders`
100100

101-
To create your own `FastBufferWriter`s and `FastBufferReader`s, it's important to note that struct default/parameterless constructors can't be removed or overridden, but `FastBufferWriter` and `FastBufferReader` require constructor behavior to be functional.
101+
To create your own `FastBufferWriter`s and `FastBufferReader`s, it's important to note that struct default/parameterless constructors can't be removed or overridden, but `FastBufferWriter` and `FastBufferReader` require constructor behavior to be functional.
102102

103103
`FastBufferWriter` always owns its internal buffer and must be constructed with an initial size, an allocator, and a maximum size. If the maximum size isn't provided or is less than or equal to the initial size, the `FastBufferWriter` can't expand.
104104

@@ -116,7 +116,7 @@ It's important to note with `Allocator.None` that the `FastBufferReader` will be
116116

117117
Regardless which allocator you use (including `Allocator.None`), `FastBufferWriter` and `FastBufferReader` must always have `Dispose()` called on them when you're done with them. The best practice is to use them within `using` blocks.
118118

119-
## Bounds Checking
119+
## Bounds checking
120120

121121
For performance reasons, by default, `FastBufferReader` and `FastBufferWriter` **don't do bounds checking** on each write. Rather, they require the use of specific bounds checking functions - `TryBeginRead(int amount)` and `TryBeginWrite(int amount)`, respectively. This improves performance by allowing you to verify the space exists for the multiple values in a single call, rather than doing that check on every single operation.
122122

@@ -126,9 +126,9 @@ For performance reasons, by default, `FastBufferReader` and `FastBufferWriter` *
126126

127127
For convenience, every `WriteValue()` and `ReadValue()` method has an equivalent `WriteValueSafe()` and `ReadValueSafe()` that does bounds checking for you, throwing `OverflowException` if the boundary is exceeded. Additionally, some methods, such as arrays (where the amount of data being read can't be known until the size value is read) and [`INetworkSerializable`](inetworkserializable.md) values (where the size can't be predicted outside the implementation) will always do bounds checking internally.
128128

129-
## Bitwise Reading and Writing
129+
## Bitwise reading and writing
130130

131-
Writing values in sizes measured in bits rather than bytes comes with a cost
131+
Writing values in sizes measured in bits rather than bytes comes with a cost
132132
- First, it comes with a cost of having to track bitwise lengths and convert them to bytewise lenghts.
133133
- Second, it comes with a cost of having to remember to add padding after your bitwise writes and reads to ensure the next bytewise write or read functions correctly, and to make sure the buffer length includes any trailing bits.
134134

@@ -159,5 +159,3 @@ Packing values is done using the utility classes `BytePacker` and `ByteUnpacker`
159159
| uint | 30 bits (0 to 1,073,741,824) |
160160
| long | 60 bits + sign bit (-1,152,921,504,606,846,976 to 1,152,921,504,606,846,975) |
161161
| ulong | 61 bits (0 to 2,305,843,009,213,693,952) |
162-
163-

docs/advanced-topics/inscene_parenting_player.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ title: Real world In-scene NetworkObject parenting of players solution
44
description: In-scene NetworkObject parenting of players Solution
55
---
66

7-
8-
We received the following issue in Github.
9-
10-
## Issue:
7+
## Issue
118

129
When a player Prefab has a script that dynamically adds a parent to its transform, the client can't join a game hosted by another client. [You can see orignal issue here](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/issues/1211)
1310

@@ -18,8 +15,7 @@ Steps to reproduce the behavior:
1815
1. Launch one instance of the game as Host.
1916
1. Launch another instance and try to join as Client.
2017

21-
## Solution:
22-
18+
## Solution
2319

2420
If you want to do this when a player has first connected and all `NetworkObjects` (in-scene placed and already dynamically spawned by the server-host) have been fully synchronized with the client then we would recommend using the `NetworkManager.SceneManager.OnSceneEvent` to trap for the `SynchronizeComplete` event.
2521

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,32 @@ title: ClientRpc
55
import ImageSwitcher from '@site/src/ImageSwitcher.js';
66

77
:::warning
8-
ClientRpc and ServerRpc are legacy features of Netcode for GameObjects and have been replaced with the universal RPC attribute. This documentation is for legacy use. For current projects, use [Rpc](rpc.md) instead.
8+
`ClientRpc` and `ServerRpc` are legacy features of Netcode for GameObjects and have been replaced with the universal RPC attribute. This documentation is for legacy use. For current projects, use [RPCs](rpc.md) instead.
99
:::
1010

1111

12-
Servers can invoke a ClientRpc to execute on all clients.
12+
Servers can invoke a `ClientRpc` to execute on all clients.
1313

1414
<figure>
15-
<ImageSwitcher
15+
<ImageSwitcher
1616
lightImageSrc="/sequence_diagrams/RPCs/ClientRPCs.png?text=LightMode"
1717
darkImageSrc="/sequence_diagrams/RPCs/ClientRPCs_Dark.png?text=DarkMode"/>
1818
</figure>
1919

2020

2121

22-
## Declaring a ClientRpc
22+
## Declaring a `ClientRpc`
2323

24-
You can declare a ClientRpc by marking a method with the `[ClientRpc]` attribute and including the `ClientRpc` suffix in the method name.
24+
You can declare a `ClientRpc` by marking a method with the `[ClientRpc]` attribute and including the `ClientRpc` suffix in the method name.
2525

2626
```csharp
2727
[ClientRpc]
2828
void PongClientRpc(int somenumber, string sometext) { /* ... */ }
2929
```
3030

31-
## Invoking a ClientRpc
31+
## Invoking a `ClientRpc`
3232

33-
You can invoke a ClientRpc by invoking the function directly with parameters:
33+
You can invoke a `ClientRpc` by invoking the function directly with parameters:
3434

3535
```csharp
3636
void Update()
@@ -63,9 +63,9 @@ PongRpc(somenumber, sometext); // Is this a ServerRpc call or ClientRpc call?
6363
PongClientRpc(somenumber, sometext); // This is clearly a ClientRpc call
6464
```
6565

66-
## To send to one client, use ClientRpcSendParameters
66+
## To send to one client, use `ClientRpcSendParameters`
6767

68-
The following code provides an example of using ClientRpcSendParameters, which sends a ClientRpc to a specific client connection. The default Netcode for GameObjects behavior is to broadcast to every single client.
68+
The following code provides an example of using `ClientRpcSendParameters`, which sends a `ClientRpc` to a specific client connection. The default Netcode for GameObjects behavior is to broadcast to every single client.
6969

7070
```csharp
7171
private void DoSomethingServerSide(int clientId)
@@ -101,7 +101,7 @@ private void DoSomethingClientRpc(int randomInteger, ClientRpcParams clientRpcPa
101101
```
102102

103103
<figure>
104-
<ImageSwitcher
104+
<ImageSwitcher
105105
lightImageSrc="/sequence_diagrams/RPCs/ClientRPCs_CertainClients.png?text=LightMode"
106106
darkImageSrc="/sequence_diagrams/RPCs/ClientRPCs_CertainClients_Dark.png?text=DarkMode"/>
107107
<figcaption>Server can invoke a client RPC on a Network Object. The RPC will be placed in the local queue and then sent to a selection of clients (by default this selection is "all clients"). When received by a client, RPC will be executed on the client's version of the same Network Object.</figcaption>
@@ -113,20 +113,20 @@ The host is both a client and a server. If a host invokes a client RPC, it trigg
113113

114114

115115
<figure>
116-
<ImageSwitcher
116+
<ImageSwitcher
117117
lightImageSrc="/sequence_diagrams/RPCs/ClientRPCs_ClientHosts_CalledByClientHost.png?text=LightMode"
118118
darkImageSrc="/sequence_diagrams/RPCs/ClientRPCs_ClientHosts_CalledByClientHost_Dark.png?text=DarkMode"/>
119119
<figcaption>Hosts can invoke client RPCs on `NetworkObjects`. If broadcasting to all clients, the RPC will be immediately invoked on the host and placed in the local queue. At the end of the frame, the client RPC will be sent to the remote clients. When a remote client receives the client RPC it's executed on the client's local cloned instance of the same NetworkObject.</figcaption>
120120
</figure>
121121

122122
:::warning
123-
When running as a host, Netcode for GameObjects invokes RPCs immediately within the same stack as the method invoking the RPC. Since a host is both considered a server and a client, you should avoid design patterns where a ClientRpc invokes a ServerRpc that invokes the same ClientRpc as this can end up in a stack overflow (infinite recursion).
123+
When running as a host, Netcode for GameObjects invokes RPCs immediately within the same stack as the method invoking the RPC. Since a host is both considered a server and a client, you should avoid design patterns where a `ClientRpc` invokes a `ServerRpc` that invokes the same `ClientRpc` as this can end up in a stack overflow (infinite recursion).
124124
:::
125125

126126
See the [Boss Room RPC Examples](../../learn/bossroom/bossroom-actions.md).
127127

128128

129-
## Also see
129+
## Additional resources
130130

131-
* [ServerRpc](serverrpc.md)
131+
* [`ServerRpc`](serverrpc.md)
132132
* [RPC parameters](rpc-params.md)

0 commit comments

Comments
 (0)