diff --git a/docs/advanced-topics/object-pooling.md b/docs/advanced-topics/object-pooling.md
index 2b17d7dda..4e8dac44a 100644
--- a/docs/advanced-topics/object-pooling.md
+++ b/docs/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/docs/components/networkmanager.md b/docs/components/networkmanager.md
index 8eb91f548..044aaaa24 100644
--- a/docs/components/networkmanager.md
+++ b/docs/components/networkmanager.md
@@ -5,7 +5,7 @@ title: NetworkManager
The `NetworkManager` is a required Netcode for GameObjects component that has all of your project's netcode-related settings. Think of it as the central netcode hub for your netcode-enabled project.
-### `NetworkManager` Inspector properties
+## `NetworkManager` Inspector properties
- **LogLevel**: Sets the network logging level
- **PlayerPrefab**: When a prefab is assigned, the prefab will be instantiated as the PlayerObject and assigned to the newly connected and authorized client. For more information about player prefabs, refer to [PlayerObjects and player prefabs](../basics/playerobjects.md).
@@ -22,12 +22,19 @@ The `NetworkManager` is a required Netcode for GameObjects component that has al
- **Enable Scene Management**: When checked, Netcode for GameObjects will handle scene management and client synchronization for you. When not checked, you will have to create your own scene management scripts and handle client synchronization.
- **Load Scene Time Out**: When Enable Scene Management is checked, this specifies the period of time the `NetworkSceneManager` will wait while a scene is being loaded asynchronously before `NetworkSceneManager` considers the load/unload scene event to have failed/timed out.
+## Starting and stopping `NetworkManager`
+
+There are two static event notifications available when [starting](#starting-a-server-host-or-client) or [stopping](#disconnecting-and-shutting-down) `NetworkManager`. If you need to know when a `NetworkManager` has been instantiated or when it's in the process of being destroyed, there are two event notifications you can subscribe to:
+
+- The `NetworkManager.OnInstantiated` notification is triggered when a new `NetworkManager` instance has been instantiated.
+- The `NetworkManager.OnDestroying` notification is triggered when an existing `NetworkManager` instance is being destroyed.
+
### `NetworkManager` sub-systems
-`NetworkManager` is also where you can find references to other Netcode related management systems:
+`NetworkManager` is also where you can find references to other Netcode-related management systems:
:::caution
-All `NetworkManager` sub-systems are instantiated once the `NetworkManager` is started (that is, `NetworkManager.IsListening == true`). A good general "rule of thumb" is to not attempt to access the below sub-systems before starting the `NetworkManager`, otherwise they won't yet be initialized.
+All `NetworkManager` sub-systems are instantiated once the `NetworkManager` is started (either when `NetworkManager.IsListening == true` or after you've received a `NetworkManager.OnInstantiated` notification). Don't attempt to access the following sub-systems before starting the `NetworkManager`, otherwise they won't yet be initialized.
:::
- [NetworkManager.PrefabHandler](../advanced-topics/object-pooling.md): This provides access to the NetworkPrefabHandler that is used for NetworkObject pools and to have more control overriding network prefabs.
@@ -59,7 +66,7 @@ Don't start a `NetworkManager` within any `NetworkBehaviour` component's method;
- [Connection Approval](../basics/connection-approval)
:::
-## Connecting
+### Connecting
When starting a client, the `NetworkManager` uses the IP and the Port provided in your `Transport` component for connecting. While you can set the IP address in the editor, many times you might want to be able to set the IP address and port during runtime.
@@ -247,3 +254,7 @@ public class ConnectionNotificationManager : MonoBehaviour
}
}
```
+
+## Additional resources
+
+- [`NetworkManager` API documentation](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkManager.html)
diff --git a/docusaurus.config.js b/docusaurus.config.js
index a0d9ba46b..14310676e 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -237,9 +237,13 @@ module.exports = {
lastVersion: "current",
versions: {
current: {
- label: "2.0.0",
+ label: "2.1.1",
path: "current",
},
+ "2.0.0": {
+ label: "2.0.0",
+ path: "2.0.0",
+ },
"1.11.0": {
label: "1.11.0",
path: "1.11.0",
diff --git a/versioned_docs/version-1.10.0/advanced-topics/object-pooling.md b/versioned_docs/version-1.10.0/advanced-topics/object-pooling.md
index a6f45541d..83741000a 100644
--- a/versioned_docs/version-1.10.0/advanced-topics/object-pooling.md
+++ b/versioned_docs/version-1.10.0/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-1.11.0/advanced-topics/object-pooling.md b/versioned_docs/version-1.11.0/advanced-topics/object-pooling.md
index a6f45541d..83741000a 100644
--- a/versioned_docs/version-1.11.0/advanced-topics/object-pooling.md
+++ b/versioned_docs/version-1.11.0/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-1.3.0/advanced-topics/object-pooling.md b/versioned_docs/version-1.3.0/advanced-topics/object-pooling.md
index f35eff8b9..cd3c63ca4 100644
--- a/versioned_docs/version-1.3.0/advanced-topics/object-pooling.md
+++ b/versioned_docs/version-1.3.0/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.1.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-1.4.0/advanced-topics/object-pooling.md b/versioned_docs/version-1.4.0/advanced-topics/object-pooling.md
index f35eff8b9..cd3c63ca4 100644
--- a/versioned_docs/version-1.4.0/advanced-topics/object-pooling.md
+++ b/versioned_docs/version-1.4.0/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.1.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-1.5.2/advanced-topics/object-pooling.md b/versioned_docs/version-1.5.2/advanced-topics/object-pooling.md
index 29f054b82..002b1e8ec 100644
--- a/versioned_docs/version-1.5.2/advanced-topics/object-pooling.md
+++ b/versioned_docs/version-1.5.2/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-1.6.0/advanced-topics/object-pooling.md b/versioned_docs/version-1.6.0/advanced-topics/object-pooling.md
index 29f054b82..002b1e8ec 100644
--- a/versioned_docs/version-1.6.0/advanced-topics/object-pooling.md
+++ b/versioned_docs/version-1.6.0/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-1.7.1/advanced-topics/object-pooling.md b/versioned_docs/version-1.7.1/advanced-topics/object-pooling.md
index 29f054b82..002b1e8ec 100644
--- a/versioned_docs/version-1.7.1/advanced-topics/object-pooling.md
+++ b/versioned_docs/version-1.7.1/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-1.8.1/advanced-topics/object-pooling.md b/versioned_docs/version-1.8.1/advanced-topics/object-pooling.md
index a6f45541d..83741000a 100644
--- a/versioned_docs/version-1.8.1/advanced-topics/object-pooling.md
+++ b/versioned_docs/version-1.8.1/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-1.9.1/advanced-topics/object-pooling.md b/versioned_docs/version-1.9.1/advanced-topics/object-pooling.md
index a6f45541d..83741000a 100644
--- a/versioned_docs/version-1.9.1/advanced-topics/object-pooling.md
+++ b/versioned_docs/version-1.9.1/advanced-topics/object-pooling.md
@@ -25,4 +25,4 @@ The following example is from the Boss Room Sample. It shows how object pooling
https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
```
-Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. In the `InitializePool` method, called in `OnNetworkSpawn`, it initialises the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-2.0.0/about.md b/versioned_docs/version-2.0.0/about.md
new file mode 100644
index 000000000..f28e3e238
--- /dev/null
+++ b/versioned_docs/version-2.0.0/about.md
@@ -0,0 +1,65 @@
+---
+id: about
+title: About Netcode for GameObjects
+description: Overview of Unity's Netcode for GameObjects for your multiplayer networking needs.
+---
+
+Netcode for GameObjects is a high-level networking library built for Unity for you to abstract networking logic. You can send GameObjects and world data across a networking session to many players at once. With Netcode for GameObjects, you can focus on building your game instead of low-level protocols and networking frameworks.
+
+To learn more about Netcode for GameObjects functionality and capabilities, explore the content below:
+
+
+
+
+
+| Getting Started | Get Started Project | Education and Samples |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [Install Unity Netcode](installation/installation.md) [Migration from UNet to Netcode](installation/migratingfromUNet.md) [Upgrade to Unity Netcode Package](installation/migratingfrommlapi.md) | [Get started with Netcode](../docs/tutorials/get-started-with-ngo.md) | [Boss Room](learn/bossroom/getting-started-boss-room.md) [Bite Size Samples](learn/bitesize/bitesize-introduction.md) [Dilmer's Tutorials](community-contributions/dilmer-videos.md) |
+
+
+
+For more information, check out [Release Notes](release-notes/ngo-changelog.md) and [APIs](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/index.html).
+
+## Before you begin
+
+Netcode for GameObjects supports the following versions:
+
+- Unity 6.0+ and later
+- Mono and IL2CPP [Scripting Backends](https://docs.unity3d.com/Manual/scripting-backends.html)
+
+Netcode for GameObjects supports the following platforms:
+
+- Windows, macOS, and Linux
+- iOS and Android
+- XR platforms running on Windows, Android, and iOS operating systems
+- Most [**closed platforms**](https://unity.com/platform-installation), such as consoles. Contact us for more information about specific closed platforms.
+ - When working with consoles (such as PlayStation, Xbox, or Nintendo Switch), there may be Netcode-specific policies you should be aware of while testing and before launching your game live. Refer to the console's internal documentation for more information. This content is typically protected by NDA.
+- WebGL (requires Netcode for GameObjects 1.2.0+ and Unity Transport 2.0.0+)
diff --git a/versioned_docs/version-2.0.0/advanced-topics/bufferserializer.md b/versioned_docs/version-2.0.0/advanced-topics/bufferserializer.md
new file mode 100644
index 000000000..c9151271c
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/bufferserializer.md
@@ -0,0 +1,21 @@
+---
+id: bufferserializer
+title: BufferSerializer
+sidebar_label: BufferSerializer
+---
+
+`BufferSerializer` is the bi-directional serializer primarily used for serializing within [`INetworkSerializable`](inetworkserializable.md) types. It wraps [`FastBufferWriter` and `FastBufferReader`](fastbufferwriter-fastbufferreader.md) to provide high performance serialization, but has a couple of differences to make it more user-friendly:
+
+- Rather than writing separate methods for serializing and deserializing, `BufferSerializer` allows writing a single method that can handle both operations, which reduces the possibility of a mismatch between the two
+- `BufferSerializer` does bound checking on every read and write by default, making it easier to avoid mistakes around manual bounds checking required by `FastBufferWriter` and `FastBufferReader`
+
+These aren't without downsides, however:
+
+- `BufferSerializer` has to operate on an existing mutable value due to its bi-directional nature, which means values like `List.Count` have to be stored to a local variable before writing.
+- `BufferSerializer` is slightly slower than `FastBufferReader` and `FastBufferWriter` due to both the extra pass-through method calls and the mandatory bounds checking on each write.
+- `BufferSerializer` don't support any form of packed reads and writes.
+
+However, when those downsides are unreasonable, `BufferSerializer` offers two ways to perform more optimal serialization for either performance or bandwidth usage:
+
+- For performance, you can use `PreCheck(int amount)` followed by `SerializeValuePreChecked()` to perform bounds checking for multiple fields at once.
+- For both performance and bandwidth usage, you can obtain the wrapped underlying reader/writer via `serializer.GetFastBufferReader()` when `serializer.IsReader` is `true`, and `serializer.GetFastBufferWriter()` when `serializer.IsWriter` is `true`. These provide micro-performance improvements by removing a level of indirection, and also give you a type you can use with `BytePacker` and `ByteUnpacker`.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/client-anticipation.md b/versioned_docs/version-2.0.0/advanced-topics/client-anticipation.md
new file mode 100644
index 000000000..3c3420e1c
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/client-anticipation.md
@@ -0,0 +1,125 @@
+---
+id: client-anticipation
+title: Client anticipation
+---
+
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+:::info Client-server only
+
+Client anticipation is only relevant for games using a [client-server topology](../terms-concepts/client-server.md).
+
+:::
+Netcode for GameObjects doesn't support full client-side prediction and reconciliation, but it does support client anticipation: a simplified model that lacks the full rollback-and-replay prediction loop, but still provides a mechanism for anticipating the server result of an action and then correcting if you anticipated incorrectly.
+
+Client anticipation uses `AnticipatedNetworkVariable` and `AnticipatedNetworkTransform`. By calling their various `Anticipate` methods, you can set a visual value that differs from the server value and then react to updates from the server in different ways depending on how you have configured the `StaleDataHandling` property. Additionally, both include a [`Smooth` method](#smoothing-for-corrections) to support interpolation, either when receiving updated values from the server that don't match the anticipated value, or when receiving updates from other clients' actions that weren't anticipated at all.
+
+## Overview
+
+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.
+
+
+
+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:
+
+
+
+This creates a responsive feel to the gameplay, allowing the client player to feel as if things are responding immediately to their input and concealing latency.
+
+## The anticipated value
+
+Both `AnticipatedNetworkVariable` and `AnticipatedNetworkTransform` separate their values into two concepts: the anticipated (or visual) value and the authoritative value. These are exposed slightly differently between the two:
+
+- On `AnticipatedNetworkVariable`, the anticipated value is stored as `variable.Value`, while the authoritative value is stored as `variable.AuthoritativeValue`. To change the anticipated value on the client, call `variable.Anticipate(newValue)`, which sets the anticipated value to the newly provided value. On the server, calling `variable.Anticipate(newValue)` changes both the anticipated and authoritative values, enabling you to use the exact same code on the client and server. Likewise, `variable.AuthoritativeValue = newValue` also updates both values on the server, while this value is read-only on the client.
+- On `AnticipatedNetworkTransform`, the anticipated value is stored in both `gameObject.transform` and `anticipatedNetworkTransform.AnticipatedState`, both of which are read-only on the client, while the authoritative value is stored as `anticipatedNetworkTransform.AuthoritativeState`. If you only update the transform's values on the client, they are overwritten when the next server update comes in. To perform anticipation on the transform, you have to call `anticipatedNetworkTransform.AnticipateMove()`, `anticipatedNetworkTransform.AnticipateRotate()`, `anticipatedNetworkTransform.AnticipateScale()`, or `anticipatedNetworkTransform.AnticipateState()` to update all three at once. As with `AnticipatedNetworkVariable`, calling any of these on the server updates both the anticipated and authoritative values.
+
+## `StaleDataHandling`
+
+Anticipation systems need to be able to handle stale data. Stale data refers to updates from the server that represent actions that happened before your last request, and are actually going to be overwritten by that request.
+
+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.
+
+
+
+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.
+
+
+
+To address this, Netcode for GameObjects's client anticipation includes a feature called `StaleDataHandling`. Stale data is determined based on assumptions about causation - it assumes that, when you make an anticipation on the client side based on player input, an RPC is sent to the server at the same time requesting it to make the same change. It uses a continuously incrementing `AnticipationCounter` to track when the server has received and responded to the batch of requests that was sent on the same frame as the variable was anticipated. If an update for a variable arrives before the server has processed that message, the anticipation system regards that data as being stale.
+
+There are two ways you can respond to stale data, which are determined by the `StaleDataHandling` value on each `AnticipatedNetworkVariable` and `AnticipatedNetworkTransform`:
+
+- StaleDataHandling.Ignore
+- StaleDataHandling.Reanticipate
+
+### StaleDataHandling.Ignore
+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`.
+
+
+
+### StaleDataHandling.Reanticipate
+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.
+
+
+
+The `OnReanticipate` event can also be used for other purposes, such as "forward simulation" of an AI to anticipate a new position based on latency. This is considered advanced functionality, however, and implementing it is up to users.
+
+## `OnReanticipate` event
+
+`NetworkBehaviour` has a virtual method called `OnReanticipate`. When server data is received for an `AnticipatedNetworkVariable` or `AnticipatedNetworkTransform`, it's rolled back immediately, setting its anticipated state. During each frame in which a server update for any `AnticipatedNetworkVariable` or `AnticipatedNetworkTransform` is received (after **all** such operations have been performed and **all** objects are rolled back to their server state), each NetworkObject that had any rollbacks calls the `OnReanticipate` method on **all** of its `NetworkBehaviour`s.
+
+If you need to do any reanticipation to update the anticipated state of any of these variables or transforms, this method is where you will do it. `OnReanticipate` takes as its only parameter a `double` providing the amount of time, in seconds, that the object has been rolled back (which corresponds to the round-trip time of the current batch of responses received from the server). This value can be used to calculate the difference between what the server value is, and what the anticipated client value should be, and apply that change.
+
+However, note that not all variables and transforms on that object may have received updates, so not all of them will have been rolled back to a previous state. Before doing any reanticipation on any given variable or transform, you should check that variable/transform's `ShouldReanticipate` property. If this is `false`, then it still contains the most recent client anticipated value and no work is needed.
+
+### Global `OnReanticipate`
+
+In addition to the `NetworkBehaviour`'s `OnReanticipate` method, `NetworkManager` also has a callback that can be subscribed to for global reanticipation. This is useful if you need to run your reanticipation in a more global way, such as if you need to run it step-wise (say, anticipating one frame at a time) and need all objects to complete one step before any of them begin the second one. This callback receives the same `lastRoundTripTime` value as the `NetworkBehaviour` method, and is called after all of the `NetworkBehaviour` methods have been called.
+
+:::note
+
+If you want to implement a full client-side prediction model in your game, the global OnReanticipate callback is likely the ideal place to incorporate your rollback and replay logic. The details of implementing this, however, are left up to users. Implementing a full, production-ready prediction loop is a complex topic and recommended for advanced users only.
+
+:::
+
+## Smoothing for corrections
+
+Most anticipations will be correct and the server will update the state to the same value. Sometimes, however, the server will have a different result, since latency can cause the server state to change before it receives your command in ways that affect the result. When this happens, by default, the value will be snapped to the new server value.
+
+This can result in an undesirable player experience, causing things that normally move smoothly to become choppy. When this happens, you can smooth out the result by using the `Smooth()` function on both `AnticipatedNetworkVariable` and `AnticipatedNetworkTransform`.
+
+`Smooth()` takes a starting position (usually the previous anticipated value), a final position (usually the new anticipated value or the current authoritative value), and a duration over which to perform the smoothing. For `AnticipatedNetworkVariable`, because the type is generic, it also requires a delegate to use to perform the smoothing operation (which takes a from value, a to value, and a percent value, and in many cases may just be `Mathf.Lerp`).
+
+For convenience, you can use `PreviousAnticipatedValue` and `PreviousAnticipatedState` to access the value most recently passed into `Anticipate()` for `AnticipatedNetworkVariable` and `AnticipatedNetworkTransform` respectively. Note, however, that if you call `Anticipate()` or its related transform methods prior to doing the smoothing, they will update the previous anticipated value, so you may need to store the previous anticipated value in a local variable before doing your reanticipation.
+
+### Server-side smoothing
+
+Even though these concepts are mostly for client-side use, there are cases where you might want to perform server-side smoothing as well. For example, when running in host mode, the host player sees the movement of other players. Due to latency and jitter, input updates from remote clients may not arrive every frame, which may result in choppy movement of an `AnticipatedNetworkTransform`, for example.
+
+To address this, you can also use the `Smooth()` function at any time on the server side. The server doesn't do anticipation, so it will not get any `OnReanticipate()` events, but you can, for example, call `Smooth()` each time you receive an input from the client to smooth the motion between the previous position and the new one.
+
+One important distinction between client-side smoothing and server-side smoothing for `AnticipatedNetworkTransform`, however, is that client-side smoothing smooths the actual motion of the transform, while server-side smoothing only smooths the visual depiction of the motion. Which is to say, `AnticipatedState` is updated, but `transform` is not, so all game logic and collision detection is done based on the actual position, and the rendering of the object will be slightly behind the actual position of the object.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/connection-events.md b/versioned_docs/version-2.0.0/advanced-topics/connection-events.md
new file mode 100644
index 000000000..2c67b9bc3
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/connection-events.md
@@ -0,0 +1,35 @@
+---
+id: connection-events
+title: Connection events
+
+---
+
+When you need to react to connection or disconnection events for yourself or other clients, you can use `NetworkManager.OnConnectionEvent` as a unified source of information about changes in the network. Connection events are session-mode agnostic and work in both [client-server](../terms-concepts/client-server.md) and [distributed authority](../terms-concepts/distributed-authority.md) contexts.
+
+`OnConnectionEvent` receives a `ConnectionEventData` struct detailing the relevant information about the connection state change:
+
+```csharp
+public enum ConnectionEvent
+{
+ ClientConnected,
+ PeerConnected,
+ ClientDisconnected,
+ PeerDisconnected
+}
+
+public struct ConnectionEventData
+{
+ public ConnectionEvent EventType;
+ public ulong ClientId;
+ public NativeArray PeerClientIds;
+}
+```
+
+There are four types of event you can receive. The events are the same for both clients and servers/hosts, but they indicate slightly different things depending on the context.
+
+|Event |Server or host |Client |
+|---|---|---|
+|`ConnectionEvent.ClientConnected` |Indicates that a new client has connected. The ID of the newly connected client is `ClientId`. `PeerClientIds` is uninitialized and shouldn't be used.|Indicates that the local client has completed its connection to the server. The ID of the client is `LocalClientId`, and `PeerClientIds` contains a list of client IDs of other clients currently connected to the server.|
+|`ConnectionEvent.PeerConnected` |Not applicable for servers. For host clients running in host mode, works the same as for clients.|Indicates that another client has connected to the server. The ID of the newly connected client is `ClientId`. `PeerClientIds` is uninitialized and shouldn't be used. |
+|`ConnectionEvent.ClientDisconnected`|Indicates that a client has disconnected. The ID of the disconnected client is `ClientId`. `PeerClientIds` is uninitialized and shouldn't be used.|Indicates that the local client has disconnected from the server. The ID of the client is `LocalClientId`. `PeerClientIds` is uninitialized and shouldn't be used. |
+|`ConnectionEvent.PeerDisconnected` |Not applicable for servers. For host clients running in host mode, works the same as for clients.| Indicates that another client has disconnected from the server. The ID of the disconnected client is `ClientId`. `PeerClientIds` is uninitialized and shouldn't be used.|
diff --git a/versioned_docs/version-2.0.0/advanced-topics/custom-serialization.md b/versioned_docs/version-2.0.0/advanced-topics/custom-serialization.md
new file mode 100644
index 000000000..3d8a96765
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/custom-serialization.md
@@ -0,0 +1,97 @@
+---
+id: custom-serialization
+title: Custom serialization
+---
+
+Netcode uses a default serialization pipeline when using `RPC`s, `NetworkVariable`s, or any other Netcode-related tasks that require serialization. The serialization pipeline looks like this:
+
+``
+Custom Types => Built In Types => INetworkSerializable
+``
+
+That is, when Netcode first gets hold of a type, it will check for any custom types that the user have registered for serialization, after that it will check if it's a built in type, such as a Vector3, float etc. These are handled by default. If not, it will check if the type inherits `INetworkSerializable`, if it does, it will call it's write methods.
+
+By default, any type that satisfies the `unmanaged` generic constraint can be automatically serialized as RPC parameters. This includes all basic types (bool, byte, int, float, enum, etc) as well as any structs that has only these basic types.
+
+With this flow, you can provide support for serializing any unsupported types, and with the API provided, it can even be done with types that you haven't defined yourself, those who are behind a 3rd party wall, such as .NET types. However, the way custom serialization is implemented for RPCs and NetworkVariables is slightly different.
+
+### Serialize a type in a Remote Procedure Call (RPC)
+
+:::note
+From versioln 1.7.0 Remote Procedure Calls (RPCs) can also use the Network Variable flow, but NetworkVariables can't use the RPC flow. The RPC flow is more efficient when RPCs serialize the type. Unity selects the RPC flow if you implement both the RPC and Network variable flows. When a type is used by both NetworkVariables and RPCs you can use the NetworkVariable flow to lower maintenance requirements.
+:::
+
+To register a custom type, or override an already handled type, you need to create extension methods for `FastBufferReader.ReadValueSafe()` and `FastBufferWriter.WriteValueSafe()`:
+
+```csharp
+// Tells the Netcode how to serialize and deserialize Url in the future.
+// The class name doesn't matter here.
+public static class SerializationExtensions
+{
+ public static void ReadValueSafe(this FastBufferReader reader, out Url url)
+ {
+ reader.ReadValueSafe(out string val);
+ url = new Url(val);
+ }
+
+ public static void WriteValueSafe(this FastBufferWriter writer, in Url url)
+ {
+ writer.WriteValueSafe(url.Value);
+ }
+}
+```
+
+The code generation for RPCs will automatically pick up and use these functions, and they'll become available via `FastBufferWriter` and `FastBufferReader` directly.
+
+You can also optionally use the same method to add support for `BufferSerializer.SerializeValue()`, if you wish, which will make this type readily available within [`INetworkSerializable`](/advanced-topics/serialization/inetworkserializable.md) types:
+
+```csharp
+// The class name doesn't matter here.
+public static class SerializationExtensions
+{
+ public static void SerializeValue(this BufferSerializer serializer, ref Url url) where TReaderWriter: IReaderWriter
+ {
+ if (serializer.IsReader)
+ {
+ url = new Url();
+ }
+ serializer.SerializeValue(ref url.Value);
+ }
+}
+```
+
+Additionally, you can also add extensions for `FastBufferReader.ReadValue()`, `FastBufferWriter.WriteValue()`, and `BufferSerializer.SerializeValuePreChecked()` to provide more optimal implementations for manual serialization using `FastBufferReader.TryBeginRead()`, `FastBufferWriter.TryBeginWrite()`, and `BufferSerializer.PreCheck()`, respectively. However, none of these will be used for serializing RPCs - only `ReadValueSafe` and `WriteValueSafe` are used.
+
+### For NetworkVariable
+
+`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.
+
+To add custom serialization support in `NetworkVariable`, follow the steps from the "For RPCs" section to write extension methods for `FastBufferReader` and `FastBufferWriter`; then, somewhere in your application startup (before any `NetworkVariable`s using the affected types will be serialized) add the following:
+
+```csharp
+UserNetworkVariableSerialization.WriteValue = SerializationExtensions.WriteValueSafe;
+UserNetworkVariableSerialization.ReadValue = SerializationExtensions.ReadValueSafe;
+```
+
+You can also use lambda expressions here:
+
+```csharp
+UserNetworkVariableSerialization.WriteValue = (FastBufferWriter writer, in Url url) =>
+{
+ writer.WriteValueSafe(url.Value);
+};
+
+UserNetworkVariableSerialization.ReadValue = (FastBufferReader reader, out Url url)
+{
+ reader.ReadValueSafe(out string val);
+ url = new Url(val);
+};
+```
+
+When you create an extension method in `NetworkVariable` you need to implement the following values:
+
+- `WriteValue`
+- `ReadValue`
+- `DuplicateValue`
+
+`DuplicateValue` returns a complete deep copy of the value that `NetworkVariable` compares to a previous value to check whether or not that values has changed. This avoids reserializing it over the network every frame when it hasn't changed.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/fastbufferwriter-fastbufferreader.md b/versioned_docs/version-2.0.0/advanced-topics/fastbufferwriter-fastbufferreader.md
new file mode 100644
index 000000000..5b7fd43e1
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/fastbufferwriter-fastbufferreader.md
@@ -0,0 +1,163 @@
+---
+id: fastbufferwriter-fastbufferreader
+title: FastBufferWriter and FastBufferReader
+sidebar_label: FastBufferWriter and FastBufferReader
+---
+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.
+
+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.
+
+
+**Example**
+
+```csharp
+struct ExampleStruct
+{
+ private float f;
+ private bool b;
+ private int i;
+
+ void Serialize(FastBufferWriter writer);
+}
+```
+
+In this example struct, `Serialize` can be implemented in two ways:
+
+```csharp
+void Serialize(FastBufferWriter writer)
+{
+ if(!writer.TryBeginWrite(sizeof(float) + sizeof(bool) + sizeof(i)))
+ {
+ throw new OverflowException("Not enough space in the buffer");
+ }
+ writer.WriteValue(f);
+ writer.WriteValue(b);
+ writer.WriteValue(i);
+}
+```
+
+```csharp
+void Serialize(FastBufferWriter writer)
+{
+ if(!writer.TryBeginWrite(sizeof(ExampleStruct)))
+ {
+ throw new OverflowException("Not enough space in the buffer");
+ }
+ writer.WriteValue(this);
+}
+```
+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:
+- First, it involves more method calls and more instructions, making it slower.
+- 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.
+
+You can also use a hybrid approach if you have a few values that will need to be packed and several that won't:
+
+```C#
+struct ExampleStruct
+{
+ struct Embedded
+ {
+ private byte a;
+ private byte b;
+ private byte c;
+ private byte d;
+ }
+ public Embedded embedded;
+ public float f;
+ public short i;
+
+ void Serialize(FastBufferWriter writer)
+ {
+ writer.WriteValue(embedded);
+ BytePacker.WriteValuePacked(writer, f);
+ BytePacker.WriteValuePacked(writer, i);
+ }
+}
+```
+
+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.
+
+
+## FastBufferWriter and FastBufferReader
+
+`FastBufferWriter` and `FastBufferReader` are replacements for the old `NetworkWriter` and `NetworkReader`. For those familiar with the old classes, there are some key differences:
+
+- `FastBufferWriter` uses `WriteValue()` as the name of the method for all types *except* [`INetworkSerializable`](serialization/inetworkserializable) types, which are serialized through `WriteNetworkSerializable()`
+- `FastBufferReader` similarly uses `ReadValue()` for all types except INetworkSerializable (which is read through `ReadNetworkSerializable`), with the output changed from a return value to an `out` parameter to allow for method overload resolution to pick the correct value.
+- `FastBufferWriter` and `FastBufferReader` outsource packed writes and reads to `BytePacker` and `ByteUnpacker`, respectively.
+- `FastBufferWriter` and `FastBufferReader` are **structs**, not **classes**. This means they can be constructed and destructed without GC allocations.
+- `FastBufferWriter` and `FastBufferReader` both use the same allocation scheme as Native Containers, allowing the internal buffers to be created and resized without creating any garbage and with the use of `Allocator.Temp` or `Allocator.TempJob`.
+- `FastBufferReader` can be instantiated using `Allocator.None` to operate on an existing buffer with no allocations and no copies.
+- Neither `FastBufferReader` nor `FastBufferWriter` inherits from nor has a `Stream`.
+- `FastBufferReader` and `FastBufferWriter` are heavily optimized for speed, using aggressive inlining and unsafe code to achieve the fastest possible buffer storage and retrieval.
+- `FastBufferReader` and `FastBufferWriter` use unsafe typecasts and `UnsafeUtility.MemCpy` operations on `byte*` values, achieving native memory copy performance with no need to iterate or do bitwise shifts and masks.
+- `FastBufferReader` and `FastBufferWriter` are intended to make data easier to debug - one such thing to support will be a `#define MLAPI_FAST_BUFFER_UNPACK_ALL` that will disable all packing operations to make the buffers for messages that use them easier to read.
+- `FastBufferReader` and `FastBufferWriter` don't support runtime type discovery - there is no `WriteObject` or `ReadObject` implementation. All types must be known at compile time. This is to avoid garbage and boxing allocations.
+
+A core benefit of `NativeArray` 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.
+
+## Creating and Disposing FastBufferWriters and FastBufferReaders
+
+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.
+
+`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.
+
+`FastBufferReader` can be constructed to either own its buffer or reference an existing one via `Allocator.None`. Not all types are compatible with `Allocator.None` - only `byte*`, `NativeArray`, and `FastBufferWriter` input types can provide `Allocator.None`. You can obtain a `byte*` from a `byte[]` using the following method:
+
+```c#
+byte[] byteArray;
+fixed(byte* bytePtr = byteArray)
+{
+ // use bytePtr here
+}
+```
+
+It's important to note with `Allocator.None` that the `FastBufferReader` will be directly referencing a position in memory, which means the `FastBufferReader` must not live longer than the input buffer it references - and if the input buffer is a `byte[]`, the `FastBufferReader` must not live longer than the `fixed()` statement, because outside of that statement, the garbage collector is free to move that memory, which will cause random and unpredictable errors.
+
+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.
+
+## Bounds Checking
+
+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.
+
+:::info
+**In editor mode and development builds**, calling these functions records a watermark point, and any attempt to read or write past the watermark point will throw an exception. This ensures these functions are used properly, while avoiding the performance cost of per-operation checking in production builds. In production builds, attempting to read or write past the end of the buffer will cause undefined behavior, likely program instability and/or crashes.
+:::
+
+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.
+
+## Bitwise Reading and Writing
+
+Writing values in sizes measured in bits rather than bytes comes with a cost
+- First, it comes with a cost of having to track bitwise lengths and convert them to bytewise lenghts.
+- 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.
+
+To address that, `FastBufferReader` and `FastBufferWriter` don't, themselves, have bitwise operations. When needed, however, you can create a `BitWriter` or `BitReader` instance, which is used ensure that no unaligned bits are left at the end - from the perspective of `FastBufferReader` and `FastBufferWriter`, only bytes are allowed. `BitWriter` and `BitReader` operate directly on the underlying buffer, so calling non-bitwise operations within a bitwise context is an error (and will raise an exception in non-production builds).
+
+```csharp
+FastBufferWriter writer = new FastBufferWriter(256, Allocator.TempJob);
+using(var bitWriter = writer.EnterBitwiseContext())
+{
+ bitWriter.WriteBit(a);
+ bitWriter.WriteBits(b, 5);
+} // Dispose automatically adds 2 more 0 bits to pad to the next byte.
+```
+
+## Packing
+
+Packing values is done using the utility classes `BytePacker` and `ByteUnpacker`. These generally offer two different ways of packing values:
+
+- `BytePacker.WriteValuePacked()`/`ByteUnpacker.ReadValuePacked()` are the most versatile. They can write any range of values that fit into the type, and also have special built-in methods for many common Unity types that can automatically pack the values contained within.
+
+- `BytePacker.WriteValueBitPacked()`/`ByteUnpacker.ReadValueBitPacked()` offer tighter/more optimal packing (the data in the buffer will never exceed `sizeof(type)`, which can happen with large values using `WriteValuePacked()`, and will usually be one byte smaller than with `WriteValuePacked()` except for values <= 240, which will be one byte with both methods), but come with the limitations that they can only be used on integral types, and they use some bits of the type to encode length information, meaning that they reduce the usable size of the type. The sizes allowed by these functions are as follows:
+
+ | Type | Usable Size |
+ | ------ | ------------------------------------------------------------ |
+ | short | 14 bits + sign bit (-16,384 to 16,383) |
+ | ushort | 15 bits (0 to 32,767) |
+ | int | 29 bits + sign bit (-536,870,912 to 536,870,911) |
+ | uint | 30 bits (0 to 1,073,741,824) |
+ | long | 60 bits + sign bit (-1,152,921,504,606,846,976 to 1,152,921,504,606,846,975) |
+ | ulong | 61 bits (0 to 2,305,843,009,213,693,952) |
+
+
diff --git a/versioned_docs/version-2.0.0/advanced-topics/inscene_parenting_player.md b/versioned_docs/version-2.0.0/advanced-topics/inscene_parenting_player.md
new file mode 100644
index 000000000..54a92836b
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/inscene_parenting_player.md
@@ -0,0 +1,92 @@
+---
+id: inscene-parenting-players
+title: Real world In-scene NetworkObject parenting of players solution
+description: In-scene NetworkObject parenting of players Solution
+---
+
+
+We received the following issue in Github.
+
+## Issue:
+
+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)
+
+Steps to reproduce the behavior:
+
+1. Set up basic networking game with at least one `GameObject` in a scene that isn't the player.
+1. Add a script to the player Prefab that adds parenting to its transform via `gameObject.transform.SetParent()` in the `Start()` method.
+1. Launch one instance of the game as Host.
+1. Launch another instance and try to join as Client.
+
+## Solution:
+
+
+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.
+
+Here is an example script that we recommend using to achieve this:
+
+```csharp
+using Unity.Netcode;
+
+public class ParentPlayerToInSceneNetworkObject : NetworkBehaviour
+{
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer)
+ {
+ // Server subscribes to the NetworkSceneManager.OnSceneEvent event
+ NetworkManager.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent;
+
+ // Server player is parented under this NetworkObject
+ SetPlayerParent(NetworkManager.LocalClientId);
+ }
+ }
+
+ private void SetPlayerParent(ulong clientId)
+ {
+ if (IsSpawned && IsServer)
+ {
+ // As long as the client (player) is in the connected clients list
+ if (NetworkManager.ConnectedClients.ContainsKey(clientId))
+ {
+ // Set the player as a child of this in-scene placed NetworkObject
+ // We parent in local space by setting the WorldPositionStays value to false
+ NetworkManager.ConnectedClients[clientId].PlayerObject.TrySetParent(NetworkObject, false);
+ }
+ }
+ }
+
+ private void SceneManager_OnSceneEvent(SceneEvent sceneEvent)
+ {
+ // OnSceneEvent is useful for many things
+ switch (sceneEvent.SceneEventType)
+ {
+ // The SceneEventType event tells the server that a client-player has:
+ // 1.) Connected and Spawned
+ // 2.) Loaded all scenes that were loaded on the server at the time of connecting
+ // 3.) Synchronized (instantiated and spawned) all NetworkObjects in the network session
+ case SceneEventType.SynchronizeComplete:
+ {
+ // As long as we aren't the server-player
+ if (sceneEvent.ClientId != NetworkManager.LocalClientId)
+ {
+ // Set the newly joined and synchronized client-player as a child of this in-scene placed NetworkObject
+ SetPlayerParent(sceneEvent.ClientId);
+ }
+ break;
+ }
+ }
+ }
+}
+```
+
+You should place this script on your in-scene placed NetworkObject (that is, the first `GameObject`) and do the parenting from it to avoid any timing issues of when it's spawned or the like. It only runs the script on the server-host side since parenting is server authoritative.
+
+
+:::note
+Remove any parenting code you might have had from your player Prefab before using the above script. Depending upon your project's goals, you might be parenting all players under the same in-scene placed NetworkObject or you might intend to have each player parenting unique. If you want each player to be parented under a unique in-scene placed NetworkObject then you will need to have the same number of in-scene placed NetworkObjects as your maximum allowed players per game session. The above example will only parent all players under the same in-scene placed NetworkObject. You can extend the above example by migrating the scene event code into an in-scene placed NetworkObject that manages the parenting of players (i,e. name it something like `PlayerSpawnManager`) as they connect, make the `SetPlayerParent` method public, and add all in-scene placed NetworkObjects to a public list of GameObjects that the `PlayerSpawnManager` will reference and assign player's to as they connect while also freeing in-scene placed NetworkObjects as players disconnect during a game session.
+:::
+
+:::important
+Netcode for GameObjects v1.2 has a [known issue](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/pull/2396) with parenting dynamically spawned `NetworkObjects` under in-scene placed `NetworkObjects`. This will be fixed in the next update.
+:::
diff --git a/versioned_docs/version-2.0.0/advanced-topics/message-system/clientrpc.md b/versioned_docs/version-2.0.0/advanced-topics/message-system/clientrpc.md
new file mode 100644
index 000000000..f750d7af4
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/message-system/clientrpc.md
@@ -0,0 +1,132 @@
+---
+id: clientrpc
+title: ClientRpc
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+:::warning
+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.
+:::
+
+
+Servers can invoke a ClientRpc to execute on all clients.
+
+
+
+
+
+## Declaring a ClientRpc
+
+You can declare a ClientRpc by marking a method with the `[ClientRpc]` attribute and including the `ClientRpc` suffix in the method name.
+
+```csharp
+[ClientRpc]
+void PongClientRpc(int somenumber, string sometext) { /* ... */ }
+```
+
+## Invoking a ClientRpc
+
+You can invoke a ClientRpc by invoking the function directly with parameters:
+
+```csharp
+void Update()
+{
+ if (Input.GetKeyDown(KeyCode.P))
+ {
+ PongClientRpc(Time.frameCount, "hello, world"); // Server -> Client
+ }
+}
+```
+
+You must mark client RPC methods with the `[ClientRpc]` attribute and use the `ClientRpc` method suffix; failing to do so results in an error message.
+
+```csharp
+// Error: Invalid, missing 'ClientRpc' suffix in the method name
+[ClientRpc]
+void Pong(int somenumber, string sometext) { /* ... */ }
+
+// Error: Invalid, missing [ClientRpc] attribute on the method
+void PongClientRpc(int somenumber, string sometext) { /* ... */ }
+```
+
+The `[ClientRpc]` attribute and matching `...ClientRpc` suffix in the method name help to assure context clarity in scripts that invoke them and are used by Netcode during the ILPostProcessor pass. The ILPostProcessor pass replaces all call-site locations where the RPC method is invoked, with additional code generated specific to the RPC to assure that the RPC message is generated and sent to the appropriate destinations/targets as opposed to just locally invoking the method.
+
+```csharp
+Pong(somenumber, sometext); // Is this an RPC call?
+
+PongRpc(somenumber, sometext); // Is this a ServerRpc call or ClientRpc call?
+
+PongClientRpc(somenumber, sometext); // This is clearly a ClientRpc call
+```
+
+## To send to one client, use ClientRpcSendParameters
+
+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.
+
+```csharp
+private void DoSomethingServerSide(int clientId)
+{
+ // If isn't the Server/Host then we should early return here!
+ if (!IsServer) return;
+
+
+ // NOTE! In case you know a list of ClientId's ahead of time, that does not need change,
+ // Then please consider caching this (as a member variable), to avoid Allocating Memory every time you run this function
+ ClientRpcParams clientRpcParams = new ClientRpcParams
+ {
+ Send = new ClientRpcSendParams
+ {
+ TargetClientIds = new ulong[]{clientId}
+ }
+ };
+
+ // Let's imagine that you need to compute a Random integer and want to send that to a client
+ const int maxValue = 4;
+ int randomInteger = Random.Range(0, maxValue);
+ DoSomethingClientRpc(randomInteger, clientRpcParams);
+}
+
+[ClientRpc]
+private void DoSomethingClientRpc(int randomInteger, ClientRpcParams clientRpcParams = default)
+{
+ if (IsOwner) return;
+
+ // Run your client-side logic here!!
+ Debug.LogFormat("GameObject: {0} has received a randomInteger with value: {1}", gameObject.name, randomInteger);
+}
+```
+
+
+
+## Invoking a client RPC from the host
+
+The host is both a client and a server. If a host invokes a client RPC, it triggers the on all clients, including the host.
+
+
+
+
+:::warning
+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).
+:::
+
+See the [Boss Room RPC Examples](../../learn/bossroom/bossroom-actions.md).
+
+
+## Also see
+
+* [ServerRpc](serverrpc.md)
+* [RPC parameters](rpc-params.md)
diff --git a/versioned_docs/version-2.0.0/advanced-topics/message-system/custom-messages.md b/versioned_docs/version-2.0.0/advanced-topics/message-system/custom-messages.md
new file mode 100644
index 000000000..8a5741d15
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/message-system/custom-messages.md
@@ -0,0 +1,302 @@
+---
+id: custom-messages
+title: Custom messages
+description: A brief explanation of Custom Messages use in Netcode for GameObjects (Netcode) covering Named and Unnamed messages.
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+If you don't want to use the Netcode for GameObjects (Netcode) messaging system, you don't have to. You can use a thin layer called "Custom Messages" to implement your own messaging behavior or add custom targeting. They're unbound to any GameObject. You can use Custom messages with [RPC messages](../messaging-system.md).
+
+There are two types of custom messages:
+- Unnamed
+- Named
+
+## Unnamed Messages
+You can think about unnamed messages as if you are sending information over a single unique channel. There's only one receiver handler per unnamed message, which can help when building a custom messaging system where you can define your own message headers. Netcode for GameObjects handles delivering and receiving custom unnamed messages; you determine what kind of information you want to transmit over the channel.
+
+### Unnamed Message Example
+Below is a basic example of how you might implement your own messaging system using unnamed messages:
+```csharp
+using UnityEngine;
+using Unity.Collections;
+using Unity.Netcode;
+
+///
+/// Using an unnamed message to send a string message
+/// defined
+/// further down below.
+///
+public class UnnamedStringMessageHandler : CustomUnnamedMessageHandler
+{
+ ///
+ /// We override this method to define the unique message type
+ /// identifier for this child derived class
+ ///
+ protected override byte MessageType()
+ {
+ // As an example, we can define message type of 1 for string messages
+ return 1;
+ }
+
+ public override void OnNetworkSpawn()
+ {
+ // For this example, we always want to invoke the base
+ base.OnNetworkSpawn();
+
+ if (IsServer)
+ {
+ // Server broadcasts to all clients when a new client connects
+ // (just for example purposes)
+ NetworkManager.OnClientConnectedCallback += OnClientConnectedCallback;
+ }
+ else
+ {
+ // Clients send a greeting string message to the server
+ SendUnnamedMessage("I am a client connecting!");
+ }
+ }
+
+ public override void OnNetworkDespawn()
+ {
+ // For this example, we always want to invoke the base
+ base.OnNetworkDespawn();
+
+ // Whether server or not, unregister this.
+ NetworkManager.OnClientDisconnectCallback -= OnClientConnectedCallback;
+ }
+
+ private void OnClientConnectedCallback(ulong clientId)
+ {
+ // Server broadcasts a welcome string message to all clients that
+ // a new client has joined.
+ SendUnnamedMessage($"Everyone welcome the newly joined client ({clientId})!");
+ }
+
+ ///
+ /// For this example, we override this message to handle receiving the string
+ /// message.
+ ///
+ protected override void OnReceivedUnnamedMessage(ulong clientId, FastBufferReader reader)
+ {
+ var stringMessage = string.Empty;
+ reader.ReadValueSafe(out stringMessage);
+ if (IsServer)
+ {
+ Debug.Log($"Server received unnamed message of type ({MessageType()}) from client " +
+ $"({clientId}) that contained the string: \"{stringMessage}\"");
+
+ // As an example, we can also broadcast the client message to everyone
+ SendUnnamedMessage($"Newly connected client sent this greeting: \"{stringMessage}\"");
+ }
+ else
+ {
+ Debug.Log(stringMessage);
+ }
+ }
+
+ ///
+ /// For this example, we will send a string as the payload.
+ ///
+ /// IMPORTANT NOTE: You can construct your own header to be
+ /// written for custom message types, this example just uses
+ /// the message type value as the "header". This provides us
+ /// with the ability to have "different types" of unnamed
+ /// messages.
+ ///
+ public override void SendUnnamedMessage(string dataToSend)
+ {
+ var writer = new FastBufferWriter(1100, Allocator.Temp);
+ var customMessagingManager = NetworkManager.CustomMessagingManager;
+ // Tip: Placing the writer within a using scope assures it will
+ // be disposed upon leaving the using scope
+ using (writer)
+ {
+ // Write our message type
+ writer.WriteValueSafe(MessageType());
+
+ // Write our string message
+ writer.WriteValueSafe(dataToSend);
+ if (IsServer)
+ {
+ // This is a server-only method that will broadcast the unnamed message.
+ // Caution: Invoking this method on a client will throw an exception!
+ customMessagingManager.SendUnnamedMessageToAll(writer);
+ }
+ else
+ {
+ // This method can be used by a client or server (client to server or server to client)
+ customMessagingManager.SendUnnamedMessage(NetworkManager.ServerClientId, writer);
+ }
+ }
+ }
+}
+
+///
+/// A templated class to handle sending different data types
+/// per unique unnamed message type/child derived class.
+///
+public class CustomUnnamedMessageHandler : NetworkBehaviour
+{
+ ///
+ /// Since there is no unique way to identify unnamed messages,
+ /// adding a message type identifier to the message itself is
+ /// one way to handle know:
+ /// "what kind of unnamed message was received?"
+ ///
+ protected virtual byte MessageType()
+ {
+ // The default unnamed message type
+ return 0;
+ }
+
+ ///
+ /// For most cases, you want to register once your NetworkBehaviour's
+ /// NetworkObject (typically in-scene placed) is spawned.
+ ///
+ public override void OnNetworkSpawn()
+ {
+ // Both the server-host and client(s) will always subscribe to the
+ // the unnamed message received event
+ NetworkManager.CustomMessagingManager.OnUnnamedMessage += ReceiveMessage;
+ }
+
+ public override void OnNetworkDespawn()
+ {
+ // Unsubscribe when the associated NetworkObject is despawned.
+ NetworkManager.CustomMessagingManager.OnUnnamedMessage -= ReceiveMessage;
+ }
+
+ ///
+ /// This method needs to be overridden to handle reading a unique message type
+ /// (that is, derived class)
+ ///
+ protected virtual void OnReceivedUnnamedMessage(ulong clientId, FastBufferReader reader)
+ {
+ }
+
+ ///
+ /// For this unnamed message example, we always read the message type
+ /// value to determine if it should be handled by this instance in the
+ /// event it's a child of the CustomUnnamedMessageHandler class.
+ ///
+ private void ReceiveMessage(ulong clientId, FastBufferReader reader)
+ {
+ var messageType = (byte)0;
+ // Read the message type value that is written first when we send
+ // this unnamed message.
+ reader.ReadValueSafe(out messageType);
+ // Example purposes only, you might handle this in a more optimal way
+ if (messageType == MessageType())
+ {
+ OnReceivedUnnamedMessage(clientId, reader);
+ }
+ }
+
+ ///
+ /// For simplicity, the default does nothing
+ ///
+ ///
+ public virtual void SendUnnamedMessage(T dataToSend)
+ {
+
+ }
+}
+```
+## Named Messages
+If you don't want to handle the complexity of creating your own messaging system, Netcode for GameObjects also provides you with the option to use custom named messages. Custom named messages use the message name as the unique identifier (it creates a hash value from the name and links that to a received named message callback).
+
+:::tip
+If you aren't quite sure if you need to incorporate the complexity of message identification and handling like you do with custom unnamed messages, you can always start with custom named messages and then if, later, you find you need sub-message types for a specific custom named message then you can always incorporate a type identifier (like you would with unnamed messages) into the named message payload itself.
+:::
+
+### Name Message Example
+Below is a basic example of implementing a custom named message:
+```csharp
+using System;
+using UnityEngine;
+using Unity.Collections;
+using Unity.Netcode;
+public class CustomNamedMessageHandler : NetworkBehaviour
+{
+ [Tooltip("The name identifier used for this custom message handler.")]
+ public string MessageName = "MyCustomNamedMessage";
+
+ ///
+ /// For most cases, you want to register once your NetworkBehaviour's
+ /// NetworkObject (typically in-scene placed) is spawned.
+ ///
+ public override void OnNetworkSpawn()
+ {
+ // Both the server-host and client(s) register the custom named message.
+ NetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(MessageName, ReceiveMessage);
+
+ if (IsServer)
+ {
+ // Server broadcasts to all clients when a new client connects (just for example purposes)
+ NetworkManager.OnClientConnectedCallback += OnClientConnectedCallback;
+ }
+ else
+ {
+ // Clients send a unique Guid to the server
+ SendMessage(Guid.NewGuid());
+ }
+ }
+
+ private void OnClientConnectedCallback(ulong obj)
+ {
+ SendMessage(Guid.NewGuid());
+ }
+
+ public override void OnNetworkDespawn()
+ {
+ // De-register when the associated NetworkObject is despawned.
+ NetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler(MessageName);
+ // Whether server or not, unregister this.
+ NetworkManager.OnClientDisconnectCallback -= OnClientConnectedCallback;
+ }
+
+ ///
+ /// Invoked when a custom message of type
+ ///
+ private void ReceiveMessage(ulong senderId, FastBufferReader messagePayload)
+ {
+ var receivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid());
+ messagePayload.ReadValueSafe(out receivedMessageContent);
+ if (IsServer)
+ {
+ Debug.Log($"Sever received GUID ({receivedMessageContent.Value}) from client ({senderId})");
+ }
+ else
+ {
+ Debug.Log($"Client received GUID ({receivedMessageContent.Value}) from the server.");
+ }
+ }
+
+ ///
+ /// Invoke this with a Guid by a client or server-host to send a
+ /// custom named message.
+ ///
+ public void SendMessage(Guid inGameIdentifier)
+ {
+ var messageContent = new ForceNetworkSerializeByMemcpy(inGameIdentifier);
+ var writer = new FastBufferWriter(1100, Allocator.Temp);
+ var customMessagingManager = NetworkManager.CustomMessagingManager;
+ using (writer)
+ {
+ writer.WriteValueSafe(messageContent);
+ if (IsServer)
+ {
+ // This is a server-only method that will broadcast the named message.
+ // Caution: Invoking this method on a client will throw an exception!
+ customMessagingManager.SendNamedMessageToAll(MessageName, writer);
+ }
+ else
+ {
+ // This is a client or server method that sends a named message to one target destination
+ // (client to server or server to client)
+ customMessagingManager.SendNamedMessage(MessageName, NetworkManager.ServerClientId, writer);
+ }
+ }
+ }
+}
+```
diff --git a/versioned_docs/version-2.0.0/advanced-topics/message-system/deprecation-of-return-values.md b/versioned_docs/version-2.0.0/advanced-topics/message-system/deprecation-of-return-values.md
new file mode 100644
index 000000000..9063a912b
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/message-system/deprecation-of-return-values.md
@@ -0,0 +1,51 @@
+---
+id: deprecation-of-return-values
+title: Deprecation of return values
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+Netcode for GameObjects used to support RPC return values on convenience RPCs.
+
+Example:
+
+```csharp
+public IEnumerator MyRpcCoroutine()
+{
+ RpcResponse response = InvokeServerRpc(MyRpcWithReturnValue, Random.Range(0f, 100f), Random.Range(0f, 100f));
+
+ while (!response.IsDone)
+ {
+ yield return null;
+ }
+
+ Debug.LogFormat("The final result was {0}!", response.Value);
+}
+
+[ServerRPC]
+public float MyRpcWithReturnValue(float x, float y)
+{
+ return x * y;
+}
+
+```
+
+Netcode for GameObjects no longer supports this feature. To achieve the same functionality, use a combination of the ServerRpc and ClientRpc methods. The following code demonstrates this method:
+
+```csharp
+void MyRpcInvoker()
+{
+ MyRpcWithReturnValueRequestServerRpc(Random.Range(0f, 100f)), Random.Range(0f, 100f)));
+}
+
+[Rpc(SendTo.Server)]
+void MyRpcWithReturnValueRequestServerRpc(float x, float y)
+{
+ MyRpcWithReturnValueResponseClientRpc(x * y);
+}
+
+[Rpc(SendTo.ClientsAndHost)]
+void MyRpcWithReturnValueResponseClientRpc(float result)
+{
+ Debug.LogFormat("The final result was {0}!", result);
+}
+```
diff --git a/versioned_docs/version-2.0.0/advanced-topics/message-system/execution-table.md b/versioned_docs/version-2.0.0/advanced-topics/message-system/execution-table.md
new file mode 100644
index 000000000..cd5940465
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/message-system/execution-table.md
@@ -0,0 +1,101 @@
+---
+id: execution-table
+title: Execution table
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+:::warning
+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.
+:::
+
+The following table details the execution of `ServerRpc` and `ClientRpc` functions:
+
+| Function | Server | Client | Host (Server+Client) |
+|---|:---:|:---:|:---:|
+| ServerRpc Send | | | |
+| ServerRpc Execute | | | |
+| ClientRpc Send | | | |
+| ClientRpc Execute | | | |
+
+An RPC function typically doesn't execute its body immediately since the function call is a stand-in for a network transmission. Since the host is both a client and a server, local RPCs targeting the host-server or host-client are invoked immediately. As such, avoid nesting RPCs when running in host mode as a ServerRpc method that invokes a ClientRpc method that invokes the same ServerRpc method (and repeat...) can cause a stack overflow.
+
+Structure of a typical `ServerRpc`:
+
+```csharp
+[ServerRpc]
+void MyServerRpc(int somenumber, string somestring)
+{
+ // Network Send Block (framework-code)
+ // Network Return Block (framework-code)
+ // RPC Method Body (user-code)
+}
+```
+
+Pseudo-code sample of a `ServerRpc`:
+
+```csharp
+[ServerRpc]
+void MyServerRpc(int somenumber, string somestring)
+{
+ // --- begin: injected framework-code
+ if (NetworkSend())
+ {
+ // this block will be executed if:
+ // - called from user-code on client
+ // - called from user-code on host
+
+ var writer = NetworkCreateWriter();
+ writer.WriteInt32(1234567890); // RPC method signature hash
+ writer.WriteInt32(somenumber);
+ writer.WriteChars(somestring);
+ NetworkSendRpc(writer);
+ }
+
+ if (NetworkReturn())
+ {
+ // this block will be executed if:
+ // - called from user-code
+ // - called from framework-code on client
+
+ return;
+ }
+ // --- end: injected framework-code
+
+ print($"MyServerRpc: {somenumber}");
+}
+```
+
+
+
+
+
+
+
+
+
+
+
diff --git a/versioned_docs/version-2.0.0/advanced-topics/message-system/reliabilty.md b/versioned_docs/version-2.0.0/advanced-topics/message-system/reliabilty.md
new file mode 100644
index 000000000..cc4e94ad6
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/message-system/reliabilty.md
@@ -0,0 +1,41 @@
+---
+id: reliability
+title: Reliability
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+## Introduction
+RPCs **are reliable by default**. This means they're guaranteed to be received and executed on the remote side. However, sometimes developers might want to opt-out reliability, which is often the case for non-critical events such as particle effects, sounds effects etc.
+:::caution
+Packet reliability can be a two edged sword (pro and con):
+- **The Pro**: Under bad network conditions a reliable packet is guaranteed to be received by the target remote side.
+- **The Con**: Because the sender will continue trying to send a reliable packet if it does not get a "packet received" response, under bad network conditions too many reliable packets being sent can cause additional bandwidth overhead.
+:::
+
+### Reliable and Unreliable RPC Examples:
+Reliability configuration can be specified for `Rpc` methods at compile-time:
+
+```csharp
+
+[Rpc(SendTo.Server)]
+void MyReliableServerRpc() { /* ... */ }
+
+[Rpc(SendTo.Server, Delivery = RpcDelivery.Unreliable)]
+void MyUnreliableServerRpc() { /* ... */ }
+```
+
+Reliable RPCs will be received on the remote end in the same order they are sent, but this in-order guarantee only applies to RPCs on the same NetworkObject. Different `NetworkObjects` might have reliable RPCs called but executed in different order compared to each other. To put more simply, **in-order reliable RPC execution is guaranteed per NetworkObject basis only**. If you determine an RPC is being updated often (that is, several times per second), it _might_ be better suited as an unreliable RPC.
+:::caution
+When testing unreliable RPCs on a local network, the chance of an unreliable packet being dropped is reduced greatly (sometimes never). As such, you might want to use [`UnityTransport`'s Simulator Pipeline](https://docs-multiplayer.unity3d.com/transport/current/pipelines#simulator-pipeline) to simulate poor network conditions to better determine how dropped unreliable RPC messages impacts your project.
+:::
+
+:::tip
+Sometimes you might find out that you are sending parameters that are both critical and non-critical. Under this scenario you might benefit by splitting the RPC into two or more RPCs with the less critical parameters being sent unreliably (possibly at the same or higher frequency) while the more critical parameters are sent reliably (possibly at the same or lower frequency).
+:::
+
+### Additional RPC Facts
+- An RPC call made without an active connection won't be automatically added to the send queue and will be dropped/ignored.
+- Both reliable and unreliable RPC calls have to be made when there is an active network connection established between a client and the server. _The caveat to this rule is if you are running a host since a host is both a server and a client:_
+ - _A host can send RPC messages from the "host-server" to the "host-client" and vice versa._
+- Reliable RPC calls made during connection will be dropped if the sender disconnects before the RPC is sent.
+
diff --git a/versioned_docs/version-2.0.0/advanced-topics/message-system/rpc-compatibility.md b/versioned_docs/version-2.0.0/advanced-topics/message-system/rpc-compatibility.md
new file mode 100644
index 000000000..9d26293dd
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/message-system/rpc-compatibility.md
@@ -0,0 +1,98 @@
+---
+id: rpc-compatibility
+title: RPC migration and compatibility
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+This section provides information on compatibility and support for Unity Netcode for GameObjects (Netcode) features compared to previous Netcode versions. See the [Release Notes](../../../../releases/introduction) for more information.
+
+## Cross-Compatibility
+
+Learn more about standard RPC API's cross-compatibility only, not the framework as a whole. A method decorated with an RPC attribute will be statically registered with its assembly-scoped method signature hash.
+
+A typical assembly-scoped method signature sample:
+
+```
+Game.dll / System.Void Shooter::PingRpc(System.Int32)
+```
+
+where:
+
+- `Game.dll` is the Assembly
+- `/` is a Separator
+- `System.Void Shooter::PingRpc(System.Int32)` is the Method signature:
+
+ - `System.Void` is the Return type
+ - `Shooter` is the Enclosing type
+ - `::` is the Scope resolution operator
+ - `PingRpc` is the Method name
+ - `(System.Int32)` is the Parameter type (no param names)
+
+An RPC signature will be turned into a 32-bit integer using [xxHash](https://cyan4973.github.io/xxHash/) (XXH32) non-cryptographic hash algorithm.
+
+The RPC signature hash changes when any of the following variables change:
+* Assembly.
+* Enclosing type.
+* Method name.
+* Method parameter type.
+
+However, the RPC signature hash doesn't change when the names of the parameters for an existing RPC are the only variables that change.
+
+When the RPC signature changes, it directs to a different invocation code path that has different serialization code. This means that the RPC method with the new signature doesn't invoke previous versions of that RPC method (for example, an RPC method from an older build).
+
+| Compatibility | | Description |
+| -- | :--: | -- |
+| Cross-Build Compatibility | | As long as the RPC method signature is kept the same, it will be compatible between different builds. |
+| Cross-Version Compatibility | | As long as the RPC method signature is kept the same, it will be compatible between different versions. |
+| Cross-Project Compatibility | | The exact same RPC method signature can be defined in different projects. This is because the project name or project-specific token isn't part of RPC signature. Cross-project RPC methods aren't compatible with each other. |
+
+## Deprecation of return values
+
+Netcode supports RPC return values on convenience RPCs.
+
+Example:
+
+```csharp
+public IEnumerator MyRpcCoroutine()
+{
+ RpcResponse response = InvokeServerRpc(MyRpcWithReturnValue, Random.Range(0f, 100f), Random.Range(0f, 100f));
+
+ while (!response.IsDone)
+ {
+ yield return null;
+ }
+
+ Debug.LogFormat("The final result was {0}!", response.Value);
+}
+
+[ServerRPC]
+public float MyRpcWithReturnValue(float x, float y)
+{
+ return x * y;
+}
+
+```
+
+To achieve similar functionality, use the following:
+
+```csharp
+void MyRpcInvoker()
+{
+ MyRpcWithReturnValueRequestServerRpc(Random.Range(0f, 100f), Random.Range(0f, 100f));
+}
+
+[Rpc(SendTo.Server)]
+void MyRpcWithReturnValueRequestServerRpc(float x, float y)
+{
+ MyRpcWithReturnValueResponseClientRpc(x * y);
+}
+
+[Rpc(SendTo.ClientsAndHost)]
+void MyRpcWithReturnValueResponseClientRpc(float result)
+{
+ Debug.LogFormat("The final result was {0}!", result);
+}
+```
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+import Link from '@docusaurus/Link';
\ No newline at end of file
diff --git a/versioned_docs/version-2.0.0/advanced-topics/message-system/rpc-params.md b/versioned_docs/version-2.0.0/advanced-topics/message-system/rpc-params.md
new file mode 100644
index 000000000..2f8efe31f
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/message-system/rpc-params.md
@@ -0,0 +1,108 @@
+---
+id: rpc-params
+title: RPC params
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+You can configure the `Rpc`, `ServerRpc` and `ClientRpc` methods in the following ways:
+* Use the `[Rpc]`, `[ServerRpc]` and `[ClientRpc]` attributes at compile-time.
+* Use `ServerRpcParams` and `ClientRpcParams` at runtime.
+
+Developers can put, `RpcParams`, `ServerRpcParams`, or `ClientRpcParams` as the last parameter (optionally, as appropriate for the type of RPC). The `RpcParams`, `ServerRpcParams`, and `ClientRpcParams` types contain both send and receive properties that are populated relative to the context of usage.
+
+
+## Rpc Params
+
+See the following for `Rpc` params:
+
+```csharp
+// Both Rpc methods below are fine, `ServerRpcParams` is completely optional
+
+[Rpc(SendTo.Server)]
+void AbcdServerRpc(int somenumber) { /* ... */ }
+
+[Rpc(SendTo.Server)]
+void XyzwServerRpc(int somenumber, RpcParams rpcParams = default) { /* ... */ }
+```
+
+For those accustomed to the legacy `ServerRpc` and `ClientRpc` parameters, there are a few differences with `Rpc` params:
+
+- `RpcParams` defines implicit conversion operators for `BaseRpcTarget` and `LocalDeferMode`:
+ - `BaseRpcTarget`: Used to change the destination of an RPC at runtime.
+ - `LocalDeferMode`: Used to change how an RPC is handled locally.
+ - `Defer`: Invokes the RPC locally on the next frame.
+ - `SendImmediate` (default): Immediately invokes the RPC (at the current call stack) locally.
+
+- Changing destination of an RPC is done using the properties and methods of `RpcTarget` (each `NetworkBehaviour` contains a reference to the shared `RpcTarget` object, as does `NetworkManager`.) This allows conveniently selecting various common targets (Server, NotServer, Owner, NotOwner, etc), as well as custom client lists using `RpcTarget.Single()` (to send to one client ID), `RpcTarget.Group()` (to send to multiple client IDs), and`RpcTarget.Not()` (to send to everyone except for the specified client ID or list of client IDs)
+- `RpcParams` do not allow overriding the destination at runtime unless either the default target is `SendTo.SpecifiedInParams` or `AllowTargetOverride = true` is passed to the attribute.
+
+```csharp
+[Rpc(SendTo.Server)]
+void ServerRpc(RpcParams rpcParams = default) { /* ... */ }
+
+[Rpc(SendTo.SpecifiedInParams)]
+void RuntimeSpecifiedRpc(RpcParams rpcParams = default) { /* ... */ }
+
+[Rpc(SendTo.Server, AllowTargetOverride = true)]
+void OverridableServerRpc(RpcParams rpcParams = default) { /* ... */ }
+
+// Throws an exception: SendTo.Server cannot be overriden for ServerRpc
+ServerRpc(RpcTarget.NotServer);
+ServerRpc(RpcTarget.Single(someClientId, RpcTargetUse.Temp));
+
+// Works
+RuntimeSpecifiedRpc(RpcTarget.NotServer);
+RuntimeSpecifiedRpc(RpcTarget.Single(someClientId, RpcTargetUse.Temp));
+
+// Works
+OverridableServerRpc(RpcTarget.NotServer);
+OverridableServerRpc(RpcTarget.Single(someClientId, RpcTargetUse.Temp));
+```
+
+:::note
+For various reasons, `BaseRpcTarget` is not intended to be extended by user code. If you have a custom use case that requires a special target, we recommend creating a wrapper method that returns `RpcTarget.Single()` or `RpcTarget.Group()`, which should be able to satisfy most if not all of your needs.
+:::
+
+## ServerRpc Params
+
+:::warning
+ClientRpc and ServerRpc are legacy features of Netcode for GameObjects, and have been supplanted by the universal Rpc attribute. This documentation is provided for legacy use, but we recommend all current projects use [Rpc](rpc.md) instead.
+:::
+
+See the following for `ServerRpc` params:
+
+``` csharp
+// Both ServerRpc methods below are fine, `ServerRpcParams` is completely optional
+
+[ServerRpc]
+void AbcdServerRpc(int somenumber) { /* ... */ }
+
+[ServerRpc]
+void XyzwServerRpc(int somenumber, ServerRpcParams serverRpcParams = default) { /* ... */ }
+```
+
+[ServerRpcParams Documentation](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.ServerRpcParams.html)
+
+## ClientRpc Params
+
+:::warning
+ClientRpc and ServerRpc are legacy features of Netcode for GameObjects, and have been supplanted by the universal Rpc attribute. This documentation is provided for legacy use, but we recommend all current projects use [Rpc](rpc.md) instead.
+:::
+
+See the following for `ClientRpc` params:
+
+```csharp
+// Both ClientRpc methods below are fine, `ClientRpcParams` is completely optional
+
+[ClientRpc]
+void AbcdClientRpc(int framekey) { /* ... */ }
+
+[ClientRpc]
+void XyzwClientRpc(int framekey, ClientRpcParams clientRpcParams = default) { /* ... */ }
+```
+
+[ClientRpcParams Documentation](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.ClientRpcParams.html)
+
+:::tip
+`ClientRpcSendParams`'s `TargetClientIds` property is a `ulong[]` which means everytime you try to specify a subset of target clients or even a single client target, you will have to allocate a `new ulong[]`. This pattern can quickly lead into lots of heap allocations and pressure GC which would cause GC spikes at runtime. We suggest developers cache their `ulong[]` variables or use an array pool to cycle `ulong[]` instances so that it would cause less heap allocations.
+:::
diff --git a/versioned_docs/version-2.0.0/advanced-topics/message-system/rpc.md b/versioned_docs/version-2.0.0/advanced-topics/message-system/rpc.md
new file mode 100644
index 000000000..9f60c73cd
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/message-system/rpc.md
@@ -0,0 +1,235 @@
+---
+id: rpc
+title: RPC
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+Any process can communicate with any other process by sending a remote procedure call (RPC). As of Netcode for GameObjects version 1.8.0, the `Rpc` attribute encompasses server to client RPCs, client to server RPCs, and client to client RPCs. The `Rpc` attribute is session-mode agnostic and can be used in both [client-server](../../terms-concepts/client-server.md) and [distributed authority](../../terms-concepts/distributed-authority.md) contexts.
+
+
+
+
+
+## Declaring an RPC
+
+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 a server, declare it like this:
+
+```csharp
+[Rpc(SendTo.Server)]
+public void PingRpc(int pingCount) { /* ... */ }
+
+[Rpc(SendTo.NotServer)]
+void PongRpc(int pingCount, string message) { /* ... */ }
+```
+
+## Invoking an RPC
+
+Invoke an RPC at [compile time](#compile-time-targets) or [runtime](#runtime-targets) by invoking the function directly with parameters:
+
+```csharp
+[Rpc(SendTo.Server)]
+public void PingRpc(int pingCount)
+{
+ // Server -> Clients because PongRpc sends to NotServer
+ // Note: This will send to all clients.
+ // Sending to the specific client that requested the pong will be discussed in the next section.
+ PongRpc(pingCount, "PONG!");
+}
+
+[Rpc(SendTo.NotServer)]
+void PongRpc(int pingCount, string message)
+{
+ Debug.Log($"Received pong from server for ping {pingCount} and message {message}");
+}
+
+void Update()
+{
+ if (IsClient && Input.GetKeyDown(KeyCode.P))
+ {
+ // Client -> Server because PingRpc sends to Server
+ PingRpc();
+ }
+}
+```
+
+You must mark client RPC methods with the `[Rpc]` attribute and use the `Rpc` method suffix. Failing to do so produces an error message.
+
+```csharp
+// Error: Invalid, missing 'Rpc' suffix in the method name
+[Rpc(SendTo.Everyone)]
+void Pong(int somenumber, string sometext) { /* ... */ }
+```
+
+The `[Rpc]` attribute and matching `...Rpc` suffix in the method name ensure context clarity in scripts that invoke them and are used by Netcode during the ILPostProcessor pass. The ILPostProcessor pass replaces all call-site locations where the RPC method is invoked with additional code, specifically generated for the RPC, to ensure that the RPC message is generated and sent to the appropriate targets rather than just locally invoking the method.
+
+```csharp
+Pong(somenumber, sometext); // Is this a local function or a remote function?
+
+PongRpc(somenumber, sometext); // This is clearly an remote function
+```
+
+## RPC targets
+
+### Compile-time targets
+
+There are several default compile-time targets you can choose from. Some of these are only available in [client-server contexts](../../terms-concepts/client-server.md).
+
+While client-to-client RPCs are supported, it's important to note that there are no direct connections between clients. When sending a client-to-client RPC, the RPC is sent to the server (or distributed authority service) that acts as a proxy and forwards the same RPC message to all destination clients. If the targeted destination clients includes the local client, the local client will still execute the RPC immediately (or on the next frame locally, if deferred).
+
+| Target | Available contexts| Description |
+| ---------------------------- | :----------------------------------------------------------- | --- |
+| `SendTo.Server` |Client-server only| Send to the server, regardless of ownership. Executes locally if invoked on the server. |
+| `SendTo.NotServer` |Client-server only| Send to everyone _but_ the server, filtered to the current observer list. Won't send to a server running in host mode - it's still treated as a server. If you want to send to servers when they are host, but not when they are dedicated server, use `SendTo.ClientsAndHost`.
Executes locally if invoked on a client. Doesn't execute locally if invoked on a server running in host mode. |
+|`SendTo.Authority`|Client-server and distributed authority|Send to the NetworkObject's current authority. Executes locally if the local process has authority.|
+|`SendTo.NotAuthority`|Client-server and distributed authority|Send to everyone but the current authority, filtered to the current observer list. Executes locally if the local process is not the owner.|
+| `SendTo.Owner` |Client-server and distributed authority| Send to the NetworkObject's current owner. Executes locally if the local process is the owner. |
+| `SendTo.NotOwner` |Client-server and distributed authority| Send to everyone but the current owner, filtered to the current observer list. Executes locally if the local process is not the owner.
In host mode, the host receives this message twice: once on the host client, once on the host server. |
+| `SendTo.Me` |Client-server and distributed authority| Execute this RPC locally.
Normally this is no different from a standard function call.
Using the `DeferLocal` parameter of the attribute or the `LocalDeferMode` override in `RpcSendParams`, this can allow an RPC to be processed on localhost with a one-frame delay as if it were sent over the network. |
+| `SendTo.NotMe` |Client-server and distributed authority| Send this RPC to everyone but the local machine, filtered to the current observer list. |
+| `SendTo.Everyone` |Client-server and distributed authority| Send this RPC to everyone, filtered to the current observer list. Executes locally. |
+| `SendTo.ClientsAndHost` |Client-server and distributed authority| Send this RPC to all clients, including the host, if a host exists. If the server is running in host mode, this is the same as `SendTo.Everyone`. If the server is running in dedicated server mode, this is the same as `SendTo.NotServer`. |
+| `SendTo.SpecifiedInParams` |Client-server and distributed authority| This RPC cannot be sent without passing in a target in `RpcSendParams`. |
+
+### Runtime targets
+
+By default, most targets are hard-coded at compile time: owner always sends to owner, server always sends to server, and so on. There are two cases where you can to specify a different set of targets at runtime:
+
+- If the target is `SendTo.SpecifiedInParams`, you must pass a target in at runtime to send the RPC.
+- If the `Rpc` parameter is declared with `AllowTargetOverride = true`, then you can optionally pass a target in at runtime to send the RPC to a different target than the compile-time default.
+
+To send to a different target, you must define an additional parameter of type `RpcParameters` as the *last* parameter in your RPC method, and then pass your runtime targets in with that parameter. This gets special handling in the ILPostProcessor pass: the last parameter isn't serialized and sent across the network. Instead, it's read on the sending side to check for overrides to its default sending behavior using the `RpcParameters.Send` field (while `RpcParameters.Receive` will be ignored), and on the receiving side, is be populated with `RpcParameters.Receive` to provide information about the receiving context (while `RpcParameters.Send` is left uninitialized).
+
+`RpcParameters` can be implicitly constructed from runtime send targets, making it simple to pass these targets in as parameters.
+
+#### Built-in targets
+
+`NetworkManager` and `NetworkBehaviour` both provide reference to a field called `RpcTarget`, which provides references to the various override targets you can pass in. The list mirrors the list of targets provided in the `SendTo` enum, and has the same behavior as described in the table above.
+
+The `RpcTarget` object is shared by all `NetworkBehaviours` attached to a given `NetworkManager`, so you can get access to this via any `NetworkBehaviour` or via the `NetworkManager` object itself.
+
+```csharp
+public class SomeNetworkBehaviour : NetworkBehaviour
+{
+ [Rpc(SendTo.Server, AllowTargetOverride = true)]
+ public void SomeRpc(int serializedParameter1, float serializedParameter2, RpcParams rpcParams)
+ {
+
+ }
+
+ // Sends SomeRpc() to the owner instead of the server
+ public void SendSomeRpcToOwner(int param1, float param2)
+ {
+ SomeRpc(param1, param2, RpcTarget.Owner);
+ }
+}
+
+public class SomeOtherClass
+{
+ public SomeNetworkBehaviour Behaviour;
+
+ public SendSomeRpcToOwnerOnBehaviour(int param1, float param2)
+ {
+ // Since this method is not within a NetworkBehaviour, RpcTarget.Owner must be accessed through
+ // the Behaviour object via Behaviour.RpcTarget.Owner.
+ Behaviour.SomeRpc(param1, param2, Behaviour.RpcTarget.Owner);
+ }
+}
+```
+
+#### Custom targets
+
+If you need to send to a specific client ID or list of client IDs that are not covered by any of the existing named targets, you can use the following methods:
+
+```csharp
+// Send to a specific single client ID.
+public BaseRpcTarget Single(ulong clientId, RpcTargetUse use) { /* ... */ }
+
+// Send to everyone EXCEPT a specific single client ID.
+public BaseRpcTarget Not(ulong excludedClientId, RpcTargetUse use) { /* ... */ }
+
+// Sends to a group of client IDs.
+public BaseRpcTarget Group(NativeArray clientIds, RpcTargetUse use) { /* ... */ }
+public BaseRpcTarget Group(NativeList clientIds, RpcTargetUse use) { /* ... */ }
+public BaseRpcTarget Group(ulong[] clientIds, RpcTargetUse use) { /* ... */ }
+public BaseRpcTarget Group(T clientIds, RpcTargetUse use) where T : IEnumerable
+{ /* ... */ }
+
+// Sends to everyone EXCEPT a group of client IDs.
+public BaseRpcTarget Not(NativeArray excludedClientIds, RpcTargetUse use) { /* ... */ }
+public BaseRpcTarget Not(NativeList excludedClientIds, RpcTargetUse use) { /* ... */ }
+public BaseRpcTarget Not(ulong[] excludedClientIds, RpcTargetUse use) { /* ... */ }
+public BaseRpcTarget Not(T excludedClientIds, RpcTargetUse use) where T : IEnumerable
+{ /* ... */ }
+```
+
+Each of these includes an `RpcTargetUse` parameter. This parameter controls the use of a particular performance optimization in situations where it can be used. Because `BaseRpcTarget` is a managed type, allocating a new one is expensive, as it puts pressure on the garbage collector.
+
+If you're only creating the `BaseRpcTarget` instance for one-time use to pass it to an RPC and then discard it, `RpcTargetUse.Temp` can be used to avoid these allocations. It does this by making use of a persistent cached `BaseRpcTarget` object that it populates with new data. The downside of this is that, the next time you call any of these methods, that data may be overwritten - so if you are creating a target that you plan to use for a longer duration of time, `RpcTargetUse.Persistent` will tell the code to allocate a new one for you that it will never overwrite.
+
+In general, in cases where you are using `RpcTargetUse.Temp` with the group functions, it's recommended to also use the `NativeArray` or `NativeList` versions. `NativeArray` and `NativeList` can be allocated with `Allocator.Temp` very efficiently with no pressure on the garbage collector; on the other hand, the `ulong[]` and `IEnumerable` will add garbage collection pressure (even if the `IEnumerable` version is invoked using a `struct` type, it will still cause a boxing allocation), so it's recommended to avoid using those frequently.
+
+#### Completing the ping example
+
+As noted in the comments above, the earlier [ping/pong example](#invoking-an-rpc) sends its pong to all connected clients instead of just the one that requested it. To complete this example, we can use `RpcParameters` along with `SendTo.SpecifiedInParams` to make the example work as you might expect a ping to work:
+
+```csharp
+[Rpc(SendTo.Server)]
+public void PingRpc(int pingCount, RpcParams rpcParams)
+{
+ // Here we use RpcParams for incoming purposes - fetching the sender ID the RPC came from
+ // That sender ID can be passed in to the PongRpc to send this back to that client and ONLY that client
+
+ PongRpc(pingCount, "PONG!", RpcTarget.Single(rpcParams.Receive.SenderClientId, RpcTargetUse.Temp));
+}
+
+[Rpc(SendTo.SpecifiedInParams)]
+void PongRpc(int pingCount, string message, RpcParams rpcParams)
+{
+ // We do not use rpcParams within this method's body, but that is okay!
+ // The params passed in are used by the generated code to ensure that this sends only
+ // to the one client it should go to
+
+ Debug.Log($"Received pong from server for ping {pingCount} and message {message}");
+}
+
+void Update()
+{
+ if (IsClient && Input.GetKeyDown(KeyCode.P))
+ {
+ PingRpc();
+ }
+}
+```
+
+## Other RPC parameters
+
+There are a few other parameters that can be passed to either the `Rpc` attribute at compile-time or the `RpcSendParams` object at runtime.
+
+### `RpcAttribute` parameters
+
+| Parameter | Description |
+| ----------------------- | ------------------------------------------------------------ |
+| `Delivery` | Controls whether the delivery is reliable (default) or unreliable.
Options: `RpcDelivery.Reliable` or `RpcDelivery.Unreliable` Default: `RpcDelivery.Reliable` |
+| `RequireOwnership` | If `true`, this RPC throws an exception if invoked by a player that does not own the object. This is in effect for server-to-client, client-to-server, and client-to-client RPCs - i.e., a server-to-client RPC will still fail if the server is not the object's owner.
Default: `false` |
+| `DeferLocal` | If `true`, RPCs that execute locally will be deferred until the start of the next frame, as if they had been sent over the network. (They will not actually be sent over the network, but will be treated as if they were.) This is useful for mutually recursive RPCs on hosts, where sending back and forth between the server and the "host client" will cause a stack overflow if each RPC is executed instantly; simulating the flow of RPCs between remote client and server enables this flow to work the same in both contexts.
Default: `false` |
+| `AllowTargetOverride` | By default, any `SendTo` value other than `SendTo.SpecifiedInParams` is a hard-coded value that cannot be changed. Setting this to `true` allows you to provide an alternate target at runtime, while using the `SendTo` value as a fallback if no runtime value is provided. |
+
+### `RpcSendParams` parameters
+
+| Parameter | Description |
+| ------------------ | ------------------------------------------------------------ |
+| `Target` | Runtime override destination for the RPC. (See above for more details.) Populating this value will throw an exception unless either the `SendTo` value for the RPC is `SendTo.SpecifiedInParams`, or `AllowTargetOverride` is `true`.
Default: `null` |
+| `LocalDeferMode` | Overrides the `DeferLocal` value. `DeferLocalMode.Defer` causes this particular invocation of this RPC to be deferred until the next frame even if `DeferLocal` is `false`, while `DeferLocalMode.SendImmediate` causes the RPC to be executed immediately on the local machine even if `DeferLocal` is `true`. `DeferLocalMode.Default` does whatever the `DeferLocal` value in the attribute is configured to do.
Options: `DeferLocalMode.Default`, `DeferLocalMode.Defer`, `DeferLocalMode.SendImmediate` Default: `DeferLocalMode.Default` |
+
+## Additional resources
+
+* [RPC parameters](rpc-params.md)
+* [Boss Room RPC Examples](../../learn/bossroom/bossroom-actions.md)
diff --git a/versioned_docs/version-2.0.0/advanced-topics/message-system/serverrpc.md b/versioned_docs/version-2.0.0/advanced-topics/message-system/serverrpc.md
new file mode 100644
index 000000000..d3a70b40a
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/message-system/serverrpc.md
@@ -0,0 +1,170 @@
+---
+id: serverrpc
+title: ServerRpc
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+:::warning
+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.
+:::
+
+## Introduction
+A `ServerRpc` provides you with the ability to send information from a client to a server just like you would invoke a method from within a class. A `ServerRpc` is a remote procedure call (RPC) that can be only invoked by a client and will always be received and executed on the server/host.
+
+## Declaring a ServerRpc
+You can declare a `ServerRpc` by:
+1. Creating a method that ends with the `ServerRpc` suffix within a `NetworkBehaviour` derived class.
+2. Adding the `[ServerRpc]` attribute above the method
+
+### Example of declaring a ServerRpc:
+```csharp
+public class SomeNetworkBehaviour : NetworkBehaviour
+{
+ [ServerRpc]
+ public void PingServerRpc(int pingCount)
+ {
+
+ }
+}
+```
+The above example uses the default [ServerRpc] attribute settings which only allows a client owner (client that owns NetworkObject associated with the `NetworkBehaviour` containing the `ServerRpc` method) invocation rights. Any client that isn't the owner won't be allowed to invoke the `ServerRpc`.
+
+## ServerRpc Ownership And ServerRpcParams
+There are times where you might want any client to have `ServerRpc` invocation rights. You can easily accomplish this by setting the `ServerRpc` attribute's `RequireOwnership` parameter to false like in the example below:
+```csharp
+[ServerRpc(RequireOwnership = false)]
+public void MyGlobalServerRpc(ServerRpcParams serverRpcParams = default)
+{
+ var clientId = serverRpcParams.Receive.SenderClientId;
+ if (NetworkManager.ConnectedClients.ContainsKey(clientId))
+ {
+ var client = NetworkManager.ConnectedClients[clientId];
+ // Do things for this client
+ }
+}
+
+public override void OnNetworkSpawn()
+{
+ MyGlobalServerRpc(); // serverRpcParams will be filled in automatically
+}
+```
+In the above example, you will also notice that `MyGlobalServerRpc` takes a single parameter of type [`ServerRpcParams`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.ServerRpcParams.html). This parameter type is optional, but it can be useful to identify **which client** was requesting the server invoke the RPC. The `ServerRpcParams.Receive.SenderClientId` property is automatically set upon the server receiving the `ServerRpc` request and used to get the server-side `NetworkClient` instance of the client (sender).
+:::important Best Practice
+Using the `ServerRpcParams.Receive.SenderClientId` property is considered the best practice to identify which client was invoking the `ServerRpc`. It isn't recommended to send the client identifier via an additional `ulong` parameter added to the `ServerRpc`:
+```csharp
+[ServerRpc(RequireOwnership = false)]
+public void MyGlobalServerRpc(ulong clientId) // This is considered a bad practice (Not Recommended)
+{
+ if (NetworkManager.ConnectedClients.ContainsKey(clientId))
+ {
+ var client = NetworkManager.ConnectedClients[clientId];
+ // Do things for this client
+ }
+}
+```
+The primary reason, especially when `RequireOwnership == false`, is that it can introduce potential security issues. The secondary reason is that this value is already automatically provided to you via `ServerRpcParams` without the additional `ulong` parameter bandwidth overhead you would incur by sending the client identifier as a `ServerRpc` parameter.
+:::
+
+Now, taking the best practices example into consideration, you might want to have other valid parameters added to your `ServerRpc`. When adding additional parameters other than the `ServerRpcParams` parameter, you **must** declare `ServerRpcParams` as the **last** parameter of the `ServerRpc`:
+```csharp
+[ServerRpc(RequireOwnership = false)]
+public void PlayerShootGunServerRpc(Vector3 lookWorldPosition, ServerRpcParams serverRpcParams = default)
+{
+ var clientId = serverRpcParams.Receive.SenderClientId;
+ if (NetworkManager.ConnectedClients.ContainsKey(clientId))
+ {
+ var client = NetworkManager.ConnectedClients[clientId];
+ var castRay = new Ray(client.PlayerObject.transform.position, lookWorldPosition);
+ RaycastHit rayCastHit;
+ if (Physics.Raycast(castRay, out rayCastHit, 100.0f))
+ {
+ // Handle shooting something
+ }
+ }
+}
+```
+Looking at the above example, we can see the client invoking the `PlayerShootGunServerRpc` method passes in a world position based on perhaps a screen space crosshair position to world space position, the `ServerRpcParams`, and the `ServerRpc` doesn't require ownership.
+
+:::tip Alternate Owner Example
+Of course, if your project's design was such that a weapon changes ownership when it's picked up by a player, then you would only allow owners to invoke the method and would only need the one `Vector3` parameter like in the example below:
+```csharp
+[ServerRpc]
+public void PlayerOwnerShootGunServerRpc(Vector3 lookWorldPosition)
+{
+ if (NetworkManager.ConnectedClients.ContainsKey(OwnerClientId))
+ {
+ var client = NetworkManager.ConnectedClients[OwnerClientId];
+ var castRay = new Ray(client.PlayerObject.transform.position, lookWorldPosition);
+ RaycastHit rayCastHit;
+ if (Physics.Raycast(castRay, out rayCastHit, 100.0f))
+ {
+ // Handle shooting something
+ }
+ }
+}
+```
+:::
+
+## Invoking a ServerRpc
+From the example below that uses the `PlayerOwnerShootGunServerRpc` method, you can see that you would invoke it just like any other method:
+
+```csharp
+private void Update()
+{
+ if (!IsSpawned || !IsOwner)
+ {
+ return;
+ }
+
+ if (Input.GetKeyDown(KeyCode.Space))
+ {
+ var point = new Vector3();
+ var currentEvent = Event.current;
+ var mousePos = new Vector2();
+
+ // Get the mouse position from Event.
+ // Note that the y position from Event is inverted.
+ mousePos.x = currentEvent.mousePosition.x;
+ mousePos.y = Camera.current.pixelHeight - currentEvent.mousePosition.y;
+
+ point = Camera.current.ScreenToWorldPoint(new Vector3(mousePos.x,
+ mousePos.y, Camera.current.nearClipPlane));
+
+ PlayerOwnerShootGunServerRpc(point);
+ }
+}
+```
+
+### ServerRpc Timing
+The following are a few timing diagrams to help provide additional visual context when invoking a `ServerRpc`.
+
+
+
+
+
+
+
+:::warning
+When running as a host, RPCs are invoked 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 (that is, infinite recursion).
+:::
+
+## See Also
+
+* [ClientRpc](clientrpc.md)
+* [RPC Params](rpc-params.md)
+* See [examples](../../learn/bossroom/bossroom-actions) of how these were used in Boss Room.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/messaging-system.md b/versioned_docs/version-2.0.0/advanced-topics/messaging-system.md
new file mode 100644
index 000000000..4b3d6b99c
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/messaging-system.md
@@ -0,0 +1,70 @@
+---
+id: messaging-system
+title: Sending events with RPCs
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+Netcode for GameObjects has two parts to its messaging system: [remote procedure calls (RPCs)](message-system/rpc.md) and [custom messages](message-system/custom-messages.md). Both types have sub-types that change their behavior, functionality, and performance. RPCs as implemented in Netcode for GameObjects are session-mode agnostic, and work in both [client-server](../terms-concepts/client-server.md) and [distributed authority](../terms-concepts/distributed-authority.md) contexts.
+
+This page provides an introduction to RPCs. For more details, refer to the pages listed in the [RPCs in Netcode for GameObjects section](#rpcs-in-netcode-for-gameobjects)
+
+## Remote procedure calls (RPCs)
+
+RPCs are a standard software industry concept. They're a way to call methods on objects that aren't in the same executable.
+
+
+
+When calling an RPC from a client, the SDK takes note of the object, component, method, and any parameters for that RPC and sends that information over the network. The server or distributed authority service receives that information, finds the specified object, finds the specified method, and calls it on the specified object with the received parameters.
+
+Netcode for GameObjects includes multiple RPC variations that you can use to execute logic with various remote targets.
+
+
+
+### RPCs in Netcode for GameObjects
+
+Refer to the following pages for more information about how RPCs are implemented in Netcode for GameObjects.
+
+- [Remote procedure calls (RPCs)](message-system/rpc.md)
+- [Reliability](message-system/reliabilty.md)
+- [RPC parameters](message-system/rpc-params.md)
+ - [Serialization types and RPCs](message-system/../serialization/serialization-intro.md)
+
+There's also some additional design advice on RPCs and some usage examples on the following pages:
+
+- [RPC vs NetworkVariable](../learn/rpcvnetvar.md)
+- [RPC vs NetworkVariables Examples](../learn/rpcnetvarexamples.md)
+
+:::note Migration and compatibility
+Refer to [RPC migration and compatibility](message-system/rpc-compatibility.md) for more information on updates, cross-compatibility, and deprecated methods for Unity RPC.
+:::
+
+## RPC method calls
+
+A typical SDK user (Unity developer) can declare multiple RPCs under a `NetworkBehaviour` and inbound/outbound RPC calls will be replicated as a part of its replication in a network frame.
+
+A method turned into an RPC is no longer a regular method; it will have its own implications on direct calls and in the network pipeline.
+
+### RPC usage checklist
+
+To use RPCs, make sure:
+
+- `[Rpc]` attributes are on your method
+- Your method name ends with `Rpc` (for example, `DoSomethingRpc()`)
+- Your method is declared in a class that inherits from `NetworkBehaviour`
+ - Your GameObject has a NetworkObject component attached
+
+## Serialization types and RPCs
+
+Instances of serializable types are passed into an RPC as parameters and are serialized and replicated to the remote side.
+
+Refer to the [serialization page](serialization/serialization-intro.md) for more information.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/network-update-loop-system/index.md b/versioned_docs/version-2.0.0/advanced-topics/network-update-loop-system/index.md
new file mode 100644
index 000000000..32af3c0e7
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/network-update-loop-system/index.md
@@ -0,0 +1,53 @@
+---
+id: about-network-update-loop
+title: About NetworkUpdateLoop
+---
+
+Often there is a need to update netcode systems like RPC queue, transport IO, and others outside the standard `MonoBehaviour` event cycle.
+
+The Network Update Loop infrastructure utilizes Unity's low-level Player Loop API allowing for registering `INetworkUpdateSystems` with `NetworkUpdate()` methods to be executed at specific `NetworkUpdateStages` which may be either before or after `MonoBehaviour`-driven game logic execution.
+
+Typically you will interact with `NetworkUpdateLoop` for registration and `INetworkUpdateSystem` for implementation. Systems such as network tick and future features (such as network variable snapshotting) will rely on this pipeline.
+
+## Registration
+
+`NetworkUpdateLoop` exposes four methods for registration:
+
+| Method | Registers |
+| -- | -- |
+| `void RegisterNetworkUpdate(INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage)` | Registers an `INetworkUpdateSystem` to be executed on the specified `NetworkUpdateStage` |
+| `void RegisterAllNetworkUpdates(INetworkUpdateSystem updateSystem)` | Registers an `INetworkUpdateSystem` to be executed on all `NetworkUpdateStage`s |
+| `void UnregisterNetworkUpdate(INetworkUpdateSystem updateSystem, NetworkUpdateStage updateStage)` | Unregisters an `INetworkUpdateSystem` from the specified `NetworkUpdateStage` |
+| `void UnregisterAllNetworkUpdates(INetworkUpdateSystem updateSystem)` | Unregisters an `INetworkUpdateSystem` from all `NetworkUpdateStage`s |
+
+## Update Stages
+
+After injection, the player loops follows these stages. The player loop executes the `Initialization` stage and that invokes `NetworkUpdateLoop`'s `RunNetworkInitialization` method which iterates over registered `INetworkUpdateSystems` in `m_Initialization_Array` and calls `INetworkUpdateSystem.NetworkUpdate(UpdateStage)` on them.
+
+In all `NetworkUpdateStages`, it iterates over an array and calls the `NetworkUpdate` method over `INetworkUpdateSystem` interface, and the pattern is repeated.
+
+ B --> C --> D --> E --> F --> G
+`}/>
+
+| Stage | Method |
+| -- | -- |
+| `Initialization` | `RunNetworkInitialization` |
+| `EarlyUpdate` | `RunNetworkEarlyUpdate` `ScriptRunDelayedStartupFrame` Other systems |
+| `FixedUpdate` | `RunNetworkFixedUpdate` `ScriptRunBehaviourFixedUpdate` Other systems |
+| `PreUpdate` | `RunNetworkPreUpdate` `PhysicsUpdate` `Physics2DUpdate` Other systems |
+| `Update` | `RunNetworkUpdate` `ScriptRunBehaviourUpdate` Other systems |
+| `PreLateUpdate` | `RunNetworkPreLateUpdate` `ScriptRunBehaviourLateUpdate` |
+| `PostLateUpdate` | `PlayerSendFrameComplete` `RunNetworkPostLateUpdate` Other systems |
+
+## References
+
+See [Network Update Loop Reference](network-update-loop-reference.md) for process flow diagrams and code.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/network-update-loop-system/network-update-loop-reference.md b/versioned_docs/version-2.0.0/advanced-topics/network-update-loop-system/network-update-loop-reference.md
new file mode 100644
index 000000000..488fcda58
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/network-update-loop-system/network-update-loop-reference.md
@@ -0,0 +1,22 @@
+---
+id: network-update-loop-reference
+title: NetworkUpdateLoop reference
+---
+
+The following diagrams provide insight into the Network Update Loop process and APIs.
+
+## Injecting NetworkUpdateLoop Systems Into PlayerLoop
+
+
+
+![Injecting NetworkUpdateLoop Systems Into PlayerLoop](/img/injecting-networkupdatesloop.svg)
+
+
diff --git a/versioned_docs/version-2.0.0/advanced-topics/networkobject-parenting.md b/versioned_docs/version-2.0.0/advanced-topics/networkobject-parenting.md
new file mode 100644
index 000000000..66bae036d
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/networkobject-parenting.md
@@ -0,0 +1,228 @@
+---
+id: networkobject-parenting
+title: NetworkObject parenting
+description: A NetworkObject parenting solution within Netcode for GameObjects (Netcode) to help developers with synchronizing transform parent-child relationships of NetworkObject components.
+---
+
+### Overview
+
+If you aren't completely familiar with transform parenting in Unity, then it's highly recommended to [review over the existing Unity documentation](https://docs.unity3d.com/Manual/class-Transform.html) before reading further to properly synchronize all connected clients with any change in a GameObject component's transform parented status, Netcode for GameObjects requires that the parent and child GameObject components have NetworkObject components attached to them.
+
+### Parenting rules
+
+- Setting the parent of a child's `Transform` directly (that is, `transform.parent = childTransform;`) always uses the default `WorldPositionStays` value of `true`.
+ - It's recommended to always use the `NetworkObject.TrySetParent` method when parenting if you plan on changing the `WorldPositionStays` default value.
+ - Likewise, it's also recommended to use the `NetworkObject.TryRemoveParent` method to remove a parent from a child.
+- When a server parents a spawned NetworkObject component under another spawned NetworkObject component during a Netcode game session this parent child relationship replicates across the network to all connected and future late joining clients.
+- If, while editing a scene, you place an in-scene placed NetworkObject component under a GameObject component that doesn't have a NetworkObject component attached to it, Netcode for GameObjects preserves that parenting relationship.
+ - During runtime, this parent-child hierarchy remains true unless the user code removes the GameObject parent from the child NetworkObject component.
+ - **Note**: Once removed, Netcode for GameObjects won't allow you to re-parent the NetworkObject component back under the same or another GameObject component that with no NetworkObject component attached to it.
+- You can perform the same parenting actions with in-scene placed NetworkObjects as you can with dynamically spawned NetworkObject components.
+ - Unlike network prefabs that don't allow in-Editor nested NetworkObject component children, in-scene placed NetworkObjects can have multiple generations of in-editor nested NetworkObject component children.
+ - You can parent dynamically spawned NetworkObject components under in-scene placed NetworkObject components and vice versa.
+- To adjust a child's transform values when parenting or when removing a parent:
+ - Override the `NetworkBehaviour.OnNetworkObjectParentChanged` virtual method within a NetworkBehaviour component attached to the child NetworkObject component.
+ - When `OnNetworkObjectParentChanged` is invoked, on the server side, adjust the child's transform values within the overridden method.
+ - Netcode for GameObjects will then synchronize all clients with the child's parenting and transform changes.
+
+:::tip
+When a NetworkObject is parented, Netcode for GameObjects synchronizes both the parenting information along with the child's transform values. Netcode for GameObjects uses the `WorldPositionStays` setting to decide whether to synchronize the local or world space transform values of the child NetworkObject component. This means that a NetworkObject component doesn't require you to include a NetworkTransform component if it never moves around, rotates, or changes its scale when it isn't parented. This can be beneficial for world items a player might pickup (parent the item under the player) and the item in question needs to adjustment relative to the player when it's parented or the parent is removed (dropped). This helps to reduce the item's over-all bandwidth and processing resources consumption.
+:::
+
+### OnNetworkObjectParentChanged
+
+[`NetworkBehaviour.OnNetworkObjectParentChanged`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html#Unity_Netcode_NetworkBehaviour_OnNetworkObjectParentChanged_Unity_Netcode_NetworkObject_) is a virtual method you can override to be notified when a NetworkObject component's parent has changed. The [`MonoBehaviour.OnTransformParentChanged()`](https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnTransformParentChanged.html) method is used by NetworkObject component to catch `transform.parent` changes and notify its associated NetworkBehaviour components.
+
+```csharp
+///
+/// Gets called when the parent NetworkObject of this NetworkBehaviour's NetworkObject has changed
+///
+virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObject) { }
+```
+
+:::caution Multi-generation children and scale
+If you are dealing with more than one generation of nested children where each parent and child have scale values other than `Vector3.one`, then mixing the `WorldPositionStays` value when parenting and removing a parent will impact how the final scale is calculated! If you want to keep the same values before parenting when removing a parent from a child, then you need to use the same `WorldPositionStays` value used when the child was parented.
+:::
+
+### Only a server (or a host) can parent NetworkObjects
+
+Similar to [Ownership](../basics/networkobject#ownership), only the server (or host) can control NetworkObject component parenting.
+
+:::tip
+If you run into a situation where your client must trigger parenting a NetworkObject component, one solution is for the client to send an RPC to the server. Upon receiving the RPC message, the server then handles parenting the NetworkObject component.
+:::
+
+### Only parent under a NetworkObject Or nothing (root or null)
+
+You can only parent a NetworkObject under another NetworkObject. The only exception is if you don't want the NetworkObject to have a parent. In this case, you can remove the NetworkObject's parent by invoking `NetworkObject.TryRemoveParent`. If this operation succeeds, the parent of the child will be set to `null` (root of the scene hierarchy).
+
+### Only spawned NetworkObjects can be parented
+
+A NetworkObject component can only be parented if it's spawned and can only be parented under another spawned NetworkObject component. This also means that NetworkObject component parenting can only occur during a network session (netcode enabled game session). Think of NetworkObject component parenting as a Netcode event. In order for it to happen, you must have, at minimum, a server or host instance started and listening.
+
+### Invalid parenting actions are reverted
+
+If an invalid/unsupported NetworkObject component parenting action occurs, the attempted parenting action reverts back to the NetworkObject component's original parenting state.
+
+**For example:**
+If you had a NetworkObject component whose current parent was root and tried to parent it in an invalid way (such as under a GameObject without a NetworkObject component), it logs a warning message and the NetworkObject component reverts back to having root as its parent.
+
+### In-scene object parenting and player objects
+
+If you plan on parenting in-scene placed NetworkObject components with a player NetworkObject component when it's initially spawned, you need to wait until the client finishes synchronizing with the server first. Because you can only perform parenting on the server side, ensure you perform the parenting action only when the server has received the `NetworkSceneManager` generated `SceneEventType.SynchronizeComplete` message from the client that owns the player NetworkObject component to be parented (as a child or parent).
+:::info For more information
+
+- [Real World In-scene NetworkObject Parenting of Players Solution](inscene_parenting_player.md)
+- [Scene Event Notifications](../basics/scenemanagement/scene-events#scene-event-notifications)
+- [In-Scene NetworkObjects](../basics/scenemanagement/inscene-placed-networkobjects.md)
+ :::
+
+### WorldPositionStays usage
+
+When using the `NetworkObject.TrySetParent` or `NetworkObject.TryRemoveParent` methods, the `WorldPositionStays` parameter is synchronized with currently connected and late joining clients. When removing a child from its parent, use the same `WorldPositionStays` value that you used to parent the child. More specifically, when `WorldPositionStays` is false, this applies. However, if you're using the default value of `true`, this isn't required (because it's the default).
+
+When the `WorldPositionStays` parameter in `NetworkObject.TrySetParent` is the default value of `true`, this will preserve the world space values of the child NetworkObject relative to the parent. However, sometimes you might want to only preserve the local space values (pick up an object that only has some initial changes to the child's transform when parented). Through a combination of `NetworkObject.TrySetParent` and `NetworkBehaviour.OnNetworkObjectParentChanged` you can accomplish this without the need for a NetworkTransform component. To better understand how this works, it's important to understand the order of operations for both of these two methods:
+
+**Server-Side**
+
+- `NetworkObject.TrySetParent` invokes `NetworkBehaviour.OnNetworkObjectParentChanged`
+ - You can make adjustments to the child's position, rotation, and scale in the overridden `OnNetworkObjectParentChanged` method.
+- The ParentSyncMessage is generated, the transform values are added to the message, and the message is then sent.
+ - ParentSyncMessage includes the child's position, rotation, and scale
+ - Currently connected or late joining clients will be synchronized with the parenting and the child's associated transform values
+
+**When to use a NetworkTransform**
+If you plan on the child NetworkObject component moving around, rotating, or scaling independently (when parented or not) then you will still want to use a NetworkTransform component.
+If you only plan on making a one time change to the child NetworkObject component's transform when parented or having a parent removed, then the child doesn't need a NetworkTransform component.
+
+:::info For More Information
+
+- [Learn More About WorldPositionStays](https://docs.unity3d.com/ScriptReference/Transform.SetParent.html)
+ :::
+
+### Network prefabs, parenting, and NetworkTransform components
+
+Because the NetworkTransform component synchronizes the transform of a GameObject component (with a NetworkObject component attached to it), it can become tricky to understand the parent-child transform relationship and how that translates when synchronizing late joining clients. Currently, a network prefab can only have one NetworkObject component within the root GameObject component of the prefab. However, you can have a complex hierarchy of GameObject components nested under the root GameObject component and each child GameObject component can have a NetworkBehaviour component attached to it. Because a NetworkTransform component synchronizes the transform of the GameObject component it's attached to, you might be tempted to setup a network prefab like this:
+
+```
+Network Prefab Root (GameObject with NetworkObject and NetworkTransform components attached to it)
+ ├─ Child #1 (GameObject with NetworkTransform component attached to it)
+ │
+ └─ Child #2 (GameObject with NetworkTransform component attached to it)
+```
+
+While this won't give you any warnings and, depending upon the transform settings of Child #1 & #2, it might appear to work properly (because it synchronizes clients), it's important to understand how the child GameObject component (with no NetworkObject component attached to it) and parent GameObject component (that does have a NetworkObject component attached to it), synchronize when a client connects to an already in-progress network session (late joins or late joining client). If Child #1 or Child #2 have had changes to their respective GameObject component's transform before a client joining, then upon a client late joining the two child GameObject component's transforms won't synchronize during the initial synchronization period because they don't have NetworkObject components attached to them:
+
+```
+Network Prefab Root (Late joining client is synchronized with GameObject's current transform state)
+ ├─ Child #1 (Late joining client *isn't synchronized* with GameObject's current transform state)
+ │
+ └─ Child #2 (Late joining client *isn't synchronized* with GameObject's current transform state)
+```
+
+This is important to understand because the NetworkTransform component initializes itself, during `NetworkTransform.OnNetworkSpawn`, with the GameObject component's current transform state. Just below, in the parenting examples, there are some valid and invalid parenting rules. As such, take these rules into consideration when using NetworkTransform components if you plan on using a complex parent-child hierarchy. Also make sure to organize your project's assets where any children that have NetworkTransform components attached to them also have NetworkObject components attached to them to avoid late-joining client synchronization issues.
+
+## Parenting examples
+
+### Simple example:
+
+For this example, assume you have the following initial scene hierarchy before implementing parenting:
+
+```
+Sun
+Tree
+Camera
+Player (GameObject->NetworkObject)
+Vehicle (GameObject->NetworkObject)
+```
+
+Both the player and vehicle NetworkObject components are spawned and the player moves towards the vehicle and wants to get into the vehicle. The player's client sends perhaps a **use object** RPC command to the server. In turn, the server then parents the player under the vehicle and changes the player's model pose to sitting. Because both NetworkObject components are spawned and the server is receiving an RPC to perform the parenting action, the parenting action performed by the server is valid and the player is then parented under the vehicle as shown below:
+
+```
+Sun
+Tree
+Camera
+Vehicle (GameObject->NetworkObject)
+ └─ Player (GameObject->NetworkObject)
+```
+
+### Mildly complex invalid example:
+
+```
+Sun
+Tree
+Camera
+Player (GameObject->NetworkObject)
+Vehicle (GameObject->NetworkObject)
+ ├─ Seat1 (GameObject)
+ └─ Seat2 (GameObject)
+```
+
+In the above example, the vehicle has two GameObject components nested under the vehicle's root GameObject to represent the two available seats. If you tried to parent the player under Seat1:
+
+```
+Sun
+Tree
+Camera
+Vehicle (GameObject->NetworkObject)
+ ├─Seat1 (GameObject)
+ │ └─Player (GameObject->NetworkObject)
+ └─Seat2 (GameObject)
+```
+
+This is an invalid parenting and will revert.
+
+### Mildly complex valid example:
+
+To resolve the earlier invalid parenting issue, you need to add a NetworkObject component to the seats. This means you need to:
+
+1. Spawn the vehicle and the seats:
+
+```
+Sun
+Tree
+Camera
+Player (GameObject->NetworkObject)
+Vehicle (GameObject->NetworkObject)
+Seat1 (GameObject->NetworkObject)
+Seat2 (GameObject->NetworkObject)
+```
+
+2. After spawning the vehicle and seats, parent the seats under the vehicle.
+
+```
+Sun
+Tree
+Camera
+Player (GameObject->NetworkObject)
+Vehicle (GameObject->NetworkObject)
+ ├─ Seat1 (GameObject->NetworkObject)
+ └─ Seat2 (GameObject->NetworkObject)
+```
+
+3. Finally, some time later a player wants to get into the vehicle and the player is parented under Seat1:
+
+```
+Sun
+Tree
+Camera
+Vehicle (GameObject->NetworkObject)
+ ├─Seat1 (GameObject->NetworkObject)
+ │ └─Player (GameObject->NetworkObject)
+ └─Seat2 (GameObject->NetworkObject)
+```
+
+### Parenting & transform synchronization
+
+It's important to understand that without the use of a NetworkTransform component clients are only synchronized with the transform values when:
+
+- A client is being synchronized with the NetworkObject component in question:
+ - During the client's first synchronization after a client has their connection approved.
+ - When a server spawns a new NetworkObject component.
+- A NetworkObject component has been parented (or a parent removed).
+- The server can override the `NetworkBehaviour.OnNetworkObjectParentChanged` method and adjust the transform values when that's invoked.
+ - These transform changes will be synchronized with clients via the `ParentSyncMessage`
+
+:::note Optional auto synchronized parenting
+The Auto Object Parent Sync property of a NetworkObject component, enabled by default, allows you to disable automatic parent change synchronization in the event you want to implement your own parenting solution for one or more NetworkObjects. It's important to understand that disabling the Auto Object Parent Sync option of a NetworkObject component will treat the NetworkObject component's transform synchronization with clients as if its parent is the hierarchy root (null).
+:::
diff --git a/versioned_docs/version-2.0.0/advanced-topics/networktime-ticks.md b/versioned_docs/version-2.0.0/advanced-topics/networktime-ticks.md
new file mode 100644
index 000000000..1bbab4556
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/networktime-ticks.md
@@ -0,0 +1,202 @@
+---
+id: networktime-ticks
+title: NetworkTime and ticks
+sidebar_label: NetworkTime and ticks
+---
+
+## LocalTime and ServerTime
+
+Why are there two different time values and which one should be used?
+
+Netcode for GameObjects (Netcode) uses a star topology. That means all communications happen between the clients and the server/host and never between clients directly. Messages take time to transmit over the network. That's why `RPCs` and `NetworkVariable` won't happen immediately on other machines. `NetworkTime` allows to use time while considering those transmission delays.
+
+- `LocalTime` on a client is ahead of the server. If a server RPC is sent at `LocalTime` from a client it will roughly arrive at `ServerTime` on the server.
+- `ServerTime` on clients is behind the server. If a client RPC is sent at `ServerTime` from the server to clients it will roughly arrive at `ServerTime` on the clients.
+
+
+
+>Server: Delay when sending message
+ Note over Server: Message arrives at ServerTime.
+ Note over Server: On server: ServerTime == LocalTime.
+ Note over Server: Send message to clients at LocalTime.
+ Server->>Receiver: Delay when sending message
+ Note over Receiver: Message arrives at ServerTime.
+`}/>
+
+
+
+
+`LocalTime`
+- Use for player objects with client authority.
+- Use if just a general time value is needed.
+
+`ServerTime`:
+- For player objects with server authority (For example, by sending inputs to the server via RPCs)
+- In sync with position updates of `NetworkTransform` for all `NetworkObjects` where the client isn't authoritative over the transform.
+- For everything on non client controlled `NetworkObjects`.
+
+## Examples
+
+### Example 1: Using network time to synchronize environments
+
+Many games have environmental objects which move in a fixed pattern. By using network time these objects can be moved without having to synchronize their positions with a `NetworkTransform`.
+
+For instance the following code can be used to create a moving elevator platform for a client authoritative game:
+
+```csharp
+using Unity.Netcode;
+using UnityEngine;
+
+public class MovingPlatform : MonoBehaviour
+{
+ public void Update()
+ {
+ // Move up and down by 5 meters and change direction every 3 seconds.
+ var positionY = Mathf.PingPong(NetworkManager.Singleton.LocalTime.TimeAsFloat / 3f, 1f) * 5f;
+ transform.position = new Vector3(0, positionY, 0);
+ }
+}
+```
+
+### Example 2: Using network time to create a synced event
+
+Most of the time aligning an effect precisely to time isn't needed. But in some cases for important effects or gameplay events it can help to improve consistency especially for clients with bad network connections.
+
+```csharp
+using System.Collections;
+using Unity.Netcode;
+using UnityEngine;
+using UnityEngine.Assertions;
+
+public class SyncedEventExample : NetworkBehaviour
+{
+ public GameObject ParticleEffect;
+
+ // Called by the client to create a synced particle event at its own position.
+ public void ClientCreateSyncedEffect()
+ {
+ Assert.IsTrue(IsOwner);
+ var time = NetworkManager.LocalTime.Time;
+ CreateSyncedEffectServerRpc(time);
+ StartCoroutine(WaitAndSpawnSyncedEffect(0)); // Create the effect immediately locally.
+ }
+
+ private IEnumerator WaitAndSpawnSyncedEffect(float timeToWait)
+ {
+ // Note sometimes the timeToWait will be negative on the server or the receiving clients if a message got delayed by the network for a long time. This usually happens only in rare cases. Custom logic can be implemented to deal with that scenario.
+ if (timeToWait > 0)
+ {
+ yield return new WaitForSeconds(timeToWait);
+ }
+
+ Instantiate(ParticleEffect, transform.position, Quaternion.identity);
+ }
+
+ [Rpc(SendTo.Server)]
+ private void CreateSyncedEffectServerRpc(double time)
+ {
+ CreateSyncedEffectClientRpc(time); // Call a client RPC to also create the effect on each client.
+ var timeToWait = time - NetworkManager.ServerTime.Time;
+ StartCoroutine(WaitAndSpawnSyncedEffect((float)timeToWait)); // Create the effect on the server but wait for the right time.
+ }
+
+ [Rpc(SendTo.ClientsAndHost)]
+ private void CreateSyncedEffectClientRpc(double time)
+ {
+ // The owner already created the effect so skip them.
+ if (IsOwner == false)
+ {
+ var timeToWait = time - NetworkManager.ServerTime.Time;
+ StartCoroutine(WaitAndSpawnSyncedEffect((float)timeToWait)); // Create the effect on the client but wait for the right time.
+ }
+ }
+}
+```
+
+>Server: CreateSyncedEffectServerRpc
+ Server->>Receiver: CreateSyncedEffectClientRpc
+ Note over Server: ServerTime = 9.95 #38; timeToWait = 0.05
+ Note over Server: StartCoroutine(WaitAndSpawnSyncedEffect(0.05))
+ Server->>Server: WaitForSeconds(0.05);
+ Note over Server: Instantiate effect at ServerTime = 10.0
+ Note over Receiver: ServerTime = 9.93 #38; timeToWait = 0.07
+ Note over Receiver: StartCoroutine(WaitAndSpawnSyncedEffect(0.07))
+ Receiver->>Receiver: WaitForSeconds(0.07);
+ Note over Receiver: Instantiate effect at ServerTime = 10.0
+`}/>
+
+
+
+:::note
+Some components such as `NetworkTransform` add additional buffering. When trying to align an RPC event like in this example, an additional delay would need to be added.
+:::
+
+## Network Ticks
+
+Network ticks are run at a fixed rate. The 'Tick Rate' field on the `NetworkManager` can be used to set the tick rate.
+
+What does changing the network tick affect? Changes to `NetworkVariables` aren't sent immediately. Instead during each network tick changes to `NetworkVariables` are collected and sent out to other peers.
+
+To run custom code once per network tick (before `NetworkVariable` changes are collected) the `Tick` event on the `NetworkTickSystem` can be used.
+```cs
+public override void OnNetworkSpawn()
+{
+ NetworkManager.NetworkTickSystem.Tick += Tick;
+}
+
+private void Tick()
+{
+ Debug.Log($"Tick: {NetworkManager.LocalTime.Tick}");
+}
+
+public override void OnNetworkDespawn() // don't forget to unsubscribe
+{
+ NetworkManager.NetworkTickSystem.Tick -= Tick;
+}
+```
+
+:::tip
+When using `FixedUpdate` or physics in your game, set the network tick rate to the same rate as the fixed update rate. The `FixedUpdate` rate can be changed in `Edit > Project Settings > Time > Fixed Timestep`
+:::
+
+## Network FixedTime
+
+`Network FixedTime` can be used to get a time value representing the time during a network tick. This works similar to `FixedUpdate` where `Time.fixedTime` represents the time during the `FixedUpdate`.
+
+```cs
+public void Update()
+{
+ double time = NetworkManager.Singleton.LocalTime.Time; // time during this Update
+ double fixedTime = NetworkManager.Singleton.LocalTime.FixedTime; // time during the previous network tick
+}
+```
+
+## NetworkTime Precision
+
+Network time values are calculated using double precisions. This allows time to stay accurate on long running servers. For game servers which run sessions for a long time (multiple hours or days) don't convert this value in a float and always use doubles for time related calculations.
+
+For games with short play sessions casting the time to float is safe or `TimeAsFloat` can be used.
+
+## NetworkTimeSystem Configuration
+
+:::caution
+The properties of the `NetworkTimeSystem` should be left untouched on the server/host. Changing the values on the client is sufficient to change the behavior of the time system.
+:::
+
+The way network time gets calculated can be configured in the `NetworkTimeSystem` if needed. Refer to the [API docs](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkTimeSystem.html) for information about the properties which can be modified. All properties can be safely adjusted at runtime. For instance, buffer values can be increased for a player with a bad connection.
+
+
diff --git a/versioned_docs/version-2.0.0/advanced-topics/object-pooling.md b/versioned_docs/version-2.0.0/advanced-topics/object-pooling.md
new file mode 100644
index 000000000..4e8dac44a
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/object-pooling.md
@@ -0,0 +1,28 @@
+---
+id: object-pooling
+title: Object pooling
+---
+
+Netcode for GameObjects (Netcode) provides built-in support for Object Pooling, which allows you to override the default Netcode destroy and spawn handlers with your own logic. This allows you to store destroyed network objects in a pool to reuse later. This is useful for often used objects, such as projectiles, and is a way to increase the application's overall performance. By pre-instantiating and reusing the instances of those objects, object pooling removes the need to create or destroy objects at runtime, which can save a lot of work for the CPU. This means that instead of creating or destroying the same object over and over again, it's simply deactivated after use, then, when another object is needed, the pool recycles one of the deactivated objects and reactivates it.
+
+See [Introduction to Object Pooling](https://learn.unity.com/tutorial/introduction-to-object-pooling) to learn more about the importance of pooling objects.
+
+## NetworkPrefabInstanceHandler
+
+You can register your own spawn handlers by including the `INetworkPrefabInstanceHandler` interface and registering with the `NetworkPrefabHandler`.
+```csharp
+ public interface INetworkPrefabInstanceHandler
+ {
+ NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation);
+ void Destroy(NetworkObject networkObject);
+ }
+```
+Netcode will use the `Instantiate` and `Destroy` methods in place of default spawn handlers for the NetworkObject used during spawning and despawning. Because the message to instantiate a new NetworkObject originates from a Host or Server, both won't have the Instantiate method invoked. All clients (excluding a Host) will have the instantiate method invoked if the `INetworkPrefabInstanceHandler` implementation is registered with `NetworkPrefabHandler` (`NetworkManager.PrefabHandler`) and a Host or Server spawns the registered/associated NetworkObject.
+
+The following example is from the Boss Room Sample. It shows how object pooling is used to handle the different projectile objects. In that example, the class `NetworkObjectPool` is the data structure containing the pooled objects and the class `PooledPrefabInstanceHandler` is the handler implementing `INetworkPrefabInstanceHandler`.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs
+```
+
+Let's have a look at `NetworkObjectPool` first. `PooledPrefabsList` has a list of prefabs to handle, with an initial number of instances to spawn for each. The `RegisterPrefabInternal` method, called in `OnNetworkSpawn`, initializes the different pools for each Prefab as `ObjectPool`s inside the `m_PooledObjects` dictionary. It also instantiates the handlers for each Prefab and registers them. To use these objects, a user then needs to obtain it via the `GetNetworkObject` method before spawning it, then return the object to the pool after use with `ReturnNetworkObject` before despawning it. This only needs to be done on the server, as the `PooledPrefabInstanceHandler` will handle it on the client(s) when the network object's `Spawn` or `Despawn` method is called, via its `Instantiate` and `Destroy` methods. Inside those methods, the `PooledPrefabInstanceHandler` simply calls the pool to get the corresponding object, or to return it.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/physics.md b/versioned_docs/version-2.0.0/advanced-topics/physics.md
new file mode 100644
index 000000000..403d69c62
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/physics.md
@@ -0,0 +1,70 @@
+---
+id: physics
+title: Physics
+Description: Brief explanation on using Physics in Netcode for GameObjects
+---
+
+There are many different ways to manage physics simulation in multiplayer games. Netcode for GameObjects (Netcode) has a built in approach which allows for server-authoritative physics where the physics simulation only runs on the server. To enable network physics, add a `NetworkRigidbody` component to your object.
+
+## NetworkRigidbody
+
+NetworkRigidbody is a component that sets the Rigidbody of the GameObject into kinematic mode on all non-authoritative instances (except the instance that has authority). Authority is determined by the NetworkTransform component (required) attached to the same GameObject as the NetworkRigidbody. Whether the NetworkTransform is server authoritative (default) or owner authoritative, the NetworkRigidBody authority model will mirror it. That way, the physics simulation runs on the authoritative instance, and the resulting positions synchronize on the non-authoritative instances, each with their RigidBody being Kinematic, without any interference.
+
+To use NetworkRigidbody, add a Rigidbody, NetworkTransform, and NetworkRigidbody component to your NetworkObject.
+
+Some collision events aren't fired when using `NetworkRigidbody`.
+- On the `server`, all collision and trigger events (such as `OnCollisionEnter`) fire as expected and you can access (and change) values of the `Rigidbody` (such as velocity).
+- On the `clients`, the `Rigidbody` is kinematic. Trigger events still fire but collision events won't fire when colliding with other networked `Rigidbody` instances.
+
+:::tip
+
+If there is a need for a gameplay event to happen on a collision, you can listen to `OnCollisionEnter` function on the server and synchronize the event via `Rpc(SendTo.ClientsAndHost)` to all clients.
+
+:::
+
+## NetworkRigidbody2D
+
+`NetworkRigidbody2D` works in the same way as NetworkRigidbody but for 2D physics (`Rigidbody2D`) instead.
+
+## NetworkRigidbody and ClientNetworkTransform
+
+You can use NetworkRigidbody with the [`ClientNetworkTransform`](../components/networktransform.md#clientnetworktransform) package sample to allow the owner client of a NetworkObject to move it authoritatively. In this mode, collisions only result in realistic dynamic collisions if the object is colliding with other NetworkObjects (owned by the same client).
+
+:::note
+
+Add the ClientNetworkTransform component to your GameObject first. Otherwise the NetworkRigidbody automatically adds a regular NetworkTransform.
+
+:::
+
+## Physics and latency
+
+A common issue with physics in multiplayer games is lag and how objects update on basically different timelines. For example, a player would be on a timeline that's offset by the network latency relative to your server's objects. One way to prepare for this is to test your game with artificial lag. You might catch some weird delayed collisions that would otherwise make it into production.
+
+The ClientDriven [bitesize sample](../learn/bitesize/bitesize-clientdriven.md) addresses this by manually adding forces server-side to offer a buffer before an actual collision, but it still feels wobbly at times. However, this isn't really a solution.
+
+The best way to address the issue of physics latency is to create a custom `NetworkTransform` with a custom physics-based interpolator. You can also use the [Network Simulator tool](../../tools/network-simulator.md) to spot issues with latency.
+
+## Message processing vs. applying changes to state (timing considerations)
+
+When handling the synchronization of changes to certain physics properties, it's important to understand the order of operations involved in message processing relative to the update stages that occur within a single frame. The stages occur in this order:
+
+- Initialization _(Awake and Start are invoked here)_
+- EarlyUpdate _(Inbound messages are processed here)_
+- FixedUpdate _(Physics simulation is run and results)_
+- PreUpdate _(NetworkTime and Tick is updated)_
+- Update _(NetworkBehaviours/Components are updated)_
+- PreLateUpdate: _(Useful for handling post-update tasks prior to processing and sending pending outbound messages)_
+- LateUpdate: _(Useful for changes to camera, detecting input, and handling other post-update tasks)_
+- PostLateUpdate: _(Dirty NetworkVariables processed and pending outbound messages are sent)_
+
+From this list of update stages, the `EarlyUpdate` and `FixedUpdate` stages have the most impact on NetworkVariableDeltaMessage and RpcMessages processing. Inbound messages are processed during the `EarlyUpdate` stage, which means that Rpc methods and NetworkVariable.OnValueChanged callbacks are invoked at that point in time during any given frame. Taking this into consideration, there are certain scenarios where making changes to a Rigidbody could yield undesirable results.
+
+### Rigidbody interpolation example
+
+While `NetworkTransform` offers interpolation as a way to smooth between delta state updates, it doesn't get applied to the authoritative instance. You can use `Rigidbody.interpolation` for your authoritative instance while maintaining a strict server-authoritative motion model.
+
+To have a client control their owned objects, you can use either [RPCs](message-system/rpc.md) or [NetworkVariables](../basics/networkvariables.md) on the client-side. However, this often results in the host-client's updates working as expected, but with slight jitter when a client sends updates. You might be scanning for key or device input during the `Update` to `LateUpdate` stages. Any input from the host player is applied after the `FixedUpdate` stage (i.e. physics simulation for the frame has already run), but input from client players is sent via a message and processed, with a half RTT delay, on the host side (or processed 1 network tick + half RTT if using NetworkVariables). Because of when messages are processed, client input updates run the risk of being processed during the `EarlyUpdate` stage which occurs just before the current frame's `FixedUpdate` stage.
+
+To avoid this kind of scenario, it's recommended that you apply any changes received via messages to a Rigidbody _after_ the FixedUpdate has run for the current frame. If you [look at how `NetworkTransform` handles its changes to transform state](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/a2c6f7da5be5af077427eef9c1598fa741585b82/com.unity.netcode.gameobjects/Components/NetworkTransform.cs#L3028), you can see that state updates are applied during the `Update` stage, but are received during the `EarlyUpdate` stage. Following this kind of pattern when synchronizing changes to a Rigidbody via messages will help you to avoid unexpected results in your Netcode for GameObjects project.
+
+The best way to address the issue of physics latency is to create a custom `NetworkTransform` with a custom physics-based interpolator. You can also use the [Network Simulator tool](../../tools/network-simulator.md) to spot issues with latency.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/reconnecting-mid-game.md b/versioned_docs/version-2.0.0/advanced-topics/reconnecting-mid-game.md
new file mode 100644
index 000000000..40664ea19
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/reconnecting-mid-game.md
@@ -0,0 +1,84 @@
+---
+id: reconnecting-mid-game
+title: Reconnecting mid-game
+created: 2023-01-24T17:55:53-06:00
+updated: 2023-01-24T18:28:58-06:00
+---
+
+In a multiplayer game, clients might get disconnected from the server for a variety of reasons (such as network issues or application/device crashes). For those reasons, you might want to allow your players to reconnect to the game.
+
+# Considerations
+
+Review the following considerations before allowing clients to reconnect in the middle of an active game:
+
+- Clients might have specific state and in-game data associated with them. If you want them to reconnect with that same state and data, implement a mechanism to keep the association of state and data with the client for when they reconnect. Refer to [Session Management](session-management.md) for more information.
+- Depending on your game's requirements, make sure the client's state is reset and ready to connect before attempting reconnection. This might require resetting some external services.
+- When using [scene management](../basics/scenemanagement/scene-management-overview.md) and multiple additive scenes, there is a specific case to keep in mind. During the synchronization process, which launches when connecting to a game, if the client's active main scene is the same as the server's, it won't start a scene load in single mode for that scene. Instead, it loads all additive scenes loaded on the server. This means that if the client has additive scenes loaded, it won't unload them like it would if the client's main scene was different than the server's.
+
+ - For example, if during a game, the server loads **main scene A**, then additively loads scenes **B** and **C**, the client has all three loaded. If the client disconnects and reconnects without changing scenes, the scene synchronization process recognizes that **main scene A** is already loaded on the client, and then proceeds to load the server's additive scenes. In that case, the client loads the scenes **B** and **C** a second time and then has two copies of those scenes loaded.
+
+ However, if, while the client is disconnected, the server loads or unloads a scene additively, there is also a mismatch between the scenes loaded on the client and on the server. For example, if the server unloads scene **C** and loads scene **D**, the client loads scene **D** when synchronizing, but doesn't unload scene C, so the client has loaded scenes **A**, **B** (twice), **C**, and **D**, while the server only has loaded scenes **A**, **B**, and **D**.
+
+ - If you want to avoid this behavior, you can
+ - Load a different scene in single mode on the client when disconnecting
+ - Unload additive scenes on the client when disconnecting
+ - Unload additive scenes on the client when reconnecting
+ - Use the `NetworkSceneManager.VerifySceneBeforeLoading` callback to prevent loading scenes already loaded on the client. However, this won't handle unloading scenes that were unloaded by the server between the time the client disconnected and reconnected.
+
+If you want to avoid this behavior, you can:
+
+- Load a different scene in single mode on the client when disconnecting
+
+- Unload additive scenes on the client when disconnecting
+
+- Unload additive scenes on the client when reconnecting
+
+- Use the `NetworkSceneManager.VerifySceneBeforeLoading` callback to prevent loading scenes already loaded on the client. However, this won't handle unloading scenes that the server unloaded between the time the client disconnected and reconnected.
+
+# Automatic reconnection
+
+For a smoother experience for your players, clients can automatically try to reconnect to a game when they lose a connection unexpectedly.
+
+To implement automatic reconnection:
+
+- Define what triggers the reconnection process and when it should start.
+
+ - For example, you can use the `NetworkManager.OnClientDisconnectCallback` callback, or some other unique event depending on your game.
+
+- Ensure the `NetworkManager` shuts down before attempting any reconnection.
+
+ - You can use the `NetworkManager.ShutdownInProgress` property to manage this.
+
+- Add additional checks to ensure automatic reconnection doesn't trigger under the wrong conditions.
+
+ - Examples
+
+ - A client purposefully quits a game
+
+ - The server shuts down as expected when the game session ends
+
+ - A client gets kicked from a game
+
+ - A client is denied during connection approval
+
+Depending on your game, you might want to add the following features as well:
+
+- Include multiple reconnection attempts in case of failure. You need to define the number of attempts, ensure that `NetworkManager` properly shuts down between each try, and reset the client's state (if needed).
+
+- Offer an option for players to cancel the reconnection process. This might be useful when there are a lot of reconnection attempts or when each try lasts a long duration.
+
+## Automatic reconnection example
+
+Check out the [Boss Room sample](../learn/bossroom/getting-started-boss-room.md) for an example implementation of automatic reconnection.
+
+The entry point for this feature is in [this class](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ConnectionManagement/ConnectionState/ClientReconnectingState.cs). Boss Room's implementation uses a state inside a state machine that starts a coroutine on entering it ( `ReconnectCoroutine`) that attempts to reconnect a few times sequentially, until it either succeeds, surpasses the defined maximum number of attempts, or is cancelled. (Check out `OnClientConnected`, `OnClientDisconnect`, `OnDisconnectReasonReceived`, and `OnUserRequestedShutdown`.)
+
+The reconnecting state is entered when a client disconnects unexpectedly. (Check out `OnClientDisconnect` in [this class](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectedState.cs))
+
+:::note
+
+This sample connects with [Lobby](https://docs.unity.com/lobby/unity-lobby-service-overview.html) and [Relay](https://docs.unity.com/relay/get-started.html) services, so the client must make sure it has left the lobby before each reconnection try.
+
+For more information about how Boss Room leverages Lobby and Relay, refer to [Getting Started with Boss Room](../learn/bossroom/getting-started-boss-room.md#register-the-project-with-unity-gaming-services-ugs)
+
+:::
diff --git a/versioned_docs/version-2.0.0/advanced-topics/serialization/cprimitives.md b/versioned_docs/version-2.0.0/advanced-topics/serialization/cprimitives.md
new file mode 100644
index 000000000..794468570
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/serialization/cprimitives.md
@@ -0,0 +1,21 @@
+---
+id: cprimitives
+title: C# primitives
+---
+
+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`.
+
+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).
+
+```csharp
+[Rpc(SendTo.Server)]
+void FooServerRpc(int somenumber, string sometext) { /* ... */ }
+
+void Update()
+{
+ if (Input.GetKeyDown(KeyCode.P))
+ {
+ FooServerRpc(Time.frameCount, "hello, world"); // Client -> Server
+ }
+}
+```
diff --git a/versioned_docs/version-2.0.0/advanced-topics/serialization/enum-types.md b/versioned_docs/version-2.0.0/advanced-topics/serialization/enum-types.md
new file mode 100644
index 000000000..90ca1fe22
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/serialization/enum-types.md
@@ -0,0 +1,33 @@
+---
+id: enum_types
+title: Enum types
+---
+
+A user-defined enum type will be serialized by built-in serialization code (with underlying integer type).
+
+```csharp
+enum SmallEnum : byte
+{
+ A,
+ B,
+ C
+}
+
+enum NormalEnum // default -> int
+{
+ X,
+ Y,
+ Z
+}
+
+[Rpc(SendTo.Server)]
+void ConfigServerRpc(SmallEnum smallEnum, NormalEnum normalEnum) { /* ... */ }
+
+void Update()
+{
+ if (Input.GetKeyDown(KeyCode.P))
+ {
+ ConfigServerRpc(SmallEnum.A, NormalEnum.X); // Client -> Server
+ }
+}
+```
diff --git a/versioned_docs/version-2.0.0/advanced-topics/serialization/fixedstrings.md b/versioned_docs/version-2.0.0/advanced-topics/serialization/fixedstrings.md
new file mode 100644
index 000000000..15391926b
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/serialization/fixedstrings.md
@@ -0,0 +1,16 @@
+---
+id: fixedstrings
+title: Fixed strings
+---
+
+Netcode's serialization system natively supports Unity's Fixed String types (`FixedString32`, `FixedString64`, `FixedString128`, `FixedString512`, and `FixedString4096`). The serialization system intelligently understands these fixed string types and ensures that only the amount of the string in use is serialized, even for the larger types. This native support ensures Netcode uses no more bandwidth than is necessary.
+
+```csharp
+[Rpc(SendTo.Server)]
+void SetPlayerNameServerRpc(FixedString32 playerName) { /* ... */ }
+
+void SetPlayerName(string name)
+{
+ SetPlayerNameServerRpc(new FixedString32(name));
+}
+```
diff --git a/versioned_docs/version-2.0.0/advanced-topics/serialization/inetworkserializable.md b/versioned_docs/version-2.0.0/advanced-topics/serialization/inetworkserializable.md
new file mode 100644
index 000000000..8764ccc47
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/serialization/inetworkserializable.md
@@ -0,0 +1,199 @@
+---
+id: inetworkserializable
+title: INetworkSerializable
+sidebar_label: INetworkSerializable
+created: 2023-01-24T18:19:59-06:00
+updated: 2023-01-24T18:19:59-06:00
+---
+
+You can use the `INetworkSerializable` interface to define custom serializable types.
+
+```csharp
+struct MyComplexStruct : INetworkSerializable
+{
+ public Vector3 Position;
+ public Quaternion Rotation;
+
+ // INetworkSerializable
+ public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter
+ {
+ serializer.SerializeValue(ref Position);
+ serializer.SerializeValue(ref Rotation);
+ }
+ // ~INetworkSerializable
+}
+```
+
+Types implementing `INetworkSerializable` are supported by `NetworkSerializer`, `RPC` s and `NetworkVariable` s.
+
+```csharp
+
+[Rpc(SendTo.Server)]
+void MyServerRpc(MyComplexStruct myStruct) { /* ... */ }
+
+void Update()
+{
+ if (Input.GetKeyDown(KeyCode.P))
+ {
+ MyServerRpc(
+ new MyComplexStruct
+ {
+ Position = transform.position,
+ Rotation = transform.rotation
+ }); // Client -> Server
+ }
+}
+```
+
+## Nested serial types
+
+Nested serial types will be `null` unless you initialize following one of these methods:
+
+* Manually before calling `SerializeValue` if `serializer.IsReader` (or something like that).
+
+* Initialize in the default constructor.
+
+This is by design. You may see the values as null until initialized. The serializer isn't deserializing them, the `null` value is applied before it can be serialized.
+
+## Conditional Serialization
+
+As you have more control over serialization of a struct, you might implement conditional serialization at runtime.
+
+The following example explores a more advanced use case.
+
+### Example: Move
+
+```csharp
+
+public struct MyMoveStruct : INetworkSerializable
+{
+ public Vector3 Position;
+ public Quaternion Rotation;
+
+ public bool SyncVelocity;
+ public Vector3 LinearVelocity;
+ public Vector3 AngularVelocity;
+
+ void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter
+ {
+ // Position & Rotation
+ serializer.SerializeValue(ref Position);
+ serializer.SerializeValue(ref Rotation);
+
+ // LinearVelocity & AngularVelocity
+ serializer.SerializeValue(ref SyncVelocity);
+ if (SyncVelocity)
+ {
+ serializer.SerializeValue(ref LinearVelocity);
+ serializer.SerializeValue(ref AngularVelocity);
+ }
+ }
+}
+```
+
+**Reading:**
+
+* (De)serialize `Position` back from the stream.
+
+* (De)serialize `Rotation` back from the stream.
+
+* (De)serialize `SyncVelocity` back from the stream.
+
+* Check if `SyncVelocity` is set to true, if so:
+
+ * (De)serialize `LinearVelocity` back from the stream.
+
+ * (De)serialize `AngularVelocity` back from the stream.
+
+**Writing:**
+
+* Serialize `Position` into the stream.
+
+* Serialize `Rotation` into the stream.
+
+* Serialize `SyncVelocity` into the stream.
+
+* Check if `SyncVelocity` is set to true, if so:
+
+ * Serialize `LinearVelocity` into the stream.
+
+ * Serialize `AngularVelocity` into the stream.
+
+* If the `SyncVelocity` flag is set to true, serialize both the `LinearVelocity` and `AngularVelocity` into the stream.
+
+* When the `SyncVelocity` flag is set to `false`, leave `LinearVelocity` and `AngularVelocity` with default values.
+
+### Recursive Nested Serialization
+
+It's possible to recursively serialize nested members with `INetworkSerializable` interface down in the hierarchy tree.
+
+Review the following example:
+
+```csharp
+
+public struct MyStructA : INetworkSerializable
+{
+ public Vector3 Position;
+ public Quaternion Rotation;
+
+ void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter
+ {
+ serializer.SerializeValue(ref Position);
+ serializer.SerializeValue(ref Rotation);
+ }
+}
+
+public struct MyStructB : INetworkSerializable
+{
+ public int SomeNumber;
+ public string SomeText;
+ public MyStructA StructA;
+
+ void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter
+ {
+ serializer.SerializeValue(ref SomeNumber);
+ serializer.SerializeValue(ref SomeText);
+ StructA.NetworkSerialize(serializer);
+ }
+}
+```
+
+If you were to serialize `MyStructA` alone, it would serialize `Position` and `Rotation` into the stream using `NetworkSerializer`.
+
+However, if you were to serialize `MyStructB`, it would serialize `SomeNumber` and `SomeText` into the stream, then serialize `StructA` by calling `MyStructA` 's `void NetworkSerialize(NetworkSerializer)` method, which serializes `Position` and `Rotation` into the same stream.
+
+:::note
+
+Technically, there is no hard-limit on the number of `INetworkSerializable` fields you can serialize down the tree hierarchy. In practice, consider memory and bandwidth boundaries for best performance.
+
+:::
+
+:::tip
+
+You can conditionally serialize in recursive nested serialization scenario and make use of both features.
+
+:::
+
+:::caution
+
+While you can have nested `INetworkSerializable` implementations (an `INetworkSerializable` implementation with `INetworkSerializable` implementations as properties) like demonstrated in the example above, you can't have derived children of an `INetworkSerializable` implementation.
+**Unsupported Example**
+
+```csharp
+/// This isn't supported.
+public struct MyStructB : MyStructA
+{
+ public int SomeNumber;
+ public string SomeText;
+
+ void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter
+ {
+ serializer.SerializeValue(ref SomeNumber);
+ serializer.SerializeValue(ref SomeText);
+ serializer.SerializeValue(ref Position);
+ serializer.SerializeValue(ref Rotation);
+ }
+}
+```
+
+:::
diff --git a/versioned_docs/version-2.0.0/advanced-topics/serialization/inetworkserializebymemcpy.md b/versioned_docs/version-2.0.0/advanced-topics/serialization/inetworkserializebymemcpy.md
new file mode 100644
index 000000000..c6bf366f3
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/serialization/inetworkserializebymemcpy.md
@@ -0,0 +1,29 @@
+---
+id: inetworkserializebymemcpy
+title: INetworkSerializeByMemcpy
+sidebar_label: INetworkSerializeByMemcpy
+---
+
+The `INetworkSerializeByMemcpy` interface is used to mark an unmanaged struct type as being trivially serializable over the network by directly copying the whole struct, byte-for-byte, as it appears in memory, into and out of the buffer. This can offer some benefits for performance compared to serializing one field at a time, especially if the struct has many fields in it, but it may be less efficient from a bandwidth-usage perspective, as fields will often be padded for memory alignment and you won't be able to "pack" any of the fields to optimize for space usage.
+
+The interface itself has no methods in it - it's an empty interface that satisfies a constraint on methods that perform this type of serialization, primarily there to ensure that memcpy serialization isn't performed by accident on structs that don't support it.
+
+```csharp
+public struct MyStruct : INetworkSerializeByMemcpy
+{
+ public int A;
+ public int B;
+ public float C;
+ public bool D;
+}
+```
+
+If you have a type you wish to serialize that you know is compatible with this method of serialization, but don't have access to modify the struct to add this interface, you can wrap your values in `ForceNetworkSerializeByMemcpy` to enable it to be serialized this way. This works in both `RPC`s and `NetworkVariables`, as well as in other contexts such as `BufferSerializer<>`, `FastBufferReader`, and `FastBufferWriter`.
+
+```csharp
+public NetworkVariable> GuidVar;
+```
+
+:::caution
+Take care with using `INetworkSerializeByMemcpy`, and especially `ForceNetworkSerializeByMemcpy`, because not all unmanaged structs are actually compatible with this type of serialization. Anything that includes pointer types (including Native Collections like `NativeArray<>`) won't function correctly when serialized this way, and will likely cause memory corruption or crashes on the receiving side.
+:::
diff --git a/versioned_docs/version-2.0.0/advanced-topics/serialization/networkobject-serialization.md b/versioned_docs/version-2.0.0/advanced-topics/serialization/networkobject-serialization.md
new file mode 100644
index 000000000..56c74cac9
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/serialization/networkobject-serialization.md
@@ -0,0 +1,95 @@
+---
+id: networkobject-serialization
+title: NetworkObject and NetworkBehaviour
+description: Brief explanation on using NetworkObject and NetworkBehaviour in Network for GameObjects
+---
+
+`GameObjects`, `NetworkObjects` and `NetworkBehaviour` aren't serializable types so they can't be used in `RPCs` or `NetworkVariables` by default.
+
+There are two convenience wrappers which can be used to send a reference to a NetworkObject or a `NetworkBehaviour` over RPCs or `NetworkVariables`.
+
+## NetworkObjectReference
+
+`NetworkObjectReference` can be used to serialize a reference to a NetworkObject. It can only be used on already spawned `NetworkObjects`.
+
+Here is an example of using NetworkObject reference to send a target NetworkObject over an RPC:
+```csharp
+public class Weapon : NetworkBehaviour
+{
+ public void ShootTarget(GameObject target)
+ {
+ var targetObject = target.GetComponent();
+ ShootTargetServerRpc(targetObject);
+ }
+
+ [Rpc(SendTo.Server)]
+ public void ShootTargetServerRpc(NetworkObjectReference target)
+ {
+ if (target.TryGet(out NetworkObject targetObject))
+ {
+ // deal damage or something to target object.
+ }
+ else
+ {
+ // Target not found on server, likely because it already has been destroyed/despawned.
+ }
+ }
+}
+```
+
+### Implicit Operators
+
+There are also implicit operators which convert from/to `NetworkObject/GameObject` which can be used to simplify code. For instance the above example can also be written in the following way:
+```csharp
+public class Weapon : NetworkBehaviour
+{
+ public void ShootTarget(GameObject target)
+ {
+ ShootTargetServerRpc(target);
+ }
+
+ [Rpc(SendTo.Server)]
+ public void ShootTargetServerRpc(NetworkObjectReference target)
+ {
+ NetworkObject targetObject = target;
+ }
+}
+```
+:::note
+The implicit conversion to NetworkObject / `GameObject` will result in `Null` if the reference can't be found.
+:::
+
+## NetworkBehaviourReference
+
+`NetworkBehaviourReference` works similar to `NetworkObjectReference` but is used to reference a specific `NetworkBehaviour` component on a spawned NetworkObject.
+
+```cs
+public class Health : NetworkBehaviour
+{
+ public NetworkVariable Health = new NetworkVariable();
+}
+
+public class Weapon : NetworkBehaviour
+{
+ public void ShootTarget(GameObject target)
+ {
+ var health = target.GetComponent();
+ ShootTargetServerRpc(health, 10);
+ }
+
+ [Rpc(SendTo.Server)]
+ public void ShootTargetServerRpc(NetworkBehaviourReference health, int damage)
+ {
+ if (health.TryGet(out Health healthComponent))
+ {
+ healthComponent.Health.Value -= damage;
+ }
+ }
+}
+```
+
+## How NetworkObjectReference & NetworkBehaviourReference work
+
+`NetworkObjectReference` and `NetworkBehaviourReference` are convenience wrappers which serialize the id of a NetworkObject when being sent and on the receiving end retrieve the corresponding ` ` with that id. `NetworkBehaviourReference` sends an additional index which is used to find the right `NetworkBehaviour` on the NetworkObject.
+
+Both of them are structs implementing the `INetworkSerializable` interface.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/serialization/serialization-arrays.md b/versioned_docs/version-2.0.0/advanced-topics/serialization/serialization-arrays.md
new file mode 100644
index 000000000..4a386b740
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/serialization/serialization-arrays.md
@@ -0,0 +1,87 @@
+---
+id: arrays
+title: Arrays and native containers
+---
+
+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.
+
+## Performance considerations
+
+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.
+
+For this reason, arrays of strings (`string[]`) aren't supported by the built-in serialization code. Instead, it's recommended to use `NativeArray` or `NativeList`, because they're more efficient and don't incur garbage collected memory allocation. Refer to [`NativeArray`](#nativearrayt) and [`NativeList`](#nativelistt) below for more details.
+
+## Built-in primitive types example
+
+Using built-in primitive types is fairly straightforward:
+
+```csharp
+[Rpc(SendTo.Server)]
+void HelloServerRpc(int[] scores, Color[] colors) { /* ... */ }
+```
+
+## INetworkSerializable implementation example
+
+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":
+
+```csharp
+[Rpc(SendTo.ClientsAndHost)]
+void SendMessagesClientRpc(StringContainer[] messages)
+{
+ foreach (var stringContainer in stringContainers)
+ {
+ Debug.Log($"{stringContainer.SomeText}");
+ }
+}
+
+public class StringContainer : INetworkSerializable
+{
+ public string SomeText;
+ public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter
+ {
+ if (serializer.IsWriter)
+ {
+ serializer.GetFastBufferWriter().WriteValueSafe(SomeText);
+ }
+ else
+ {
+ serializer.GetFastBufferReader().ReadValueSafe(out SomeText);
+ }
+ }
+}
+```
+
+## Native containers
+
+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.
+
+A few examples of nesting that will cause a crash:
+
+* `NativeArray>`
+* `NativeList>`
+* `NativeArray>`
+* `NativeList>`
+
+### `NativeArray`
+
+To serialize a `NativeArray` container, use `serializer.SerializeValue(ref Array)`.
+
+### `NativeList`
+
+To serialize a `NativeList` container, you must:
+1. Ensure your assemblies reference `Collections`.
+2. You must add `UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT` to your **Scriptiong Define Symbols** list.
+ 1. From the Unity Editor top bar menu, go to **Edit** > **Project Settings...** > **Player**.
+ 2. Select the **Other Settings** dropdown.
+ 3. Scroll to **Script Compilation** > **Scripting Define Symbols**.
+ 4. Add `UNITY_NETCODE_NATIVE_COLLECTION_SUPPORT`.
+3. Use `serializer.SerializeValue(ref List)` as your serialization syntax.
+
+:::important
+When using `NativeLists` within `INetworkSerializable`, the list `ref` value must be a valid, initialized `NativeList`.
+
+NetworkVariables are similar that the value must be initialized before it can receive updates.
+For example, `public NetworkVariable> ByteListVar = new NetworkVariable>{Value = new NativeList(Allocator.Persistent)};`.
+
+RPCs do this automatically.
+:::
diff --git a/versioned_docs/version-2.0.0/advanced-topics/serialization/serialization-intro.md b/versioned_docs/version-2.0.0/advanced-topics/serialization/serialization-intro.md
new file mode 100644
index 000000000..e81443336
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/serialization/serialization-intro.md
@@ -0,0 +1,16 @@
+---
+id: serialization-intro
+title: About serialization
+---
+Multiplayer framework has built-in serialization support for C# and Unity primitive types out-of-the-box, also with ability to further extend network serialization for user defined types implementing `INetworkSerializable` interface.
+
+See the following sections:
+
+* [C# Primitives](cprimitives.md)
+* [Unity Primitives](unity-primitives.md)
+* [Enum Types](enum-types.md)
+* [Arrays](serialization-arrays.md)
+* [Fixed Strings](fixedstrings.md)
+* [INetworkSerializable](inetworkserializable.md)
+* [INetworkSerializeByMemcpy](inetworkserializebymemcpy.md)
+* [NetworkObjects & NetworkBehaviours](networkobject-serialization.md)
diff --git a/versioned_docs/version-2.0.0/advanced-topics/serialization/unity-primitives.md b/versioned_docs/version-2.0.0/advanced-topics/serialization/unity-primitives.md
new file mode 100644
index 000000000..a2bfaef84
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/serialization/unity-primitives.md
@@ -0,0 +1,19 @@
+---
+id: unity-primitives
+title: Unity primitives
+---
+
+Unity Primitive `Color`, `Color32`, `Vector2`, `Vector3`, `Vector4`, `Quaternion`, `Ray`, `Ray2D` types will be serialized by built-in serialization code.
+
+```csharp
+[Rpc(SendTo.ClientsAndHost)]
+void BarClientRpc(Color somecolor) { /* ... */ }
+
+void Update()
+{
+ if (Input.GetKeyDown(KeyCode.P))
+ {
+ BarClientRpc(Color.red); // Server -> Client
+ }
+}
+```
diff --git a/versioned_docs/version-2.0.0/advanced-topics/session-management.md b/versioned_docs/version-2.0.0/advanced-topics/session-management.md
new file mode 100644
index 000000000..3d8a43447
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/session-management.md
@@ -0,0 +1,43 @@
+---
+id: session-management
+title: Session management
+created: 2023-01-24T17:55:53-06:00
+updated: 2023-01-24T18:28:58-06:00
+---
+
+You can use session management to keep data when a player disconnects and accurately reassign it to the player when they reconnect.
+
+# Linking data to players
+
+To reassign data to the correct player when they reconnect, you need to link this data to the player.
+
+The **clientId** generated by Netcode for GameObjects (Netcode) can't be used, because it generates when a player connects and is disposed of when they disconnect. That ID may then be assigned to a different player if they connect to the server after the first one disconnected.
+
+To properly link data to a specific player, we need an ID that isn't tied to the current connection, but persists through time and is unique to that player. Some options include
+* A login system with unique player accounts
+
+* A Globally Unique Identifier (GUID). For example, a GUID generated via `System.Guid.NewGuid()` and then saved to the `PlayerPrefs` client side.
+
+With this unique identifier, you can map each player's data (that's needed when reconnecting), such as the current state of their character (last known position, health, and the like). You then ensure this data is up to date and kept host side after a player disconnects to repopulate that player's data when they reconnect.
+
+You can also decide to clear all data when a session completes or add a timeout to purge the data after a specific amount of time.
+
+# Reconnection
+
+The best way to reconnect players depends on your game. For example, if you use a [Player Object](../basics/networkobject.md#player-objects), a new `Default Player Prefab` automatically spawns when a player connects to the game (including when they reconnect). You can use the player's earlier saved session data to update that object so that it returns to the same state before disconnecting. In those cases, you would need to keep all the important data that you want to restore and map it to the player using your identification system. You can save this data when a player disconnects or update it periodically. You can then use the `OnNetworkSpawn` event on the Player Object's `NetworkBehavior`(s) to get this data and apply it where needed.
+
+In cases where we don't use the Player Object approach and instead manually attribute client ownership to NetworkObject(s), we can keep the objects that a player owns when they disconnect, and set the reconnected player as their new owner. To accomplish this, the only data we would need to keep would be the mapping between those objects and their owning player's identifier, then when a player reconnects we can use this mapping to set them as the new owner. This mapping can be as simple as a dictionary mapping the player identifier with the `NetworkObjectId`(s) of the NetworkObject(s) they own. Then, in the `OnClientConnectedCallback` from the `NetworkManager`, the server can set the ownership of these objects.
+
+Here is an example from the Boss Room sample, showing some simple session management. The game uses the Player Object approach and a GUID to identify unique players.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/SessionManager.cs
+```
+
+This class allows Boss Room to handle player session data, represented by a struct `T` implementing the `ISessionPlayerData` interface, by providing mechanisms to initialize, get and edit that data, and to associate it to a specific player. It also handles the clearing of data that's no longer used and the reinitialization of data between sessions.
+
+In this case, since game sessions are quite short, the session data is only cleared for disconnected players when a session ends, or if a player leaves before a session starts. This makes sure that if a player disconnects during a session and then reconnects during the next session, the game treats it as a new connection. The definition of when a session ends and when a session starts might vary from game to game, but in Boss Room, a session starts after character selection and ends when the players enter the post-game scene. In other cases, one might want to add a timeout to session data and clear it after a specified time instead.
+
+This code is in Boss Room's utilities package so it can be easily reused. You can add this package via the `Package Manager` window in the Unity Editor by selecting `add from Git URL` and adding the following URL: "https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main"
+
+Or you can directly add this line to your `manifest.json` file: "com.unity.multiplayer.samples.coop": "https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main"
diff --git a/versioned_docs/version-2.0.0/advanced-topics/transports.md b/versioned_docs/version-2.0.0/advanced-topics/transports.md
new file mode 100644
index 000000000..26d284c69
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/transports.md
@@ -0,0 +1,35 @@
+---
+id: transports
+title: Transports
+description: A transport collects messages from your application and transmits them safely over the network. It ensures that all packets arrive and in order, if needed.
+---
+
+Unity Netcode for GameObjects (Netcode) uses Unity Transport by default and supports UNet Transport (deprecated) up to Unity 2022.2 version.
+
+## So what is a transport layer?
+
+The transport layer establishes communication between your application and different hosts in a network.
+
+A transport layer can provide:
+* *Connection-oriented communication* to ensure a robust connection before exchanging data with a handshake protocol.
+* *Maintain order delivery* for your packets to fix any discrepancies from the network layer in case of packet drops or device interruption.
+* *Ensure data integrity* by requesting retransmission of missing or corrupted data through using checksums.
+* *Control the data flow* in a network connection to avoid buffer overflow or underflow--causing unnecessary network performance issues.
+* *Manage network congestion* by mediating flow rates and node overloads.
+* *Adjust data streams* to transmit as byte streams or packets.
+
+## Unity Transport package
+
+Netcode's default transport Unity Transport is an entire transport layer that you can use to add multiplayer and network features to your project with or without Netcode. See the Transport [documentation](../../../transport/current/about) for more information and how to [install](../../../transport/current/install).
+
+## Unity's UNet Transport Layer API
+
+UNet is a deprecated solution that is no longer supported after Unity 2022.2. Unity Transport Package is the default transport for Netcode for GameObjects. We recommend transitioning to Unity Transport as soon as possible.
+
+### Community Transports or Writing Your Own
+
+You can use any of the community contributed custom transport implementations or write your own.
+
+The community transports are interchangeable transport layers for Netcode and can be installed with the Unity Package Manager. After installation, the transport package will appear in the **Select Transport** dropdown of the `NetworkManager`. Check out the [Netcode community contributed transports](https://github.com/Unity-Technologies/multiplayer-community-contributions/tree/main/Transports) for more information.
+
+To start writing your own and contributing to the community, check out the [Netcode community contribution repository](https://github.com/Unity-Technologies/multiplayer-community-contributions) for starting points and how to add your content.
diff --git a/versioned_docs/version-2.0.0/advanced-topics/ways-to-synchronize.md b/versioned_docs/version-2.0.0/advanced-topics/ways-to-synchronize.md
new file mode 100644
index 000000000..294218868
--- /dev/null
+++ b/versioned_docs/version-2.0.0/advanced-topics/ways-to-synchronize.md
@@ -0,0 +1,48 @@
+---
+id: ways-synchronize
+title: Synchronizing states and events
+---
+
+Netcode for GameObjects has three options for synchronizing game states and events:
+
+- Messaging system
+ - [Remote procedure calls (RPCs)](message-system/rpc.md)
+ - [Custom messages](message-system/custom-messages.md)
+- [NetworkVariables](../basics/networkvariable.md)
+ - Handled by the internal messaging system
+
+While each of these options can be used to synchronize states or events, they all have specific use cases and limitations.
+
+## Messaging system
+
+The Netcode for GameObjects messaging system allows you to send and receive messages or events. The system supports the serialization of most primitive value `type`s as well as any classes and/or structures that implement the `INetworkSerializable` interface.
+
+### Remote procedure calls (RPCs)
+
+RPCs are a way of sending an event notification as well as a way of handling direct communication between a server and a client, or between clients and the [distributed authority service](../terms-concepts/distributed-authority.md). This is sometimes useful when the ownership scope of the `NetworkBehavior`, that the remote procedure call is declared within, belongs to the server but you still want one or more clients to be able to communicate with the associated NetworkObject.
+
+Usage examples:
+
+- An RPC with `SendTo.Server` can be used by a client to notify the server that the player is trying to use a world object (such as a door or vehicle).
+- An RPC with `SendTo.SpecifiedInParams` can be used by a server to notify a specific client of a special reconnection key or some other player-specific information that doesn't require its state to be synchronized with all current and any future late-joining client(s).
+
+There are many RPC methods, as outlined on the [RPC page](message-system/rpc.md#rpc-targets). The most commonly used are:
+
+- `Rpc(SendTo.Server)`: A remote procedure call received by and executed on the server side.
+- `Rpc(SendTo.NotServer)`: A remote procedure call received by and executed on the client side. Note that this does NOT execute on the host, as the host is also the server.
+- `Rpc(SendTo.ClientsAndHost)`: A remote procedure call received by and executed on the client side. If the server is running in host mode, this RPC will also be executed on the server (the host client).
+- `Rpc(SendTo.SpecifiedInParams)`: A remote procedure call that will be sent to a list of client IDs provided as parameters at runtime. By default, other `SendTo` values cannot have any client IDs passed to them to change where they are being sent, but this can also be changed by passing `AllowTargetOverride = true` to the `Rpc` attribute.
+
+RPCs have no limitations on who can send them: the server can invoke an RPC with `SendTo.Server`, a client can invoke an RPC with `SendTo.NotServer`, and so on. If an RPC is invoked in a way that would cause it to be received by the same process that invoked it, it will be executed immediately in that process by default. Passing `DeferOverride = true` to the `Rpc` attribute will change this behavior and the RPC will be invoked at the start of the next frame.
+
+Refer to the [RPC page](../advanced-topics/message-system/rpc.md) for more details.
+
+### Custom messages
+
+Custom messages provide you with the ability to create your own message type. Refer to the [custom messages page](../advanced-topics/message-system/custom-messages.md) for more details.
+
+## NetworkVariables
+
+A NetworkVariable is most commonly used to synchronize state between both connected and late-joining clients. The `NetworkVariable` system only supports non-nullable value `type`s, but also provides support for `INetworkSerializable` implementations as well. You can create your own `NetworkVariable` class by deriving from the `NetworkVariableBase` abstract class. If you want something to always be synchronized with current and late-joining clients, then it's likely a good `NetworkVariable` candidate.
+
+Refer to the [NetworkVariable page](../basics/networkvariable.md) for more details.
diff --git a/versioned_docs/version-2.0.0/basics/connection-approval.md b/versioned_docs/version-2.0.0/basics/connection-approval.md
new file mode 100644
index 000000000..0e2bee126
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/connection-approval.md
@@ -0,0 +1,235 @@
+---
+id: connection-approval
+title: Connection approval
+---
+
+Connection approval allows you to decide for every new client connection attempt whether to allow or deny the client to connect.
+
+You can also send additional payload data via connection approval to initialize the client. For instance you can use this data to have a client specify a custom player Prefab (see example below).
+
+You have to enable ConnectionApproval in the NetworkManager Inspector or by setting `NetworkManager.NetworkConfig.ConnectionApproval = true` in a script before starting the host/server. If connection approval is not enabled, the `NetworkManager.ConnectionApprovalCallback` is not invoked.
+
+In both cases clients also have to pass internal authentication, to confirm that their NetworkConfig matches that of the server.
+
+## Server-side connection approval example
+
+```csharp
+using Unity.Netcode;
+
+private void Setup()
+{
+ NetworkManager.Singleton.ConnectionApprovalCallback = ApprovalCheck;
+ NetworkManager.Singleton.StartHost();
+}
+
+private void ApprovalCheck(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response)
+{
+ // The client identifier to be authenticated
+ var clientId = request.ClientNetworkId;
+
+ // Additional connection data defined by user code
+ var connectionData = request.Payload;
+
+ // Your approval logic determines the following values
+ response.Approved = true;
+ response.CreatePlayerObject = true;
+
+ // The Prefab hash value of the NetworkPrefab, if null the default NetworkManager player Prefab is used
+ response.PlayerPrefabHash = null;
+
+ // Position to spawn the player object (if null it uses default of Vector3.zero)
+ response.Position = Vector3.zero;
+
+ // Rotation to spawn the player object (if null it uses the default of Quaternion.identity)
+ response.Rotation = Quaternion.identity;
+
+ // If response.Approved is false, you can provide a message that explains the reason why via ConnectionApprovalResponse.Reason
+ // On the client-side, NetworkManager.DisconnectReason will be populated with this message via DisconnectReasonMessage
+ response.Reason = "Some reason for not approving the client";
+
+ // If additional approval steps are needed, set this to true until the additional steps are complete
+ // once it transitions from true to false the connection approval response will be processed.
+ response.Pending = false;
+}
+```
+
+## `NetworkManager.ConnectionApprovalRequest`
+
+This class represents the client-to-server request which has:
+
+- **ClientNetworkId**: the connecting client identifier
+- **Payload**: any additional user-defined connection data
+
+## `NetworkManager.ConnectionApprovalResponse`
+
+This is how the connection approval response is formed by server-side specific user code in the handler assigned to `NetworkManager.ConnectionApprovalCallback`. On the server side, this class has all the connection approval response information required to either allow or reject a player attempting to connect. It also has the following properties:
+
+- **Approved**: When `true`, the player is approved. When `false`, the player is denied.
+- **CreatePlayerObject**: When `true`, the server spawns a player Prefab for the connecting client. When `false`, the connecting client will have no player Prefab spawned.
+- **PlayerPrefabHash**: The type of player Prefab to use for the authorized player (if this is `null`, it uses the default NetworkManager-defined player Prefab)
+- **Position** and **Rotation**: The position and rotation of the player when spawned.
+- **Pending**: Provides the ability to mark the approval as pending to delay the authorization until other user-specific code finishes the approval process.
+- **Reason**: If `Approved` is `false`, you can populate this with a string-based message (or JSON) to send the reason the client wasn't approved.
+
+In earlier versions of Netcode for GameObjects, you had to provide a callback to invoke within the connection approval handler method. It's now only necessary to set the appropriate properties of the `NetworkManager.ConnectionApprovalResponse` class. Part of this update allows you to set your `ConnectionApprovalResponse` to `Pending`, providing extra time to process any other tasks involved with the player approval process.
+
+## Sending an approval declined reason (`NetworkManager.ConnectionApprovalResponse.Reason`)
+
+If you need to deny a player from connecting for any reason (such as if they reached the maximum number of connections or provided an invalid authorization), the `NetworkManager.ConnectionApprovalResponse` structure provides you with the optional `NetworkManager.ConnectionApprovalResponse.Reason` property.
+
+When `NetworkManager.ConnectionApprovalResponse.Approved` is false and `NetworkManager.ConnectionApprovalResponse.Reason` is populated with the reason for denying the player's request to connect, the server sends the client a `DisconnectReasonMessage`. Upon the client side receiving the `DisconnectReasonMessage`, the `NetworkManager.DisconnectReason` property populates with the `NetworkManager.ConnectionApprovalResponse.Reason` message. The example below shows how this works:
+
+
+```csharp
+using UnityEngine;
+using Unity.Netcode;
+
+///
+/// Connection Approval Handler Component
+///
+///
+/// This should be placed on the same GameObject as the NetworkManager.
+/// It automatically declines the client connection for example purposes.
+///
+public class ConnectionApprovalHandler : MonoBehaviour
+{
+ private NetworkManager m_NetworkManager;
+
+ private void Start()
+ {
+ m_NetworkManager = GetComponent();
+ if (m_NetworkManager != null)
+ {
+ m_NetworkManager.OnClientDisconnectCallback += OnClientDisconnectCallback;
+ m_NetworkManager.ConnectionApprovalCallback = ApprovalCheck;
+ }
+ }
+
+ private void ApprovalCheck(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response)
+ {
+ response.Approved = false;
+ response.Reason = "Testing the declined approval message";
+ }
+
+ private void OnClientDisconnectCallback(ulong obj)
+ {
+ if (!m_NetworkManager.IsServer && m_NetworkManager.DisconnectReason != string.Empty)
+ {
+ Debug.Log($"Approval Declined Reason: {m_NetworkManager.DisconnectReason}");
+ }
+ }
+}
+```
+
+
+## Connection data (`NetworkManager.ConnectionApprovalRequest.Payload`)
+
+The `ConnectionApprovalRequest.Payload` parameter takes any custom data the client should send to the server. Usually, this data is some sort of ticket, room password, or similar that helps the server decide whether to approve a connection. The `connectionData` is specified on the client-side in the `NetworkingConfig` (supplied when connecting). The `NetworkConfig.ConnectionData`, automatically sent with the connection request message to the server, should be populated on the client-side before calling `NetworkManager.StartClient`.
+
+Example:
+
+```csharp
+using Unity.Netcode;
+
+NetworkManager.Singleton.NetworkConfig.ConnectionData = System.Text.Encoding.ASCII.GetBytes("room password");
+NetworkManager.Singleton.StartClient();
+```
+
+The `Payload`, defined by the client-side `NetworkConfig.ConnectionData`, is sent to the server as part of the `Payload` of the connection request message that's used on the server-side to decide if the client is approved or not. The connection data is optional and you can use the connection approval process to assign player's unique Prefabs and facilitates the ability to spawn players at various locations (without requiring the client to send any form of connection data).
+
+## Timeout
+
+Netcode for GameObjects uses a callback system to allow for external validation. For example, you might have an authentication ticket sent as the `ConnectionData` that you want to validate against the owning servers. This can take some time, so you want to set the `NetworkManager.ConnectionApprovalResponse.Pending` to true while the server (or other third-party authentication service) validates the incoming ticket.
+
+If the third-party authentication process takes longer than the time specified by the `NetworkConfig.ClientConnectionBufferTimeout`, then the connection is dropped. The timer for this starts when the server is notified of the new inbound client connection. You can set the **Client Connection Buffer Timeout** value via the `NetworkManager` in the Inspector view or with the `NetworkManager.NetworkConfig.ClientConnectionBufferTimeout` property.
+
+## Security
+
+If you enable connection approval, the server silently ignores any messages sent before a connection is set up.
+
+### Connection data security
+
+:::warning
+
+Netcode for GameObjects doesn't encrypt or authenticate any of the raw information sent over connection approval. To prevent man-in-the-middle attacks, you should avoid sending authentication tokens (such as authentication tickets or user passwords) over connection approval without additional safety precautions.
+
+The examples on this page illustrate how Netcode for GameObjects doesn't protect any connection data, and don't show how to incorporate encryption, authentication, or some other method of data security.
+
+:::
+
+## Changing the player Prefab
+
+There might be times when you want to specify an alternate player Prefab to use for a player connecting. The connection approval process provides you with the ability to do this.
+
+### Modify or create an in-scene placed connection approval component
+
+```csharp
+ public class ClientConnectionHandler : NetworkBehaviour
+ {
+ public List AlternatePlayerPrefabs;
+
+ public void SetClientPlayerPrefab(int index)
+ {
+ if (index > AlternatePlayerPrefabs.Count)
+ {
+ Debug.LogError($"Trying to assign player Prefab index of {index} when there are only {AlternatePlayerPrefabs.Count} entries!");
+ return;
+ }
+ if (NetworkManager.IsListening || IsSpawned)
+ {
+ Debug.LogError("This needs to be set this before connecting!");
+ return;
+ }
+ NetworkManager.NetworkConfig.ConnectionData = System.BitConverter.GetBytes(index);
+ }
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer)
+ {
+ NetworkManager.ConnectionApprovalCallback = ConnectionApprovalCallback;
+ }
+ }
+
+ private void ConnectionApprovalCallback(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response)
+ {
+ var playerPrefabIndex = System.BitConverter.ToInt32(request.Payload);
+ if (AlternatePlayerPrefabs.Count > playerPrefabIndex)
+ {
+ response.PlayerPrefabHash = AlternatePlayerPrefabs[playerPrefabIndex];
+ }
+ else
+ {
+ Debug.LogError($"Client provided player Prefab index of {playerPrefabIndex} when there are only {AlternatePlayerPrefabs.Count} entries!");
+ return;
+ }
+ // Continue filling out the response
+ }
+ }
+
+```
+
+The above example creates a list of unsigned integers to store an alternate player Prefab GlobalObjectIdHash values (`AlternatePlayerPrefabs`). For example purposes, this code sample adds a public method that a client can invoke to set their selected player Prefab's index that's relative to `AlternatePlayerPrefabs` (you can do this in some other component). The general idea for this approach is that the client provides the server with the alternate player Prefab index that the player wishes to use.
+
+The server assigns the `ConnectionApprovalCallback` when it spawns the in-scene placed NetworkObject that the `ClientConnectionHandler` is attached to. When the server handles a connection request, it grabs the alternate player Prefab index from the request's `Payload` field and then obtains the GlobalObjectIdHash value from the `AlternatePlayerPrefabs` list and assigns that to the `response.PlayerPrefabHash`.
+
+### Copy the alternate player Prefab's GlobalObjectIdHash value
+
+![Copy-GlobalObjectIdHash](/img/CopyGlobalObjectIdHash.png)
+
+To populate the `AlternatePlayerPrefabs` list:
+
+- Open the scene containing the in-scene placed NetworkObject that the `ConnectionApprovalCallback` is attached to.
+- Find each alternate player Prefab you wish to add to the list, select the Prefab (but don't open it), and copy the **GlobalObjectIdHash** value by right-clicking and selecting **Copy**.
+- Paste the copied **GlobalObjectIdHash** value into a new list item entry in the **AlternatePlayerPrefabs** list.
+
+### Assign client's selected player Prefab index
+
+This part is up to your project's design. The example includes a method that clients can invoke, but that also requires the client to have that scene loaded. You can choose to have a ScriptableObject that has the list of alternate player Prefab GlobalObjectIdHash values and share that between components (this would require you to change the `AlternatePlayerPrefabs` to a reference of the `ScriptableObject`). The general idea is to have the client populate the `NetworkConfig.ConnectionData` before starting.
+
+:::tip
+An alternate way to handle this is by using a generic player Prefab that's used as the parent to the actual player's character and allowing the player to select their player once they're connected. This involves dynamically spawning the player's selected character with the client as the owner and parenting that under the player's generic player Prefab instance.
+Suggested Reading:
+[NetworkObject Parenting](../advanced-topics/networkobject-parenting.md)
+[Session Management](../advanced-topics/session-management.md)
+:::
diff --git a/versioned_docs/version-2.0.0/basics/custom-networkvariables.md b/versioned_docs/version-2.0.0/basics/custom-networkvariables.md
new file mode 100644
index 000000000..0226ecc09
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/custom-networkvariables.md
@@ -0,0 +1,251 @@
+---
+id: custom-networkvariables
+title: Custom NetworkVariables
+---
+
+In addition to the standard [`NetworkVariable`s](networkvariable.md) available in Netcode for GameObjects, you can also create custom `NetworkVariable`s for advanced implementations. The `NetworkVariable` and `NetworkList` classes were created as `NetworkVariableBase` class implementation examples. While the `NetworkVariable` class is considered production ready, you might run into scenarios where you have a more advanced implementation in mind. In this case, you can create your own custom implementation.
+
+To create your own `NetworkVariableBase`-derived container, you should:
+
+1. Create a class deriving from `NetworkVariableBase`.
+1. Override the following methods:
+ - `void WriteField(FastBufferWriter writer)`
+ - `void ReadField(FastBufferReader reader)`
+ - `void WriteDelta(FastBufferWriter writer)`
+ - `void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)`
+1. Depending on your custom `NetworkVariableBase` container, you can look at `NetworkVariable` or `NetworkList` to see how those two examples were implemented.
+
+## NetworkVariable serialization
+
+The way you read and write `NetworkVariable`s changes depending on the type you use.
+
+* Known, non-generic types: Use `FastBufferReader.ReadValue` to read from and `FastBufferWriter.WriteValue` to write to the `NetworkVariable` value.
+* Integer types: This type gives you the option to use `BytePacker` and `ByteUnpacker` to compress the `NetworkVariable` value. This process can save bandwidth but adds CPU processing time.
+* Generic types: Use serializers that Unity generates based on types discovered during a compile-time code generation process. This means you need to tell Unity's code generation algorithm which types to generate serializers for. To tell Unity which types to serialize, use the following methods:
+ * Use `GenerateSerializationForTypeAttribute` to serialize hard-coded types.
+ * Use `GenerateSerializationForGenericParameterAttribute` to serialize generic types.
+
+### Serialize a hard-coded type
+
+The following code example uses `GenerateSerializationForTypeAttribute` to generate serialization for a specific hard-coded type:
+
+```csharp
+[GenerateSerializationForType(typeof(Foo))]
+public class MyNetworkVariableTypeUsingFoo : NetworkVariableBase {}
+```
+
+You can call a type that you know the name of with the `FastBufferReader` or `FastBufferWriter` methods. These methods don't work for generic types because the name of the type is unknown.
+
+### Serialize a generic type
+
+The following code example uses `GenerateSerializationForGenericParameterAttribute` to generate serialization for a specific generic parameter in your `NetworkVariable` type:
+
+```csharp
+[GenerateSerializationForGenericParameter(0)]
+public class MyNetworkVariableType : NetworkVariableBase {}
+```
+
+This attribute accepts an integer that indicates which parameter in the type to generate serialization for. This value is 0-indexed, which means that the first type is 0, the second type is 1, and so on.
+
+The following code example places the attribute more than once on one class to generate serialization for multiple types, in this case,`TFirstType` and `TSecondType:
+
+```csharp
+[GenerateSerializationForGenericParameter(0)]
+[GenerateSerializationForGenericParameter(1)]
+public class MyNetworkVariableType : NetworkVariableBase {}
+```
+
+
+The `GenerateSerializationForGenericParameterAttribute` and `GenerateSerializationForTypeAttribute` attributes make Unity's code generation create the following methods:
+
+```csharp
+NetworkVariableSerialization.Write(FastBufferWriter writer, ref T value);
+NetworkVariableSerialization.Read(FastBufferWriter writer, ref T value);
+NetworkVariableSerialization.Duplicate(in T value, ref T duplicatedValue);
+NetworkVariableSerialization.AreEqual(in T a, in T b);
+```
+
+For dynamically-allocated types with a value that isn't `null` (for example, managed types and collections like `NativeArray` and `NativeList`) call `Read` to read the value in the existing object and write data into it directly (in-place). This avoids more allocations.
+
+You can use `AreEqual` to determine if a value is different from the value that `Duplicate` cached. This avoids sending the same value multiple times. You can also use the previous value that `Duplicate` cached to calculate deltas to use in `ReadDelta` and `WriteDelta`.
+
+The type you use must be serializable according to the [support types list above](#supported-types). Each type needs its own serializer instantiated, so this step tells the codegen which types to create serializers for. Unity's code generator assumes that all `NetworkVariable` types exist as fields inside `NetworkBehaviour` types. This means that Unity only inspects fields inside `NetworkBehaviour` types to identify the types to create serializers for.
+
+## Custom NetworkVariable example
+
+This example shows a custom `NetworkVariable` type to help you understand how you might implement such a type. In the current version of Netcode for GameObjects, this example is possible without using a custom `NetworkVariable` type; however, for more complex situations that aren't natively supported, this basic example should help inform you of how to approach the implementation:
+
+ ```csharp
+ /// Using MyCustomNetworkVariable within a NetworkBehaviour
+ public class TestMyCustomNetworkVariable : NetworkBehaviour
+ {
+ public MyCustomNetworkVariable CustomNetworkVariable = new MyCustomNetworkVariable();
+ public MyCustomGenericNetworkVariable CustomGenericNetworkVariable = new MyCustomGenericNetworkVariable();
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ var someData = new SomeData();
+ someData.SomeFloatData = (float)i;
+ someData.SomeIntData = i;
+ someData.SomeListOfValues.Add((ulong)i + 1000000);
+ someData.SomeListOfValues.Add((ulong)i + 2000000);
+ someData.SomeListOfValues.Add((ulong)i + 3000000);
+ CustomNetworkVariable.SomeDataToSynchronize.Add(someData);
+ CustomNetworkVariable.SetDirty(true);
+
+ CustomGenericNetworkVariable.SomeDataToSynchronize.Add(i);
+ CustomGenericNetworkVariable.SetDirty(true);
+ }
+ }
+ }
+ }
+
+ /// Bare minimum example of NetworkVariableBase derived class
+ [Serializable]
+ public class MyCustomNetworkVariable : NetworkVariableBase
+ {
+ /// Managed list of class instances
+ public List SomeDataToSynchronize = new List();
+
+ ///
+ /// Writes the complete state of the variable to the writer
+ ///
+ /// The stream to write the state to
+ public override void WriteField(FastBufferWriter writer)
+ {
+ // Serialize the data we need to synchronize
+ writer.WriteValueSafe(SomeDataToSynchronize.Count);
+ foreach (var dataEntry in SomeDataToSynchronize)
+ {
+ writer.WriteValueSafe(dataEntry.SomeIntData);
+ writer.WriteValueSafe(dataEntry.SomeFloatData);
+ writer.WriteValueSafe(dataEntry.SomeListOfValues.Count);
+ foreach (var valueItem in dataEntry.SomeListOfValues)
+ {
+ writer.WriteValueSafe(valueItem);
+ }
+ }
+ }
+
+ ///
+ /// Reads the complete state from the reader and applies it
+ ///
+ /// The stream to read the state from
+ public override void ReadField(FastBufferReader reader)
+ {
+ // De-Serialize the data being synchronized
+ var itemsToUpdate = (int)0;
+ reader.ReadValueSafe(out itemsToUpdate);
+ SomeDataToSynchronize.Clear();
+ for (int i = 0; i < itemsToUpdate; i++)
+ {
+ var newEntry = new SomeData();
+ reader.ReadValueSafe(out newEntry.SomeIntData);
+ reader.ReadValueSafe(out newEntry.SomeFloatData);
+ var itemsCount = (int)0;
+ var tempValue = (ulong)0;
+ reader.ReadValueSafe(out itemsCount);
+ newEntry.SomeListOfValues.Clear();
+ for (int j = 0; j < itemsCount; j++)
+ {
+ reader.ReadValueSafe(out tempValue);
+ newEntry.SomeListOfValues.Add(tempValue);
+ }
+ SomeDataToSynchronize.Add(newEntry);
+ }
+ }
+
+ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
+ {
+ // Do nothing for this example
+ }
+
+ public override void WriteDelta(FastBufferWriter writer)
+ {
+ // Do nothing for this example
+ }
+ }
+
+ /// Bare minimum example of generic NetworkVariableBase derived class
+ [Serializable]
+ [GenerateSerializationForGenericParameter(0)]
+ public class MyCustomGenericNetworkVariable : NetworkVariableBase
+ {
+ /// Managed list of class instances
+ public List SomeDataToSynchronize = new List();
+
+ ///
+ /// Writes the complete state of the variable to the writer
+ ///
+ /// The stream to write the state to
+ public override void WriteField(FastBufferWriter writer)
+ {
+ // Serialize the data we need to synchronize
+ writer.WriteValueSafe(SomeDataToSynchronize.Count);
+ for (var i = 0; i < SomeDataToSynchronize.Count; ++i)
+ {
+ var dataEntry = SomeDataToSynchronize[i];
+ // NetworkVariableSerialization is used for serializing generic types
+ NetworkVariableSerialization.Write(writer, ref dataEntry);
+ }
+ }
+
+ ///
+ /// Reads the complete state from the reader and applies it
+ ///
+ /// The stream to read the state from
+ public override void ReadField(FastBufferReader reader)
+ {
+ // De-Serialize the data being synchronized
+ var itemsToUpdate = (int)0;
+ reader.ReadValueSafe(out itemsToUpdate);
+ SomeDataToSynchronize.Clear();
+ for (int i = 0; i < itemsToUpdate; i++)
+ {
+ T newEntry = default;
+ // NetworkVariableSerialization is used for serializing generic types
+ NetworkVariableSerialization.Read(reader, ref newEntry);
+ SomeDataToSynchronize.Add(newEntry);
+ }
+ }
+
+ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
+ {
+ // Do nothing for this example
+ }
+
+ public override void WriteDelta(FastBufferWriter writer)
+ {
+ // Do nothing for this example
+ }
+ }
+
+ /// Example managed class used as the item type in the
+ /// MyCustomNetworkVariable.SomeDataToSynchronize list
+ [Serializable]
+ public class SomeData
+ {
+ public int SomeIntData = default;
+ public float SomeFloatData = default;
+ public List SomeListOfValues = new List();
+ }
+ ```
+
+While the above example isn't the recommended way to synchronize a list where the number or order of elements in the list often changes, it's an example of how you can define your own rules using `NetworkVariableBase`.
+
+You can test the code above by:
+- Using the above code with a project that includes Netcode for GameObjects v1.0 (or higher).
+- Adding the `TestMyCustomNetworkVariable` component to an in-scene placed NetworkObject.
+- Creating a stand alone build and running that as a host or server.
+- Running the same scene within the Editor and connecting as a client.
+ - Once connected, you can then select the `GameObject` with the attached NetworkObject and `TestMyCustomNetworkVariable` components so it appears in the inspector view. There you can verify the `TestMyCustomNetworkVariable.CustomNetworkVariable` property was synchronized with the client (like in the screenshot below):
+ ![ScreenShot](/img/MyCustomNetworkVariableInspectorView.png)
+
+:::caution
+You can't nest `NetworkVariable`s inside other `NetworkVariable` classes. This is because Netcode for GameObjects performs a code generation step to define serialization callbacks for each type it finds in a `NetworkVariable`. The code generation step looks for variables as fields of `NetworkBehaviour` types; it misses any `NetworkVariable`s declared anywhere else.
+
+Instead of nesting `NetworkVariable`s inside other `NetworkVariable` classes, declare `NetworkVariable` or `NetworkList` properties within the same `NetworkBehaviour` within which you have declared your custom `NetworkVariableBase` implementation.
+:::
diff --git a/versioned_docs/version-2.0.0/basics/deferred-despawning.md b/versioned_docs/version-2.0.0/basics/deferred-despawning.md
new file mode 100644
index 000000000..35d639704
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/deferred-despawning.md
@@ -0,0 +1,233 @@
+---
+id: deferred-despawning
+title: Deferred despawning
+---
+
+:::info Distributed authority only
+
+Deferred despawning is only available for games using a [distributed authority topology](../terms-concepts/distributed-authority.md).
+
+:::
+
+In addition to the visual latency issues described on the [spawning synchronization page](spawning-synchronization.md), networked games also experience latency issues when despawning objects. In [client-server](../terms-concepts/client-server.md) contexts, these problems are typically addressed using client prediction models, but in a distributed authority context there is a simpler alternative solution: deferred despawning.
+
+## Why deferred despawning
+
+Issues with despawning occur when objects are despawned too early. The client that owns the projectile detects a collision, triggers any local animations, and despawns the projectile locally. For the player being hit, they see the projectile despawn before it reaches them and animations can appear to trigger at the wrong point in time. This can be seen in the diagram below.
+
+![Without deferred despawning](/img/without-deferred-despawning.jpg)
+
+Deferred despawning allows you to add a tick-based delay to a NetworkObject prior to despawning it locally. The deferred despawn tick value is then added to the `DestroyObjectMessage` so that other clients, upon receiving the message, defer processing the destroy message until the specified tick value has been reached. The results of this deferred despawn adjustment can be seen in the diagram below.
+
+![With deferred despawning](/img/with-deferred-despawning.jpg)
+
+Deferred despawning allows non-owner instances of an object to complete their interpolation towards the last transform state update before despawning the object. Even though non-owner clients can be visually latent by several network ticks behind the authority, all clients end up with the same visual experience since NetworkTransform deltas are tick synchronized.
+
+## Implementing deferred despawning
+
+Implementing deferred despawning is a three-step process, as described in the diagram below.
+
+![Implementing deferred despawning](/img/implementing-deferred-despawning.jpg)
+
+The process above is broken down into two steps that are performed on the authority instance, and one step performed on the non-authority instance(s).
+
+|Authority instance|Non-authority instance(s)|
+|---|---|
+|1. Invoke the `NetworkObject.DeferDespawn` method while providing the number of ticks to offset despawning by on non-authority instance(s), relative to the local client's current known network tick. 2. If overridden, handle any changes to state (i.e. NetworkVariables) when `NetworkBehaviour.OnDeferringDespawn` is invoked.|1. Use any updated states to synchronize the visual portion of a deferred despawn (for example, starting a particle system to represent the point of impact).|
+
+### Deferred despawning example
+
+Below is a basic example demonstrating how deferred despawning can be used to visually synchronize a projectile's impact with explosion effects:
+
+```
+public class ExplodingProjectile : NetworkBehaviour
+{
+ // The explosion network prefab
+ public GameObject ExplosionPrefab;
+ public int DespawnTickOffset = 4;
+ private ExplosionFx m_SpawnedExplosion;
+
+
+ // Permission are always owner write and everyone read in distributed authority
+ // Authority assigns this value after spawning the ExplosionFx within the overridden
+ // OnDeferringDespawn method prior to the local ExplodingPrrojectile is despawned
+ // locally.
+ private NetworkVariable m_ExplosionFx = new NetworkVariable();
+
+
+ public override void OnNetworkSpawn()
+ {
+ if (!HasAuthority)
+ {
+ m_ExplosionFx.OnValueChanged += OnExplosionFxChanged;
+ }
+
+
+ base.OnNetworkSpawn();
+ }
+
+
+ private void OnCollisionEnter(Collision collision)
+ {
+ if (!IsSpawned || !HasAuthority)
+ {
+ return;
+ }
+ // Typically you would want to check what you hit
+ // to make sure you want to "explode" the projectile
+ // first. This example assumes that a check was performed.
+
+
+ // Start with the projectile's position
+ var explodePoint = transform.position;
+ if (collision.contacts.Length > 0 )
+ {
+ // Example purposes, just use the first contact
+ explodePoint = collision.contacts[0].point;
+ }
+ HandleExplosion(explodePoint);
+ }
+
+
+ private void HandleExplosion(Vector3 explodePoint)
+ {
+ // Example purposes only, we recommend using object pools
+ // using an INetworkPrefabInstanceHandler implementation
+ // and registering that with the NetworkManager.PrefabHandler.
+ var instance = Instantiate(ExplosionPrefab);
+
+ // position the explosion
+ instance.transform.position = explodePoint;
+
+
+ // Assign this for later use (example purposes)
+ m_SpawnedExplosion = instance.GetComponent();
+
+ // Spawn the explosion
+ var instanceObj = instance.GetComponent();
+ instanceObj.Spawn();
+
+
+ // Defer the despawning of the projectile instance
+ NetworkObject.DeferDespawn(DespawnTickOffset);
+
+ // The local instance should be despawned at this point
+ }
+
+
+ ///
+ /// Invoked on the authority side when it is deferring the
+ /// despawning of the NetworkObject.
+ ///
+ ///
+ /// This is a good time to set any NetworkVariable states as
+ /// they will be sent to clients prior to the defer despawn message.
+ ///
+ /// the final future network tick
+ /// non-authority instances will despawn the clone instance.
+ public override void OnDeferringDespawn(int despawnTick)
+ {
+ // This lets the non-authority instances know what ExplosionFx instance is
+ // associated with this NetworkObject.
+ m_ExplosionFx = new NetworkVariable(m_SpawnedExplosion);
+
+
+ // Apply any other state updates here
+
+
+ base.OnDeferringDespawn(despawnTick);
+ }
+
+
+ ///
+ /// Non-authority registers for this and acquires the ExplosionFX
+ /// of the network prefab spawned.
+ ///
+ private void OnExplosionFxChanged(NetworkBehaviourReference previous, NetworkBehaviourReference current)
+ {
+ // If possible, get the ExplosionFx component
+ current.TryGet(out m_SpawnedExplosion);
+ }
+
+
+ public override void OnNetworkDespawn()
+ {
+ // When non-authority instances finally despawn,
+ // the explosion FX will begin playing.
+ if (!HasAuthority)
+ {
+ if (m_SpawnedExplosion)
+ {
+ m_SpawnedExplosion.SetParticlePlayingState(true);
+ }
+ m_ExplosionFx.OnValueChanged -= OnExplosionFxChanged;
+ }
+ base.OnNetworkDespawn();
+ }
+}
+```
+
+The pseudo script above excludes the motion of the projectile, but makes the assumption that authority is moving the projectile and that when the projectile impacts a valid object, the `OnCollisionEnter` method will be invoked.
+
+Authority instance|Non-authority instance(s)|
+|---|---|
+|1. Move until collision (excluded from the above example) 2. Upon collision: instantiate ExplosionFX, position ExplosionFX, acquire the ExplosionFX component, spawn the ExplosionFX, defer despawning the projectile 3. When deferring despawning the projectile, assign the NetworkBehaviourReference to the ExplosionFX 4. Despawn locally (happens automatically at end of the DeferDespawn)|1. When spawned, register changes to the m_ExplosionFX NetworkVariable 2. Continue to interpolate towards last updated position (handled by NetworkTransform) 3. When m_ExplosionFX NetworkVariable changes, assign the local m_SpawnExplosion ExplosionFX component of the explosion associated with the current projectile instance (to be used when despawned) 4.When despawned, start the ExplosionFX particle system via m_SpawnExplosion|
+
+The non-authority instance still spawns the ExplosionFX NetworkObject at the same relative time frame as the authority, however it doesn't start its particle system until the local non-authority projectile instance is despawned. Since the projectile has had its despawn deferred until a future network tick, the non-authority instance interpolates up to its last updated position from the authority side and then shortly (in milliseconds) after is despawned and the explosion particle system started.
+
+:::info Example purposes only
+
+The spawning explosion FX example above is only for example purposes and would be less bandwidth and processor intensive if you used a local particle FX pool that you pull from and began playing on both the authority and non-authority sides when the object in question is despawned. The same deferred despawn principles would be used without the need to spawn an additional object. However, providing the spawned explosion example also covers other scenarios where spawning is required.
+
+:::
+
+For example purposes, the below script is all that you would need to control starting and stopping the explosion particle system:
+
+```
+public class ExplosionFx : NetworkBehaviour
+{
+ public ParticleSystem ParticleSystem;
+
+
+ private void OnEnable()
+ {
+ // In the event a pool is used, it is always good to
+ // make sure the particle system is not playing
+ SetParticlePlayingState();
+ }
+
+
+ public override void OnNetworkSpawn()
+ {
+ // Authority starts the particle system (locally) when spawned
+ if (HasAuthority)
+ {
+ SetParticlePlayingState(true);
+ }
+ base.OnNetworkSpawn();
+ }
+
+
+ ///
+ /// Used to start/stop the particle system
+ /// Non-Authority starts this when its associated projectile
+ /// is finally despawned
+ ///
+ public void SetParticlePlayingState(bool isPlaying = false)
+ {
+ if (ParticleSystem)
+ {
+ if(isPlaying)
+ {
+ ParticleSystem.Play();
+ }
+ else
+ {
+ ParticleSystem.Stop();
+ }
+ }
+ }
+}
+```
+
+Note that the authority automatically starts the particle system upon being spawned. Non-authority instances are started by their paired projectile when despawned at the end of the deferred despawn defined network tick.
diff --git a/versioned_docs/version-2.0.0/basics/logging.md b/versioned_docs/version-2.0.0/basics/logging.md
new file mode 100644
index 000000000..97fb23eb0
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/logging.md
@@ -0,0 +1,25 @@
+---
+id: logging
+title: Logging
+sidebar_label: Logging
+---
+
+ Netcode for GameObjects (Netcode) has built in support for logging which can be great for working with development builds, playtesting and more. If used in production, it should be noted that logs can be forged and do take up some bandwidth depending on the log sizes.
+
+The logging functionality can be accessed with the NetworkLog API. If a `NetworkLog` is called on the server, the log won't be sent across the network but will instead just be logged locally with the `ServerClientId` as the sender. An example log would be `[MLAPI_SERVER Sender=0] Hello World!`. If the NetworkLog API is instead accessed from a client, it will first log locally on the sending client but will also be logged on the server.
+
+## Examples
+
+```csharp
+if (IsServer)
+{
+ // This won't send any network packets but will log it locally on the server
+ NetworkLog.LogInfoServer("Hello World!");
+}
+
+if (IsClient)
+{
+ // This will log locally and send the log to the server to be logged there aswell
+ NetworkLog.LogInfoServer("Hello World!");
+}
+```
\ No newline at end of file
diff --git a/versioned_docs/version-2.0.0/basics/maxnumberplayers.md b/versioned_docs/version-2.0.0/basics/maxnumberplayers.md
new file mode 100644
index 000000000..94188169a
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/maxnumberplayers.md
@@ -0,0 +1,35 @@
+---
+id: max-players
+title: Limiting the maximum number of players
+created: 2023-01-24T18:08:36-06:00
+updated: 2023-01-24T18:59:55-06:00
+---
+
+Netcode for GameObjects provides a way to customize the [connection approval process](connection-approval.md) that can reject incoming connections based on any number of user-specific reasons.
+
+Boss Room provides one example of how to handle limiting the number of players through the connection approval process:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ConnectionManagement/ConnectionState/HostingState.cs
+
+```
+
+The code below shows an example of an over-capacity check that would prevent more than a certain pre-defined number of players from connecting.
+
+
+```csharp
+if( m_Portal.NetManager.ConnectedClientsIds.Count >= CharSelectData.k_MaxLobbyPlayers )
+{
+ return ConnectStatus.ServerFull;
+}
+```
+
+:::tip
+
+In connection approval delegate, Netcode for GameObjects doesn't support sending anything more than a Boolean back.
+
+Boss Room shows a way to offer meaningful error code to the client by invoking a client RPC in the same channel that Netcode for GameObjects uses for its connection callback.
+
+:::
+
+When using Relay, ensure the maximum number of peer connections allowed by the host satisfies the logic implemented in the connection approval delegate.
diff --git a/versioned_docs/version-2.0.0/basics/networkbehaviour-synchronize.md b/versioned_docs/version-2.0.0/basics/networkbehaviour-synchronize.md
new file mode 100644
index 000000000..f37141e95
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/networkbehaviour-synchronize.md
@@ -0,0 +1,179 @@
+---
+id: networkbehavior-synchronize
+title: NetworkBehaviour synchronization
+---
+
+[`NetworkBehaviour`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html) is an abstract class that derives from [`MonoBehaviour`](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html) and is primarily used to create unique netcode or game logic. To replicate any netcode-aware properties or send and receive RPCs, a [GameObject](https://docs.unity3d.com/Manual/GameObjects.html) must have a [NetworkObject](networkobject.md) component and at least one `NetworkBehaviour` component.
+
+You can use `NetworkBehaviour`s to synchronize settings before, during, and after spawning NetworkObjects.
+
+For more information about spawning and despawning `NetworkBehaviour`s, refer to the [NetworkBehaviour spawning and despawning page](networkbehaviour.md).
+
+## Pre-spawn, spawn, post-spawn and synchronization
+
+The NetworkObject spawn process can become complicated when there are multiple `NetworkBehaviour` components attached to the same GameObject. Additionally, there can be times where you want to be able to handle pre- and post-spawn oriented tasks.
+
+- Pre-spawn example: Instantiating a `NetworkVariable` with owner write permissions and assigning a value to that `NetworkVariable` on the server or host side.
+- Spawn example: Applying a local value or setting that may be used during post spawn by another local `NetworkBehaviour` component.
+- Post-spawn example: Accessing a `NetworkVariable` or other property that is set during the spawn process.
+
+Below are the available virtual methods you can override within a `NetworkBehaviour`-derived class:
+
+Method | Scope | Use case | Context
+---------------------------- | ------------------------ | ------------------------------------------------------ | -------------
+`OnNetworkPreSpawn` | NetworkObject | Pre-spawn initialization | Client and server
+`OnNetworkSpawn` | NetworkObject | During spawn initialization | Client and server
+`OnNetworkPostSpawn` | NetworkObject | Post-spawn actions | Client and server
+`OnNetworkSessionSynchronized` | All NetworkObjects | New client finished synchronizing | Client-side only
+`OnInSceneObjectsSpawned` | In-scene NetworkObjects | New client finished synchronizing or a scene is loaded | Client and server
+
+
+`OnNetworkSessionSynchronized` and `OnInSceneObjectsSpawned` are two special case convenience methods:
+
+- `OnNetworkSessionSynchronized`: When scene management is enabled and a new client joins a session, the client starts synchronizing with the network session. During this period of time the client might need to load additional scenes as well as instantiate and spawn NetworkObjects. When a client has finished loading all scenes and all NetworkObjects are spawned, this method gets invoked on all `NetworkBehaviour`s associated with any spawned NetworkObjects. This can be useful if you want to write scripts that might require access to other spawned NetworkObjects and/or their `NetworkBehaviour` components. When this method is invoked, you are assured that everything is spawned and ready to be accessed and/or to have messages sent from them. Remember that this method is only invoked on clients and isn't invoked on a server or host.
+- `OnInSceneObjectsSpawned`: This method ensures that any in-scene placed NetworkObjects have been spawned prior to a specific set of scripts being invoked. This method is invoked on in-scene placed NetworkObjects when:
+ - A server or host first starts up after all in-scene placed NetworkObjects in the currently loaded scene(s) have been spawned.
+ - A client finishes synchronizing.
+ - On the server and client side after a scene has been loaded and all newly instantiated in-scene placed NetworkObjects have been spawned.
+
+### Pre-spawn synchronization with `OnSynchronize`
+
+There can be scenarios where you need to include additional configuration data or use a `NetworkBehaviour` to configure some non-netcode related component before a NetworkObject is spawned. This can be particularly critical if you want specific settings applied before `NetworkBehaviour.OnNetworkSpawn` is invoked. When a client is synchronizing with an existing network session, this can become problematic as messaging requires a client to be fully synchronized before you know "it is safe" to send the message, and even if you send a message there is latency involved that might require additional specialized code to compensate for.
+
+`NetworkBehaviour.OnSynchronize` allows you to write and read custom serialized data during the NetworkObject serialization process.
+
+There are two cases where NetworkObject synchronization occurs:
+
+- When dynamically spawning a NetworkObject.
+- When a client is being synchronized after connection approval (that is, full synchronization of the NetworkObjects and scenes).
+
+:::info
+
+The [`INetworkSerializable` interface](../advanced-topics/serialization/inetworkserializable.md) is similar to `NetworkBehaviour.OnSynchronize`, and can be a useful reference point to understand first.
+:::
+
+#### Order of operations when dynamically spawning
+
+The following provides you with an outline of the order of operations that occur during NetworkObject serialization when dynamically spawned.
+
+Server-side:
+
+- `GameObject` with NetworkObject component is instantiated.
+- The `NetworkObject` is spawned.
+ - For each associated `NetworkBehaviour` component, `NetworkBehaviour.OnNetworkSpawn` is invoked.
+- The `CreateObjectMessage` is generated.
+ - NetworkObject state is serialized.
+ - `NetworkVariable` state is serialized.
+ - `NetworkBehaviour.OnSynchronize` is invoked for each `NetworkBehaviour` component.
+ - If this method isn't overridden then nothing is written to the serialization buffer.
+- The `CreateObjectMessage` is sent to all clients that are observers of the NetworkObject.
+
+
+Client-side:
+
+- The `CreateObjectMessage` is received.
+ - `GameObject` with NetworkObject component is instantiated.
+ - `NetworkVariable` state is deserialized and applied.
+ - `NetworkBehaviour.OnSynchronize` is invoked for each `NetworkBehaviour` component.
+ - If this method isn't overridden then nothing is read from the serialization buffer.
+- The `NetworkObject` is spawned.
+ - For each associated `NetworkBehaviour` component, `NetworkBehaviour.OnNetworkSpawn` is invoked.
+
+#### Order of operations during full (late-join) client synchronization
+
+Server-side:
+- The `SceneEventMessage` of type `SceneEventType.Synchronize` is created.
+ - All spawned `NetworkObjects` that are visible to the client, already instantiated, and spawned are serialized.
+ - `NetworkObject` state is serialized.
+ - `NetworkVariable` state is serialized.
+ - `NetworkBehaviour.OnSynchronize` is invoked for each `NetworkBehaviour` component.
+ - If this method isn't overridden then nothing is written to the serialization buffer.
+- The `SceneEventMessage` is sent to the client.
+
+Client-side:
+- The `SceneEventMessage` of type `SceneEventType.Synchronize` is received.
+- Scene information is deserialized and scenes are loaded (if not already).
+ - In-scene placed NetworkObjects are instantiated when a scene is loaded.
+- All NetworkObject-oriented synchronization information is deserialized.
+ - Dynamically spawned NetworkObjects are instantiated and state is synchronized.
+ - For each NetworkObject instance:
+ - `NetworkVariable` state is deserialized and applied.
+ - `NetworkBehaviour.OnSynchronize` is invoked.
+ - If this method isn't overridden then nothing is read from the serialization buffer.
+ - The `NetworkObject` is spawned.
+ - For each associated `NetworkBehaviour` component, `NetworkBehaviour.OnNetworkSpawn` is invoked.
+
+### `OnSynchronize` example
+
+Understanding when to use `OnSynchronize` is key to making the most of the method. `NetworkVariable`s can be useful to synchronize state, but they're only updated every network tick and you might have some form of state that needs to be updated when it happens and not several frames later, so you decide to use RPCs. However, this becomes an issue when you want to synchronize late-joining clients as there is no way to synchronize late-joining clients based on RPC activity over the duration of a network session. This is one of many possible reasons one might want to use `NetworkBehaviour.OnSynchronize`.
+
+The following example uses `NetworkBehaviour.OnSynchronize` to synchronize connecting (to-be-synchronized) clients and also uses an RPC to synchronize changes in state for already synchronized and connected clients:
+
+```csharp
+using UnityEngine;
+using Unity.Netcode;
+
+///
+/// Simple RPC driven state that shows one
+/// form of NetworkBehaviour.OnSynchronize usage
+///
+public class SimpleRpcState : NetworkBehaviour
+{
+ private bool m_ToggleState;
+
+ ///
+ /// Late joining clients will be synchronized
+ /// to the most current m_ToggleState
+ ///
+ protected override void OnSynchronize(ref BufferSerializer serializer)
+ {
+ serializer.SerializeValue(ref m_ToggleState);
+ base.OnSynchronize(ref serializer);
+ }
+
+ public void ToggleState(bool stateIsSet)
+ {
+ m_ToggleState = stateIsSet;
+ }
+
+ ///
+ /// Synchronizes connected clients with the
+ /// server-side m_ToggleState
+ ///
+ ///
+ [Rpc(SendTo.ClientsAndHost)]
+ private void ToggleStateClientRpc(bool stateIsSet)
+ {
+ m_ToggleState = stateIsSet;
+ }
+}
+```
+:::caution
+`NetworkBehaviour.OnSynchronize` is only invoked on the server side during the write part of serialization and only invoked on the client side during the read part of serialization. When running a host, `NetworkBehaviour.OnSynchronize` is still only invoked once (server-side) during the write part of serialization.
+:::
+
+### Debugging `OnSynchronize` serialization
+
+If your serialization code has a bug and throws an exception, then `NetworkBehaviour.OnSynchronize` has additional safety checking to handle a graceful recovery without completely breaking the rest of the synchronization serialization pipeline.
+
+#### When writing
+
+If user-code throws an exception during `NetworkBehaviour.OnSynchronize`, it catches the exception and if:
+- **LogLevel = Normal**: A warning message that includes the name of the `NetworkBehaviour` that threw an exception while writing will be logged and that part of the serialization for the given `NetworkBehaviour` is skipped.
+- **LogLevel = Developer**: It provides the same warning message as well as it logs an error with the exception message and stack trace.
+
+After generating the log message(s), it rewinds the serialization stream to the point just before it invoked `NetworkBehaviour.OnSynchronize` and will continue serializing. Any data written before the exception occurred will be overwritten or dropped depending upon whether there are more `NetworkBehaviour` components to be serialized.
+
+#### When reading
+
+For exceptions this follows the exact same message logging pattern described above when writing. The difference is that after `NetworkBehaviour.OnSynchronize` logs one or more messages to the console, it skips over only the serialization data written by the server-side when `NetworkBehaviour.OnSynchronize` was invoked and continues the deserialization process for any remaining `NetworkBehaviour` components.
+
+However, there is an additional check to ensure that the total expected bytes to read were actually read from the buffer. If the total number of bytes read does not equal the expected number of bytes to be read it will log a warning that includes the name of the `NetworkBehaviour` in question, the total bytes read, the expected bytes to be read, and lets you know this `NetworkBehaviour` is being skipped.
+
+:::caution
+When using `NetworkBehaviour.OnSynchronize` you should be aware that you are increasing the synchronization payload size per instance. If you have 30 instances that each write 100 bytes of information you will have increased the total full client synchronization size by 3000 bytes.
+:::
+
+## Serializing `NetworkBehaviour`s
+
+`NetworkBehaviour`s require the use of specialized [`NetworkBehaviourReference`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviourReference.html) structures to be serialized and used with RPCs and `NetworkVariable`s.
diff --git a/versioned_docs/version-2.0.0/basics/networkbehaviour.md b/versioned_docs/version-2.0.0/basics/networkbehaviour.md
new file mode 100644
index 000000000..7f007cfff
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/networkbehaviour.md
@@ -0,0 +1,138 @@
+---
+id: networkbehavior
+title: NetworkBehaviour spawning and despawning
+---
+
+[`NetworkBehaviour`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html) is an abstract class that derives from [`MonoBehaviour`](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html) and is primarily used to create unique netcode or game logic. To replicate any netcode-aware properties or send and receive RPCs, a [GameObject](https://docs.unity3d.com/Manual/GameObjects.html) must have a [NetworkObject](networkobject.md) component and at least one `NetworkBehaviour` component.
+
+`NetworkBehaviour`s can use `NetworkVariable`s and RPCs to synchronize states and send messages over the network. When you call an RPC function in a `NetworkBehaviour`, the function isn't called locally. Instead, a message is sent containing your parameters, the `networkId` of the NetworkObject associated with the same GameObject (or child) that the `NetworkBehaviour` is assigned to, and the index of the NetworkObject-relative `NetworkBehaviour` (NetworkObjects can have several `NetworkBehaviours`, the index communicates which one).
+
+For more information about serializing and synchronizing `NetworkBehaviour`s, refer to the [NetworkBehaviour synchronization page](networkbehaviour-synchronize.md).
+
+## `NetworkBehaviour` requirements
+
+A `NetworkBehaviour` requires a NetworkObject component on the same relative GameObject or on a parent of the GameObject with the `NetworkBehaviour` component assigned to it. If you add a `NetworkBehaviour` to a GameObject that doesn't have a NetworkObject (or any parent), then Netcode for GameObjects automatically adds a NetworkObject component to the `GameObject` in which the `NetworkBehaviour` was added.
+
+It's important that the `NetworkBehaviour`s on each NetworkObject remain the same for the server and any client connected. When using multiple projects, this becomes especially important so the server doesn't try to call a client RPC on a `NetworkBehaviour` that might not exist on a specific client type (or set a `NetworkVariable` that doesn't exist, and so on).
+
+:::warning Disabling automatic NetworkObject addition
+You can optionally disable the automatic addition of NetworkObjects to GameObjects in the Editor using the **Multiplayer** > **Netcode for GameObjects** project settings. However, this is only recommended for advanced users who understand the implications and have alternative strategies in place to ensure that GameObjects with `NetworkBehaviour`s always have an associated NetworkObject.
+:::
+
+## Spawning
+
+`OnNetworkSpawn` is invoked on each `NetworkBehaviour` associated with a NetworkObject when it's spawned. This is where all netcode-related initialization should occur.
+
+You can still use `Awake` and `Start` to do things like finding components and assigning them to local properties, but if `NetworkBehaviour.IsSpawned` is false then don't expect netcode-distinguishing properties (like `IsClient`, `IsServer`, `IsHost`, for example) to be accurate within `Awake` and `Start` methods.
+
+For reference purposes, below is a table of when `NetworkBehaviour.OnNetworkSpawn` is invoked relative to the NetworkObject type:
+
+Dynamically spawned | In-scene placed
+------------------- | ---------------
+`Awake` | `Awake`
+`OnNetworkSpawn` | `Start`
+`Start` | `OnNetworkSpawn`
+
+For more information about `NetworkBehaviour` methods and when they are invoked, see the [Pre-Spawn and MonoBehaviour Methods](networkbehaviour.md#pre-spawn-and-monobehaviour-methods) section.
+
+### Disabling `NetworkBehaviour`s when spawning
+
+If you want to disable a specific `NetworkBehaviour` but still want it to be included in the NetworkObject spawn process (so you can still enable it at a later time), you can disable the individual `NetworkBehaviour` instead of the entire `GameObject`.
+
+`NetworkBehaviour` components that are disabled by default and are attached to in-scene placed NetworkObjects behave like `NetworkBehaviour` components that are attached to dynamically spawned NetworkObjects when it comes to the order of operations for the `NetworkBehaviour.Start` and `NetworkBehaviour.OnNetworkSpawn` methods. Since in-scene placed NetworkObjects are spawned when the scene is loaded, a `NetworkBehaviour` component (that is disabled by default) will have its `NetworkBehaviour.OnNetworkSpawn` method invoked before the `NetworkBehaviour.Start` method, since `NetworkBehaviour.Start` is invoked when a disabled `NetworkBehaviour` component is enabled.
+
+Dynamically spawned | In-scene placed (disabled `NetworkBehaviour` components)
+------------------- | ---------------
+`Awake` | `Awake`
+`OnNetworkSpawn` | `OnNetworkSpawn`
+`Start` | `Start` (invoked when disabled `NetworkBehaviour` components are enabled)
+
+:::warning Parenting, inactive GameObjects, and `NetworkBehaviour` components
+If you have child GameObjects that are not active in the hierarchy but are nested under an active GameObject with an attached NetworkObject component, then the inactive child GameObjects will not be included when the NetworkObject is spawned. This applies for the duration of the NetworkObject's spawned lifetime. If you want all child `NetworkBehaviour` components to be included in the spawn process, then make sure their respective GameObjects are active in the hierarchy before spawning the NetworkObject. Alternatively, you can just disable the NetworkBehaviour component(s) individually while leaving their associated GameObject active.
+
+It's recommended to disable a `NetworkBehaviour` component rather than the GameObject itself.
+:::
+
+### Dynamically spawned NetworkObjects
+
+For dynamically spawned NetworkObjects (instantiating a network prefab during runtime) the `OnNetworkSpawn` method is invoked before the `Start` method is invoked. This means that finding and assigning components to a local property within the `Start` method exclusively will result in that property not being set in a `NetworkBehaviour` component's `OnNetworkSpawn` method when the NetworkObject is dynamically spawned. To circumvent this issue, you can have a common method that initializes the components and is invoked both during the `Start` method and the `OnNetworkSpawned` method like the code example below:
+
+```csharp
+public class MyNetworkBehaviour : NetworkBehaviour
+{
+ private MeshRenderer m_MeshRenderer;
+ private void Start()
+ {
+ Initialize();
+ }
+
+ private void Initialize()
+ {
+ if (m_MeshRenderer == null)
+ {
+ m_MeshRenderer = FindObjectOfType();
+ }
+ }
+
+ public override void OnNetworkSpawn()
+ {
+ Initialize();
+ // Do things with m_MeshRenderer
+
+ base.OnNetworkSpawn();
+ }
+}
+```
+
+### In-scene placed NetworkObjects
+
+For in-scene placed NetworkObjects, the `OnNetworkSpawn` method is invoked after the `Start` method, because the SceneManager scene loading process controls when NetworkObjects are instantiated. The previous code example shows how you can design a `NetworkBehaviour` that ensures both in-scene placed and dynamically spawned NetworkObjects will have assigned the required properties before attempting to access them. Of course, you can always make the decision to have in-scene placed `NetworkObjects` contain unique components to that of dynamically spawned `NetworkObjects`. It all depends upon what usage pattern works best for your project.
+
+For more information about in-scene placed NetworkObjects, refer to the [in-scene placed NetworkObjects page](scenemanagement/inscene-placed-networkobjects.md).
+
+## Despawning
+
+`NetworkBehaviour.OnNetworkDespawn` is invoked on each `NetworkBehaviour` associated with a NetworkObject when it's despawned. This is where all netcode cleanup code should occur, but isn't to be confused with destroying ([see below](#destroying)). When a `NetworkBehaviour` component is destroyed, it means the associated GameObject, and all attached components, are in the middle of being destroyed. Regarding the order of operations, `NetworkBehaviour.OnNetworkDespawn` is always invoked before `NetworkBehaviour.OnDestroy`.
+
+### Destroying
+
+Each `NetworkBehaviour` has a virtual `OnDestroy` method that can be overridden to handle clean up that needs to occur when you know the `NetworkBehaviour` is being destroyed.
+
+If you override the virtual `OnDestroy` method it's important to always invoke the base like such:
+
+```csharp
+ public override void OnDestroy()
+ {
+ // Clean up your NetworkBehaviour
+
+ // Always invoked the base
+ base.OnDestroy();
+ }
+```
+
+`NetworkBehaviour` handles other destroy clean up tasks and requires that you invoke the base `OnDestroy` method to operate properly.
+
+## Pre-spawn and `MonoBehaviour` methods
+
+Since `NetworkBehaviour` is derived from `MonoBehaviour`, the `NetworkBehaviour.OnNetworkSpawn` method is treated similar to the `Awake`, `Start`, `FixedUpdate`, `Update`, and `LateUpdate` `MonoBehaviour` methods. Different methods are invoked depending on whether the GameObject is active in the hierarchy.
+
+- When active: `Awake`, `Start`, `FixedUpdate`, `Update`, and `LateUpdate` are invoked.
+- When not active: `Awake`, `Start`, `FixedUpdate`, `Update`, and `LateUpdate` are not invoked.
+
+For more information about execution order, refer to [Order of execution for event functions](https://docs.unity3d.com/Manual/ExecutionOrder.html) in the main Unity Manual.
+
+The unique behavior of `OnNetworkSpawn`, compared to the previously listed methods, is that it's not invoked until the associated GameObject is active in the hierarchy and its associated NetworkObject is spawned.
+
+Additionally, the `FixedUpdate`, `Update`, and `LateUpdate` methods, if defined and the GameObject is active in the hierarchy, will still be invoked on `NetworkBehaviour`s even when they're not yet spawned. If you want portions or all of your update methods to only execute when the associated NetworkObject component is spawned, you can use the `NetworkBehaviour.IsSpawned` flag to determine the spawned status like the below example:
+
+```csharp
+private void Update()
+{
+ // If the NetworkObject is not yet spawned, exit early.
+ if (!IsSpawned)
+ {
+ return;
+ }
+ // Netcode specific logic executed when spawned.
+}
+```
diff --git a/versioned_docs/version-2.0.0/basics/networkobject.md b/versioned_docs/version-2.0.0/basics/networkobject.md
new file mode 100644
index 000000000..a2c49ea2b
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/networkobject.md
@@ -0,0 +1,127 @@
+---
+id: networkobject
+title: NetworkObject
+---
+
+A NetworkObject is a [GameObject](https://docs.unity3d.com/Manual/GameObjects.html) with a NetworkObject component and at least one [NetworkBehaviour](networkbehaviour.md) component, which enables the GameObject to respond to and interact with netcode. NetworkObjects are session-mode agnostic and used in both [client-server](../terms-concepts/client-server.md) and [distributed authority](../terms-concepts/distributed-authority.md) contexts.
+
+Netcode for GameObjects' high level components, [the RPC system](../advanced-topics/messaging-system.md), [object spawning](../object-spawning), and [`NetworkVariable`](networkvariable.md)s all rely on there being at least two Netcode components added to a GameObject:
+
+ 1. NetworkObject
+ 2. [`NetworkBehaviour`](networkbehaviour.md)
+
+NetworkObjects require the use of specialized [`NetworkObjectReference`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObjectReference.html) structures before you can serialize and use them with RPCs and `NetworkVariable`s
+
+Netcode for GameObjects also has [PlayerObjects](playerobjects.md), an optional feature that you can use to assign a NetworkObject to a specific client.
+
+## Using NetworkObjects
+
+To replicate any Netcode-aware properties or send/receive RPCs, a GameObject must have a NetworkObject component and at least one NetworkBehaviour component. Any Netcode-related component, such as a NetworkTransform or a NetworkBehaviour with one or more NetworkVariables or RPCs, requires a NetworkObject component on the same relative GameObject (or on a parent of the GameObject in question).
+
+When spawning a NetworkObject, the `NetworkObject.GlobalObjectIdHash` value initially identifies the associated network prefab asset that clients instantiate to create a client-local clone. After instantiated locally, each NetworkObject is assigned a NetworkObjectId that's used to associate NetworkObjects across the network. For example, one peer can say "Send this RPC to the object with the NetworkObjectId 103," and everyone knows what object it's referring to. A NetworkObject is spawned on a client when it's instantiated and assigned a unique NetworkObjectId.
+
+You can use [NetworkBehaviours](networkbehaviour.md) to add your own custom Netcode logic to the associated NetworkObject.
+
+### Component order
+
+The order of components on a networked GameObject matters. When adding netcode components to a GameObject, ensure that the NetworkObject component is ordered before any NetworkBehaviour components.
+
+The order in which NetworkBehaviour components are presented in the **Inspector** view is the order in which each associated `NetworkBehaviour.OnNetworkSpawn` method is invoked. Any properties that are set during `NetworkBehaviour.OnNetworkSpawn` are set in the order that each NetworkBehaviour's `OnNetworkSpawned` method is invoked.
+
+#### Avoiding execution order issues
+
+You can avoid execution order issues in any NetworkBehaviour component scripts that have dependencies on other NetworkBehaviour components associated with the same NetworkObject by placing those scripts in an overridden `NetworkBehaviour.OnNetworkPostSpawn` method. The `NetworkBehaviour.OnNetworkPostSpawn` method is invoked on each NetworkBehaviour component after all NetworkBehaviour components associated with the same NetworkObject component have had their `NetworkBehaviour.OnNetworkSpawn` methods invoked (but they will still be invoked in the same execution order defined by their relative position to the NetworkObject component when viewed within the Unity Editor **Inspector** view).
+
+## Ownership
+
+Either the server (default) or any connected and approved client owns each NetworkObject. By default, Netcode for GameObjects is [server-authoritative](../terms-concepts/client-server.md), which means only the server can spawn and despawn NetworkObjects, but you can also build [distributed authority](../terms-concepts/distributed-authority.md) games where clients have the authority to spawn and despawn NetworkObjects as well.
+
+If you're creating a client-server game and you want a client to control more than one NetworkObject, use the following ownership methods.
+
+The default `NetworkObject.Spawn` method assumes server-side ownership:
+
+```csharp
+GetComponent().Spawn();
+```
+
+To spawn NetworkObjects with ownership use the following:
+
+```csharp
+GetComponent().SpawnWithOwnership(clientId);
+```
+
+To change ownership, use the `ChangeOwnership` method:
+
+```csharp
+GetComponent().ChangeOwnership(clientId);
+```
+
+To give ownership back to the server use the `RemoveOwnership` method:
+
+```csharp
+GetComponent().RemoveOwnership();
+```
+
+To see if the local client is the owner of a NetworkObject, you can check the [`NetworkBehaviour.IsOwner`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.IsOwner.html) property.
+
+To see if the server owns the NetworkObject, you can check the [`NetworkBehaviour.IsOwnedByServer`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.IsOwnedByServer.html) property.
+
+:::note
+
+When you want to despawn and destroy the owner but you don't want to destroy a specific NetworkObject along with the owner, you can set the `NetworkObject.DontDestroyWithOwner` property to `true` which ensures that the owned NetworkObject isn't destroyed with the owner.
+
+:::
+
+## Network prefabs
+
+Network prefabs are registered to a `NetworkPrefabsList` object (a type of `ScriptableObject`). By default, a default prefabs list containing every network prefab in your project.
+
+However, when you want to limit which prefabs are available (for example, to reduce memory usage), you can disable this behavior in **Project Settings** > **Netcode For GameObjects** > **Project Settings**. You can also manually create a `NetworkPrefabsList` by right-clicking in the assets view and selecting **Create** > **Netcode** > **Network Prefabs List** and adding your prefabs to it. That prefab list can then be assigned to a `NetworkManager` to allow that `NetworkManager` to create those prefabs.
+
+:::warning
+
+You can only have one NetworkObject at the root of a prefab. Don't create prefabs with nested `NetworkObjects`.
+
+:::
+
+## Spawning with (or without) observers
+
+![image](/img/SpawnWithObservers.png)
+
+The `NetworkObject.SpawnWithObservers` property (default is true) enables you to spawn a NetworkObject with no initial observers. This is the recommended alternative to using `NetworkObject.CheckObjectVisibility` when you just want it to be applied globally to all clients (only when spawning an instance of the NetworkObject in question). If you want more precise per-client control then `NetworkObject.CheckObjectVisibility` is recommended. `NetworkObject.SpawnWithObservers` is only applied upon the initial server-side spawning and once spawned it has no impact on object visibility.
+
+## Transform synchronization
+
+![image](/img/NetworkObject-TransformSynchronization.png)
+
+There are times when you want to use a NetworkObject for something that doesn't require the synchronization of its transform. You might have an [in-scene placed NetworkObject](./scenemanagement/inscene-placed-networkobjects.md) that's only used to manage game state and it doesn't make sense to incur the initial client synchronization cost of synchronizing its transform. To prevent a NetworkObject from initially synchronizing its transform when spawned, deselect the **Synchronize Transform** property. This property is enabled by default.
+
+:::caution
+If you're planning to use a NetworkTransform, then you always want to make sure the **Synchronize Transform** property is enabled.
+:::
+
+## Active scene synchronization
+
+![image](/img/ActiveSceneMigration.png)
+
+When a GameObject is instantiated, it gets instantiated in the current active scene. However, sometimes you might find that you want to change the currently active scene and would like specific NetworkObject instances to automatically migrate to the newly assigned active scene. While you could keep a list or table of the NetworkObject instances and write the code/logic to migrate them into a newly assigned active scene, this can be time consuming and become complicated depending on project size and complexity. The alternate and recommended way to handle this is by enabling the **Active Scene Synchronization** property of each NetworkObject you want to automatically migrate into any newly assigned scene. This property defaults to disabled.
+
+Refer to the [NetworkSceneManager active scene synchronization](../scenemanagement/using-networkscenemanager#active-scene-synchronization) page for more details.
+
+## Scene migration synchronization
+
+![image](/img/SceneMigrationSynchronization.png)
+
+Similar to [`NetworkObject.ActiveSceneSynchronization`](#active-scene-synchronization), [`NetworkObject.SceneMigrationSynchronization`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_SceneMigrationSynchronization) automatically synchronizes client-side NetworkObject instances that are migrated to a scene via [`SceneManager.MoveGameObjectToScene`](https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.MoveGameObjectToScene.html) on the host or server side. This can be useful if you have a specific scene you wish to migrate NetworkObject instances to that is not the currently active scene.
+
+`NetworkObject.ActiveSceneSynchronization` can be used with `NetworkObject.SceneMigrationSynchronization` as long as you take into consideration that if you migrate a NetworkObject into a non-active scene via `SceneManager.MoveGameObjectToScene` and later change the active scene, then the NetworkObject instance will be automatically migrated to the newly set active scene.
+
+:::warning
+Scene migration synchronization is enabled by default. For NetworkObjects that don't require it, such as those that generate static environmental objects like trees, it's recommended to disable scene migration synchronization to avoid additional processing overheads.
+:::
+
+## Additional resources
+
+- [PlayerObjects and player prefabs](playerobjects.md)
+- [NetworkBehaviour](networkbehaviour.md)
+- [NetworkVariable](networkvariable.md)
diff --git a/versioned_docs/version-2.0.0/basics/networkvariable.md b/versioned_docs/version-2.0.0/basics/networkvariable.md
new file mode 100644
index 000000000..61a73dc7d
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/networkvariable.md
@@ -0,0 +1,632 @@
+---
+id: networkvariable
+title: NetworkVariables
+---
+
+`NetworkVariable`s are a way of synchronizing properties between servers and clients in a persistent manner, unlike [RPCs](../advanced-topics/message-system/rpc.md) and [custom messages](../advanced-topics/message-system/custom-messages.md), which are one-off, point-in-time communications that aren't shared with any clients not connected at the time of sending. `NetworkVariable`s are session-mode agnostic and can be used with either a [client-server](../terms-concepts/client-server.md) or [distributed authority](../terms-concepts/distributed-authority.md) network topology.
+
+`NetworkVariable` is a wrapper of the stored value of type `T`, so you need to use the `NetworkVariable.Value` property to access the actual value being synchronized. A `NetworkVariable` is synchronized with:
+
+* New clients joining the game (also referred to as late-joining clients)
+ * When the associated NetworkObject of a `NetworkBehaviour` with `NetworkVariable` properties is spawned, any `NetworkVariable`'s current state (`Value`) is automatically synchronized on the client side.
+* Connected clients
+ * When a `NetworkVariable` value changes, all connected clients that subscribed to the `NetworkVariable.OnValueChanged` event (prior to the value being changed) are notified of the change. Two parameters are passed to any `NetworkVariable.OnValueChanged` subscribed callback method:
+ - First parameter (Previous): The previous value before the value was changed
+ - Second parameter (Current): The newly changed `NetworkVariable.Value`
+
+You can use `NetworkVariable` [permissions](#permissions) to control read and write access to `NetworkVariable`s. You can also create [custom `NetworkVariable`s](custom-networkvariables.md).
+
+## Setting up NetworkVariables
+
+### Defining a NetworkVariable
+
+- A `NetworkVariable` property must be defined within a `NetworkBehaviour`-derived class attached to a `GameObject`.
+ - The `GameObject` or a parent `GameObject` must also have a NetworkObject component attached to it.
+- A `NetworkVariable`'s value can only be set:
+ - When initializing the property (either when it's declared or within the Awake method).
+ - While the associated NetworkObject is spawned (upon being spawned or any time while it's still spawned).
+
+### Initializing a NetworkVariable
+
+When a client first connects, it's synchronized with the current value of the `NetworkVariable`. Typically, clients should register for `NetworkVariable.OnValueChanged` within the `OnNetworkSpawn` method. A `NetworkBehaviour`'s `Start` and `OnNetworkSpawn` methods are invoked based on the type of NetworkObject the `NetworkBehaviour` is associated with:
+
+- In-scene placed: Since the instantiation occurs via the scene loading mechanism(s), the `Start` method is invoked before `OnNetworkSpawn`.
+- Dynamically spawned: Since `OnNetworkSpawn` is invoked immediately (that is, within the same relative call-stack) after instantiation, the `Start` method is invoked after `OnNetworkSpawn`.
+
+Typically, these methods are invoked at least one frame after the NetworkObject and associated `NetworkBehaviour` components are instantiated. The table below lists the event order for dynamically spawned and in-scene placed objects respectively.
+
+Dynamically spawned | In-scene placed
+------------------- | ---------------
+Awake | Awake
+OnNetworkSpawn | Start
+Start | OnNetworkSpawn
+
+You should only set the value of a `NetworkVariable` when first initializing it or if it's spawned. It isn't recommended to set a `NetworkVariable` when the associated NetworkObject isn't spawned.
+
+:::tip
+If you need to initialize other components or objects based on a `NetworkVariable`'s initial synchronized state, then you can use a common method that's invoked on the client side within the `NetworkVariable.OnValueChanged` callback (if assigned) and `NetworkBehaviour.OnNetworkSpawn` method.
+:::
+
+## Supported types
+
+`NetworkVariable` supports the following types:
+
+* C# unmanaged [primitive types](../advanced-topics/serialization/cprimitives.md) (which are serialized by direct `memcpy` into/out of the buffer): `bool`, `byte`, `sbyte`, `char`, `decimal`, `double`, `float`, `int`, `uint`, `long`, `ulong`, `short`, and `ushort`.
+* Unity unmanaged [built-in types](../advanced-topics/serialization/unity-primitives.md) (which are serialized by direct `memcpy` into/out of the buffer): `Vector2`, `Vector3`, `Vector2Int`, `Vector3Int`, `Vector4`, `Quaternion`, `Color`, `Color32`, `Ray`, `Ray2D`.
+* Any [`enum`](../advanced-topics/serialization/enum-types.md) types (which are serialized by direct `memcpy` into/out of the buffer).
+* Any type (managed or unmanaged) that implements [`INetworkSerializable`](../advanced-topics/serialization/inetworkserializable.md) (which are serialized by calling their `NetworkSerialize` method). **On the reading side, these values are deserialized in-place, meaning the existing instance is reused and any non-serialized values are left in their current state.**
+* Any unmanaged struct type that implements [`INetworkSerializeByMemcpy`](../advanced-topics/serialization/inetworkserializebymemcpy.md) (which are serialized by direct `memcpy `of the entire struct into/out of the buffer).
+* Unity [fixed string](../advanced-topics/serialization/fixedstrings.md) types: `FixedString32Bytes`, `FixedString64Bytes`, `FixedString128Bytes`, `FixedString512Bytes`, and `FixedString4096Bytes` (which are serialized intelligently, only sending the used part across the network and adjusting the length of the string on the other side to fit the received data).
+
+For any types that don't fit within this list, including managed types and unmanaged types with pointers: you can provide delegates informing the serialization system of how to serialize and deserialize your values. For more information, refer to [Custom Serialization](../advanced-topics/custom-serialization.md). A limitation of custom serialization is that, unlike `INetworkSerializable` types, types using custom serialization aren't able to be read in-place, so managed types will, by necessity, incur a garbage collection allocation (which can cause performance issues) on every update.
+
+### Managing garbage collection
+
+Although `NetworkVariable` supports both managed and [unmanaged](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters#unmanaged-constraint) types, managed types come with additional overhead.
+
+Netcode for GameObjects has been designed to minimize garbage collection allocations for managed `INetworkSerializable` types (for example, a new value is only allocated if the value changes from `null` to non-`null`). However, the ability of a type to be `null` adds additional overhead both in logic (checking for nulls before serializing) and bandwidth (every serialization carries an additional byte indicating whether the value is `null`).
+
+Additionally, any type that has a managed type is itself a managed type - so a struct that has `int[]` is a managed type because `int[]` is a managed type.
+
+Finally, while managed `INetworkSerializable` types are serialized in-place (and thus don't incur allocations for simple value updates), C# arrays and managed types serialized through custom serialization are **not** serialized in-place, and will incur an allocation on every update.
+
+### Using collections with `NetworkVariable`s
+
+You can use `NetworkVariable`s with both managed and unmanaged collections, but you need to call `NetworkVariable.CheckDirtyState()` after making changes to a collection (or items in a collection) for those changes to be detected. Then the [`OnValueChanged`](#onvaluechanged-example) event will trigger, if subscribed locally, and by the end of the frame the rest of the clients and server will be synchronized with the detected change(s).
+
+`NetworkVariable.CheckDirtyState()` checks every item in a collection, including recursively nested collections, which can have a significant impact on performance if collections are large. If you're making multiple changes to a collection, you only need to call `NetworkVariable.CheckDirtyState()` once after all changes are complete, rather than calling it after each change.
+
+## Synchronization and notification example
+
+The following client-server example shows how the initial `NetworkVariable` synchronization has already occurred by the time `OnNetworkSpawn` is invoked. It also shows how subscribing to `NetworkVariable.OnValueChanged` within `OnNetworkSpawn` provides notifications for any changes to `m_SomeValue.Value` that occur.
+
+1. The server initializes the `NetworkVariable` when the associated NetworkObject is spawned.
+1. The client confirms that the `NetworkVariable` is synchronized to the initial value set by the server and assigns a callback method to `NetworkVariable.OnValueChanged`.
+1. Once spawned, the client is notified of any changes made to the `NetworkVariable`.
+
+:::important
+This example only tests the initial client synchronization of the value and when the value changes. If a second client joins, it will throw a warning about the `NetworkVariable.Value` not being the initial value. This example is intended for use with a single server or host and a single client.
+:::
+
+ ```csharp
+public class TestNetworkVariableSynchronization : NetworkBehaviour
+{
+ private NetworkVariable m_SomeValue = new NetworkVariable();
+ private const int k_InitialValue = 1111;
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer)
+ {
+ m_SomeValue.Value = k_InitialValue;
+ NetworkManager.OnClientConnectedCallback += NetworkManager_OnClientConnectedCallback;
+ }
+ else
+ {
+ if (m_SomeValue.Value != k_InitialValue)
+ {
+ Debug.LogWarning($"NetworkVariable was {m_SomeValue.Value} upon being spawned" +
+ $" when it should have been {k_InitialValue}");
+ }
+ else
+ {
+ Debug.Log($"NetworkVariable is {m_SomeValue.Value} when spawned.");
+ }
+ m_SomeValue.OnValueChanged += OnSomeValueChanged;
+ }
+ }
+
+ private void NetworkManager_OnClientConnectedCallback(ulong obj)
+ {
+ StartCoroutine(StartChangingNetworkVariable());
+ }
+
+ private void OnSomeValueChanged(int previous, int current)
+ {
+ Debug.Log($"Detected NetworkVariable Change: Previous: {previous} | Current: {current}");
+ }
+
+ private IEnumerator StartChangingNetworkVariable()
+ {
+ var count = 0;
+ var updateFrequency = new WaitForSeconds(0.5f);
+ while (count < 4)
+ {
+ m_SomeValue.Value += m_SomeValue.Value;
+ yield return updateFrequency;
+ }
+ NetworkManager.OnClientConnectedCallback -= NetworkManager_OnClientConnectedCallback;
+ }
+}
+ ```
+
+If you attach the above script to an in-scene placed NetworkObject, make a standalone build, run the standalone build as a host, and then connect to that host by entering Play Mode in the Editor, you can see (in the console output):
+- The client side `NetworkVariable` value is the same as the server when `NetworkBehaviour.OnNetworkSpawn` is invoked.
+- The client detects any changes made to the `NetworkVariable` after the in-scene placed NetworkObject is spawned.
+
+This works the same way with dynamically spawned NetworkObjects.
+
+## OnValueChanged example
+
+The [synchronization and notification example](#synchronization-and-notification-example) highlights the differences between synchronizing a `NetworkVariable` with newly-joining clients and notifying connected clients when a `NetworkVariable` changes, but it doesn't provide any concrete example usage.
+
+The `OnValueChanged` example shows a simple server-authoritative `NetworkVariable` being used to track the state of a door (that is, open or closed) using a non-ownership-based server RPC. With `RequireOwnership = false` any client can notify the server that it's performing an action on the door. Each time the door is used by a client, the `Door.ToggleServerRpc` is invoked and the server-side toggles the state of the door. When the `Door.State.Value` changes, all connected clients are synchronized to the (new) current `Value` and the `OnStateChanged` method is invoked locally on each client.
+
+```csharp
+public class Door : NetworkBehaviour
+{
+ public NetworkVariable State = new NetworkVariable();
+
+ public override void OnNetworkSpawn()
+ {
+ State.OnValueChanged += OnStateChanged;
+ }
+
+ public override void OnNetworkDespawn()
+ {
+ State.OnValueChanged -= OnStateChanged;
+ }
+
+ public void OnStateChanged(bool previous, bool current)
+ {
+ // note: `State.Value` will be equal to `current` here
+ if (State.Value)
+ {
+ // door is open:
+ // - rotate door transform
+ // - play animations, sound etc.
+ }
+ else
+ {
+ // door is closed:
+ // - rotate door transform
+ // - play animations, sound etc.
+ }
+ }
+
+ [Rpc(SendTo.Server)]
+ public void ToggleServerRpc()
+ {
+ // this will cause a replication over the network
+ // and ultimately invoke `OnValueChanged` on receivers
+ State.Value = !State.Value;
+ }
+}
+```
+
+## Permissions
+
+The `NetworkVariable` constructor can take up to three parameters:
+
+```csharp
+public NetworkVariable(T value = default,
+NetworkVariableReadPermission readPerm = NetworkVariableReadPermission.Everyone,
+NetworkVariableWritePermission writePerm = NetworkVariableWritePermission.Server);
+```
+
+By default, in a [client-server](../terms-concepts/client-server.md) context, the default permissions are:
+
+- **Server**: Has read and write permissions
+- **Clients:** Have read-only permissions.
+
+The two types of permissions are defined within [NetworkVariablePermissions.cs](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/release/1.0.0/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariablePermission.cs):
+
+```csharp
+ ///
+ /// The permission types for reading a var
+ ///
+ public enum NetworkVariableReadPermission
+ {
+ ///
+ /// Everyone can read
+ ///
+ Everyone,
+ ///
+ /// Only the owner and the server can read
+ ///
+ Owner,
+ }
+
+ ///
+ /// The permission types for writing a var
+ ///
+ public enum NetworkVariableWritePermission
+ {
+ ///
+ /// Only the server can write
+ ///
+ Server,
+ ///
+ /// Only the owner can write
+ ///
+ Owner
+ }
+```
+:::important
+Owner writer permissions are owner-only.
+:::
+
+### Read permissions
+
+There are two options for reading a `NetworkVariable.Value`:
+
+- **Everyone (default)**: both owners and non-owners of the NetworkObject can read the value.
+ - This is useful for global states that all clients should be aware of, such as player scores, health, or any other state that all clients should know about.
+ - We provided an example of maintaining a door's open or closed state using the everyone permission.
+- **Owner**: only the owner of the NetworkObject and the server can read the value.
+ - This is useful if your `NetworkVariable` represents something specific to the client's player that only the server and client should know about, such as a player's inventory or ammo count.
+
+### Write permissions
+
+There are two options for writing a `NetworkVariable.Value`:
+
+- **Server**: the server is the only one that can write the value. This is the default for [client-server contexts](../terms-concepts/client-server.md).
+ - This is useful for server-side specific states that all clients should be aware of but can't change, such as an NPC's status or some global world environment state (that is, is it night or day time).
+- **Owner**: only the owner of the NetworkObject can write to the value. This is the default for [distributed authority contexts](../terms-concepts/distributed-authority.md).
+ - This is useful if your `NetworkVariable` represents something specific to the client's player that only the owning client should be able to set, such as a player's skin or other cosmetics.
+
+### Permissions example
+
+The following example has a few different permissions configurations that you might use in a game while keeping track of a player's state. It also provides details of each `NetworkVariable`'s purpose and the reasoning behind each `NetworkVariable`'s read and write permission settings.
+
+```csharp
+public class PlayerState : NetworkBehaviour
+{
+ private const float k_DefaultHealth = 100.0f;
+ ///
+ /// Default Permissions: Everyone can read, server can only write
+ /// Player health is typically something determined (updated/written to) on the server
+ /// side, but a value everyone should be synchronized with (that is, read permissions).
+ ///
+ public NetworkVariable Health = new NetworkVariable(k_DefaultHealth);
+
+ ///
+ /// Owner Read Permissions: Owner or server can read
+ /// Owner Write Permissions: Only the Owner can write
+ /// A player's ammo count is something that you might want, for convenience sake, the
+ /// client-side to update locally. This might be because you are trying to reduce
+ /// bandwidth consumption for the server and all non-owners/ players or you might be
+ /// trying to incorporate a more client-side "hack resistant" design where non-owners
+ /// are never synchronized with this value.
+ ///
+ public NetworkVariable AmmoCount = new NetworkVariable(default,
+ NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Owner);
+
+ ///
+ /// Owner Write & Everyone Read Permissions:
+ /// A player's model's skin selection index. You might have the option to allow players
+ /// to select different skin materials as a way to further encourage a player's personal
+ /// association with their player character. It would make sense to make the permissions
+ /// setting of the NetworkVariable such that the client can change the value, but everyone
+ /// will be notified when it changes to visually reflect the new skin selection.
+ ///
+ public NetworkVariable SkinSelectionIndex = new NetworkVariable(default,
+ NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
+
+ ///
+ /// Owner Read & Server Write Permissions:
+ /// You might incorporate some form of reconnection logic that stores a player's state on
+ /// the server side and can be used by the client to reconnect a player if disconnected
+ /// unexpectedly. In order for the client to let the server know it's the "same client"
+ /// you might have implemented a keyed array (that is, Hashtable, Dictionary, etc, ) to track
+ /// each connected client. The key value for each connected client would only be written to
+ /// the each client's PlayerState.ReconnectionKey. Under this scenario, you only want the
+ /// server to have write permissions and the owner (client) to be synchronized with this
+ /// value (via owner only read permissions).
+ ///
+ public NetworkVariable ReconnectionKey = new NetworkVariable(default,
+ NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Server);
+}
+```
+
+:::important
+You might be wondering about our earlier door example and why we chose to use a server RPC for clients to notify the server that the door's open/closed state has changed. In that scenario, the owner of the door will most likely be owned by the server, just like non-player characters will almost always be owned by the server. In a server-owned scenario, using an RPC to handle updating a `NetworkVariable` is the proper choice above permissions for most cases.
+:::
+
+## Complex types
+
+Almost all of the examples on this page have been focused around numeric [value types](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-types). Netcode for GameObjects also supports complex types and can support both unmanaged types *and* managed types (although avoiding managed types where possible will improve your game's performance).
+
+### Synchronizing complex types example
+
+This example extends the previous `PlayerState` class to include some complex types to handle a weapon boosting game play mechanic. The example uses two complex values types:
+
+- `WeaponBooster`: A power-up weapon booster that can only be applied by the client. This is a simple example of a complex type.
+- `AreaWeaponBooster`: A second kind of weapon booster power-up that players can deploy at a specific location, and any team members within the radius of the `AreaWeaponBooster` have the weapon booster applied. This is an example of a nested complex type.
+
+`WeaponBooster` only needs one `NetworkVariable` to handle synchronizing everyone with any currently active player-local `WeaponBooster`. However, the `AreaWeaponBooster` must consider what happens if there are eight team members that can, at any given moment, deploy an `AreaWeaponBooster`. It requires, at a minimum, a list of all deployed and currently active `AreaWeaponBooster`s. This task uses a `NetworkList` instead of a `NetworkVariable`.
+
+Below are the `PlayerState` additions along with the `WeaponBooster` structure (complex type):
+
+```csharp
+public class PlayerState : NetworkBehaviour
+{
+ // ^^^^^^^ including all code from previous example ^^^^^^^
+
+ // The weapon booster currently applied to a player
+ private NetworkVariable PlayerWeaponBooster = new NetworkVariable();
+
+ ///
+ /// A list of team members active "area weapon boosters" that can be applied if the local player
+ /// is within their range.
+ ///
+ private NetworkList TeamAreaWeaponBoosters;
+
+ void Awake()
+ {
+ //NetworkList can't be initialized at declaration time like NetworkVariable. It must be initialized in Awake instead.
+ //If you do initialize at declaration, you will run into memory leak errors.
+ TeamAreaWeaponBoosters = new NetworkList();
+ }
+
+ void Start()
+ {
+ /*At this point, the object hasn't been network spawned yet, so you're not allowed to edit network variables! */
+ //list.Add(new AreaWeaponBooster());
+ }
+
+ void Update()
+ {
+ //This is just an example that shows how to add an element to the list after its initialization:
+ if (!IsServer) { return; } //remember: only the server can edit the list
+ if (Input.GetKeyUp(KeyCode.UpArrow))
+ {
+ TeamAreaWeaponBoosters.Add(new AreaWeaponBooster()));
+ }
+ }
+
+ public override void OnNetworkSpawn()
+ {
+ base.OnNetworkSpawn();
+ if (IsClient)
+ {
+ TeamAreaWeaponBoosters.OnListChanged += OnClientListChanged;
+ }
+ if (IsServer)
+ {
+ TeamAreaWeaponBoosters.OnListChanged += OnServerListChanged;
+ TeamAreaWeaponBoosters.Add(new AreaWeaponBooster()); //if you want to initialize the list with some default values, this is a good time to do so.
+ }
+ }
+
+ void OnServerListChanged(NetworkListEvent changeEvent)
+ {
+ Debug.Log($"[S] The list changed and now has {TeamAreaWeaponBoosters.Count} elements");
+ }
+
+ void OnClientListChanged(NetworkListEvent changeEvent)
+ {
+ Debug.Log($"[C] The list changed and now has {TeamAreaWeaponBoosters.Count} elements");
+ }
+}
+
+///
+/// Example: Complex Type
+/// This is an example of how one might handle tracking any weapon booster currently applied
+/// to a player.
+///
+public struct WeaponBooster : INetworkSerializable, System.IEquatable
+{
+ public float PowerAmplifier;
+ public float Duration;
+
+ public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter
+ {
+ if (serializer.IsReader)
+ {
+ var reader = serializer.GetFastBufferReader();
+ reader.ReadValueSafe(out PowerAmplifier);
+ reader.ReadValueSafe(out Duration);
+ }
+ else
+ {
+ var writer = serializer.GetFastBufferWriter();
+ writer.WriteValueSafe(PowerAmplifier);
+ writer.WriteValueSafe(Duration);
+ }
+ }
+
+ public bool Equals(WeaponBooster other)
+ {
+ return PowerAmplifier == other.PowerAmplifier && Duration == other.Duration;
+ }
+}
+```
+
+The example code above shows how a complex type implements `INetworkSerializable`. The second part of the example below shows that the `AreaWeaponBooster` includes a `WeaponBooster` property that would (for example) be applied to team members that are within the `AreaWeaponBoosters` radius:
+
+```csharp
+///
+/// Example: Nesting Complex Types
+/// This example uses the previous WeaponBooster complex type to be a "container" for
+/// the "weapon booster" information of an AreaWeaponBooster. It then provides additional
+/// information that would allow clients to easily determine, based on location and radius,
+/// if it should add (for example) a special power up HUD symbol or special-FX to the local
+/// player.
+///
+public struct AreaWeaponBooster : INetworkSerializable, System.IEquatable
+{
+ public WeaponBooster ApplyWeaponBooster; // the nested complex type
+ public float Radius;
+ public Vector3 Location;
+ public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter
+ {
+ if (serializer.IsReader)
+ {
+ // The complex type handles its own de-serialization
+ serializer.SerializeValue(ref ApplyWeaponBooster);
+ // Now de-serialize the non-complex type properties
+ var reader = serializer.GetFastBufferReader();
+ reader.ReadValueSafe(out Radius);
+ reader.ReadValueSafe(out Location);
+ }
+ else
+ {
+ // The complex type handles its own serialization
+ serializer.SerializeValue(ref ApplyWeaponBooster);
+ // Now serialize the non-complex type properties
+ var writer = serializer.GetFastBufferWriter();
+ writer.WriteValueSafe(Radius);
+ writer.WriteValueSafe(Location);
+ }
+ }
+
+ public bool Equals(AreaWeaponBooster other)
+ {
+ return other.ApplyWeaponBooster.Equals(ApplyWeaponBooster) && Radius == other.Radius && Location == other.Location;
+ }
+}
+```
+
+Looking closely at the read and write segments of code within `AreaWeaponBooster.NetworkSerialize`, the nested complex type property `ApplyWeaponBooster` handles its own serialization and de-serialization. The `ApplyWeaponBooster`'s implemented `NetworkSerialize` method serializes and deserialized any `AreaWeaponBooster` type property. This design approach can help reduce code replication while providing a more modular foundation to build even more complex, nested types.
+
+## Custom NetworkVariable Implementations
+
+:::warning Disclaimer
+The `NetworkVariable` and `NetworkList` classes were created as `NetworkVariableBase` class implementation examples. While the `NetworkVariable` class is considered production ready, you might run into scenarios where you have a more advanced implementation in mind. In this case, we encourage you to create your own custom implementation.
+:::
+In order to create your own `NetworkVariableBase` derived container, you should:
+
+- Create a class deriving from `NetworkVariableBase`.
+
+- Assure the the following methods are overridden:
+ - `void WriteField(FastBufferWriter writer)`
+ - `void ReadField(FastBufferReader reader)`
+ - `void WriteDelta(FastBufferWriter writer)`
+ - `void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)`
+- Depdending upon your custom `NetworkVariableBase` container, you might look at `NetworkVariable` or `NetworkList` to see how those two examples were implemented.
+
+
+
+#### NetworkVariableSerialization<T>
+
+The way you read and write network variables changes depending on the type you use.
+
+* Known, non-generic types: Use `FastBufferReader.ReadValue` to read from and `FastBufferWriter.WriteValue` to write to the network variable value.
+* Integer types: This type gives you the option to use `BytePacker` and `ByteUnpacker` to compress the network variable value. This process can save bandwidth but adds CPU processing time.
+* Generic types: Use serializers that Unity generates based on types discovered during a compile-time code generation process. This means you need to tell Unity's code generation algorithm which types to generate serializers for. To tell Unity which types to serialize, use the following methods:
+ * Use `GenerateSerializationForTypeAttribute` to serialize hard-coded types.
+ * Use `GenerateSerializationForGenericParameterAttribute` to serialize generic types.
+ To learn how to use these methods, refer to [Network variable serialization](#network-variable-serialization).
+
+##### Tell Unity to serialize a hard-coded type
+The following code example uses `GenerateSerializationForTypeAttribute` to generate serialization for a specific hard-coded type:
+```csharp
+[GenerateSerializationForType(typeof(Foo))]
+public class MyNetworkVariableTypeUsingFoo : NetworkVariableBase {}
+```
+
+You can call a type that you know the name of with the `FastBufferReader` or `FastBufferWriter` methods. These methods don't work for Generic types because the name of the type is unknown.
+##### Tell Unity to serialize a generic type
+The following code example uses `GenerateSerializationForGenericParameterAttribute` to generate serialization for a specific Generic parameter in your `NetworkVariable` type:
+```csharp
+[GenerateSerializationForGenericParameter(0)]
+public class MyNetworkVariableType : NetworkVariableBase {}
+```
+
+This attribute accepts an integer that indicates which parameter in the type to generate serialization for. This value is 0-indexed, which means that the first type is 0, the second type is 1, and so on.
+The following code example places the attribute more than once on one class to generate serialization for multiple types, in this case,`TFirstType` and `TSecondType:
+
+```csharp
+[GenerateSerializationForGenericParameter(0)]
+[GenerateSerializationForGenericParameter(1)]
+public class MyNetworkVariableType : NetworkVariableBase {}
+```
+
+
+The `GenerateSerializationForGenericParameterAttribute` and `GenerateSerializationForTypeAttribute` attributes make Unity's code generation create the following methods:
+
+```csharp
+NetworkVariableSerialization.Write(FastBufferWriter writer, ref T value);
+NetworkVariableSerialization.Read(FastBufferWriter writer, ref T value);
+NetworkVariableSerialization.Duplicate(in T value, ref T duplicatedValue);
+NetworkVariableSerialization.AreEqual(in T a, in T b);
+```
+
+For dynamically allocated types with a value that isn't `null` (for example, managed types and collections like NativeArray and NativeList) call `Read` to read the value in the existing object and write data into it directy (in-place). This avoids more allocations.
+
+You can use `AreEqual` to determine if a value is different from the value that `Duplicate` cached. This avoids sending the same value multiple times. You can also use the previous value that `Duplicate` cached to calculate deltas to use in `ReadDelta` and `WriteDelta`.
+
+The type you use must be serializable according to the "Supported Types" list above. Each type needs its own serializer instantiated, so this step tells the codegen which types to create serializers for.
+
+:::note Unity's code generator assumes that all `NetworkVariable` types exist as fields inside `NetworkBehaviour` types. This means that Unity only inspects fields inside `NetworkBehaviour` types to identify the types to create serializers for.
+
+ ### Custom NetworkVariable Example
+
+This example shows a custom `NetworkVariable` type to help you understand how you might implement such a type. In the current version of Netcode for GameObjects, this example is possible without using a custom `NetworkVariable` type; however, for more complex situations that aren't natively supported, this basic example should help inform you of how to approach the implementation:
+
+Looking at the read and write segments of code within `AreaWeaponBooster.NetworkSerialize`, the nested complex type property `ApplyWeaponBooster` handles its own serialization and de-serialization. The `ApplyWeaponBooster`'s implemented `NetworkSerialize` method serializes and deserializes any `AreaWeaponBooster` type property. This design approach can help reduce code replication while providing a more modular foundation to build even more complex, nested types.
+
+## Strings
+
+While `NetworkVariable` does support managed `INetworkSerializable` types, strings aren't in the list of supported types. This is because strings in C# are immutable types, preventing them from being deserialized in-place, so every update to a `NetworkVariable` would cause a Garbage Collected allocation to create the new string, which may lead to performance problems.
+
+While it's technically possible to support strings using custom serialization through `UserNetworkVariableSerialization`, it isn't recommended to do so due to the performance implications that come with it. Instead, we recommend using one of the `Unity.Collections.FixedString` value types. In the below example, we used a `FixedString128Bytes` as the `NetworkVariable` value type. On the server side, it changes the string value each time you press the space bar on the server or host instance. Joining clients will be synchronized with the current value applied on the server side, and each time you hit the space bar on the server side, the client synchronizes with the changed string.
+
+:::note
+`NetworkVariable` won't serialize the entire 128 bytes each time the `Value` is changed. Only the number of bytes that are actually used to store the string value will be sent, no matter which size of `FixedString` you use.
+:::
+
+```csharp
+public class TestFixedString : NetworkBehaviour
+{
+ /// Create your 128 byte fixed string NetworkVariable
+ private NetworkVariable m_TextString = new NetworkVariable();
+
+ private string[] m_Messages ={ "This is the first message.",
+ "This is the second message (not like the first)",
+ "This is the third message (but not the last)",
+ "This is the fourth and last message (next will roll over to the first)"
+ };
+
+ private int m_MessageIndex = 0;
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer)
+ {
+ // Assin the current value based on the current message index value
+ m_TextString.Value = m_Messages[m_MessageIndex];
+ }
+ else
+ {
+ // Subscribe to the OnValueChanged event
+ m_TextString.OnValueChanged += OnTextStringChanged;
+ // Log the current value of the text string when the client connected
+ Debug.Log($"Client-{NetworkManager.LocalClientId}'s TextString = {m_TextString.Value}");
+ }
+ }
+
+ public override void OnNetworkDespawn()
+ {
+ m_TextString.OnValueChanged -= OnTextStringChanged;
+ }
+
+ private void OnTextStringChanged(FixedString128Bytes previous, FixedString128Bytes current)
+ {
+ // Just log a notification when m_TextString changes
+ Debug.Log($"Client-{NetworkManager.LocalClientId}'s TextString = {m_TextString.Value}");
+ }
+
+ private void LateUpdate()
+ {
+ if (!IsServer)
+ {
+ return;
+ }
+
+ if (Input.GetKeyDown(KeyCode.Space))
+ {
+ m_MessageIndex++;
+ m_MessageIndex %= m_Messages.Length;
+ m_TextString.Value = m_Messages[m_MessageIndex];
+ Debug.Log($"Server-{NetworkManager.LocalClientId}'s TextString = {m_TextString.Value}");
+ }
+ }
+}
+```
+
+
+:::note
+The above example uses a pre-set list of strings to cycle through for example purposes only. If you have a predefined set of text strings as part of your actual design then you would not want to use a FixedString to handle synchronizing the changes to `m_TextString`. Instead, you would want to use a `uint` for the type `T` where the `uint` was the index of the string message to apply to `m_TextString`.
+:::
diff --git a/versioned_docs/version-2.0.0/basics/object-spawning.md b/versioned_docs/version-2.0.0/basics/object-spawning.md
new file mode 100644
index 000000000..221fef2fc
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/object-spawning.md
@@ -0,0 +1,347 @@
+---
+id: object-spawning
+title: Object spawning
+sidebar_label: Object spawning
+---
+
+In Unity, you typically create a new game object using the `Instantiate` function. Creating a game object with `Instantiate` will only create that object on the local machine. `Spawning` in Netcode for GameObjects (Netcode) means to instantiate and/or spawn the object that is synchronized between all clients by the server.
+
+## Network Prefabs
+
+A network Prefab is any unity Prefab asset that has one NetworkObject component attached to a `GameObject` within the prefab. More commonly, the NetworkObject component is attached to the root `GameObject` of the Prefab asset because this allows any child `GameObject` to have `NetworkBehaviour` components automatically assigned to the NetworkObject. The reason for this is that a NetworkObject component attached to a `GameObject` will be assigned (associated with) any `NetworkBehaviour` components on:
+
+- the same `GameObject` that the NetworkObject component is attached to
+- any child or children of the `GameObject` that the NetworkObject is attached to.
+
+:::note
+A caveat of the above two rules is when one of the children `GameObject`s also has a NetworkObject component assigned to it (a.k.a. "Nested NetworkObjects"). Because nested NetworkObject components aren't permited in network prefabs, Netcode for GameObjects will notify you in the editor if you are trying to add more than one NetworkObject to a Prefab and won't allow you to do this.
+:::
+
+When a `NetworkBehaviour` is assigned to a NetworkObject, the `NetworkObject.NetworkObjectId` is used to help determine which `NetworkBehaviour` component instance will receive an update to a `NetworkVariable` or where to invoke an RPC. A NetworkObject component can have one or more `NetworkBehaviour` components assigned to it.
+
+### Registering a Network Prefab
+
+You must register a Network Prefab instance with a `NetworkManager` using a `NetworkedPrefabsList` scriptable object.
+There are four steps to registering a network Prefab with a `NetworkManager`:
+
+1. Create a Network Prefab by creating a Prefab with a NetworkObject component attached to the root `GameObject`.
+2. Create a scriptable object called `NetworkedPrefabsList` by right-clicking the project window, then: `Create/Netcode/NetworkedPrefabsList`.
+3. Add your Network Prefab to the `NetworkPrefabsList`.
+4. Add the `NetworkPrefabsList` to the Network Prefabs Lists that's associated with a `NetworkManager`.
+
+### Spawning a Network Prefab (Overview)
+
+Netcode uses a server authoritative networking model so spawning netcode objects can only be done on a server or host. To spawn a network prefab, you must first create an instance of the network Prefab and then invoke the spawn method on the NetworkObject component of the instance you created.
+_In most cases, you will want to keep the NetworkObject component attached to the root `GameObject` of the network prefab._
+
+By default a newly spawned network Prefab instance is owned by the server unless otherwise specified.
+
+See [Ownership](networkobject.md#ownership) for more information.
+
+The following is a basic example of how to spawn a network Prefab instance (with the default server ownership):
+
+```csharp
+var instance = Instantiate(myPrefab);
+var instanceNetworkObject = instance.GetComponent();
+instanceNetworkObject.Spawn();
+```
+
+The `NetworkObject.Spawn` method takes 1 optional parameter that defaults to `true`:
+```csharp
+public void Spawn(bool destroyWithScene = true);
+```
+
+When you set the destroyWithScene property to `false` it will be treated the same as when you set [Object.DontDestroyOnLoad](https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html). Typically, you use this if you are loading a scene using [LoadSceneMode.Single](https://docs.unity3d.com/ScriptReference/SceneManagement.LoadSceneMode.html) parameter.
+
+[Learn more about Netcode Scene Management here](scenemanagement/scene-management-overview.md)
+
+:::caution You might find it useful to add a `GameObject` property in a `NetworkBehaviour`-derived component to use when assigning a network prefab instance for dynamically spawning. You need to make sure to instantiate a new instance **prior** to spawning. If you attempt to just spawn the actual network prefab instance it can result in unexpected results.
+:::
+
+### Taking Prefab Overrides Into Consideration
+Sometimes, you might want to make a simpler prefab instance to be spawned on server version the override for clients. You should take this into consideration when dynamically spawning a network prefab. If you're running as a host, you want the override to spawn since a host is both a server and a client. However, if you also want to have the ability to run as a dedicated server, you might want to spawn the source network prefab.
+
+There are two ways you can accomplish this, as explained below.
+
+#### Get The Network Prefab Override First
+This option provides you with the overall view of getting the network prefab override, instantiating it, and then spawning it.
+
+```csharp
+var instance = Instantiate(NetworkManager.GetNetworkPrefabOverride(myPrefab));
+var instanceNetworkObject = instance.GetComponent();
+instanceNetworkObject.Spawn();
+```
+In the above script, we get the prefab override using the `NetworkManager.GetNetworkPrefabOverride` method. Then we create an instance of the network prefab override, and finally we spawn the network prefab override instance's NetworkObject.
+
+#### Using InstantiateAndSpawn
+The second option is to leverage the `NetworkSpawnManager.InstantiateAndSpawn` method that handles whether or not to spawn an override for you. The below script is written as if it's being invoked within a `NetworkBehaviour`.
+
+```csharp
+var networkObject = NetworkManager.SpawnManager.InstantiateAndSpawn(myPrefab, ownerId);
+```
+We pass in the overridden source network prefab we want to have instantiated and spawned, and then it returns the instantiated and spawned NetworkObject of the spawned object. The default behavior of `InstantiateAndSpawn` is to spawn the override if running as a host and the original source prefab if running as a server.
+
+`InstantiateAndSpawn` has several parameters to provide more control over this process:
+
+```csharp
+InstantiateAndSpawn(NetworkObject networkPrefab, ulong ownerClientId = NetworkManager.ServerClientId, bool destroyWithScene = false, bool isPlayerObject = false, bool forceOverride = false, Vector3 position = default, Quaternion rotation = default)
+```
+
+Looking at the parameters, we can see it defaults to the server as the owner, ensures that the instantiated NetworkObject won't be destroyed if the scene is unloaded, is not spawned as a player, has a `forceOverride` parameter, and provides a way to set the position and rotation of the newly instantiated NetworkObject.
+
+The `forceOverride` parameter, when set to true, will use the override whether you're running as either server or host.
+
+
+## Destroying / Despawning
+
+By default, a spawned network Prefab instance that is destroyed on the server/host will be automatically destroyed on all clients.
+
+When a client disconnects, all network Prefab instances created during the network session will be destroyed on the client-side by default. If you don't want that to happen, set the `DontDestroyWithOwner` field on NetworkObject to true before despawning.
+
+To do this at runtime:
+
+```csharp
+m_SpawnedNetworkObject.DontDestroyWithOwner = true;
+m_SpawnedNetworkObject.Despawn();
+```
+
+To make this the default from the editor Inspector view:
+
+![image](/img/DontDestroyWithOwner.png)
+
+As an alternative way, you can make the `NetworkObject.DontDestroyWithOwner` property default to `true` by setting it on the NetworkObject itself like in the above screenshot.
+
+### Despawning
+
+Only a server can despawn a NetworkObject, and the default despawn behavior is to destroy the associated GameObject. to despawn but not destroy a NetworkObject, you should call `NetworkObject.Despawn` and pass false as the parameter. Clients will always be notified and will mirror the despawn behavior. If you despawn and destroy on the server then all clients will despawn and then destroy the `GameObject` that the `NetworkObjet` component is attached to.
+
+On the client side, you should never call `Object.Destroy` on any `GameObject` with a NetworkObject component attached to it (this isn't supported and will cause an exception to be thrown). If you want to use a more client authority model, have the client with ownership invoke an RPC to defer the despawning on server side.
+
+The only way to despawn NetworkObject for a specific client is to use `NetworkObject.NetworkHide`.
+See: [Object Visibility](object-visibility.md) for more information on this.
+
+:::warning
+If you have `GameObject` children, with `NetworkBehaviour` components attached, of a parent `GameObject`, with a NetworkObject component attached, you can't disable the `GameObject` children before spawning or despawning. Doing so, in v1.0.0, can cause unexpected results and it's recommended to make sure all children are enabled in the hierarchy before spawning or despawning.
+:::
+
+## Dynamically Spawned Network Prefabs
+
+Netcode for GameObjects uses the term "dynamically spawned" to convey that the NetworkObject is being spawned via user specific code. Whereas a player or in-scene placed NetworkObject (with scene management enabled) is typically spawned by Netcode for GameObjects. There are several ways to spawn a network Prefab via code:
+
+### Dynamic Spawning (non-pooled):
+
+This type of dynamically spawned NetworkObject typically is a simple wrapper class that holds a reference to the Prefab asset. In the example below, the `NonPooledDynamicSpawner.PrefabToSpawn` property holds a reference to the network prefab:
+
+```csharp
+ public class NonPooledDynamicSpawner : NetworkBehaviour
+ {
+ public GameObject PrefabToSpawn;
+ public bool DestroyWithSpawner;
+ private GameObject m_PrefabInstance;
+ private NetworkObject m_SpawnedNetworkObject;
+
+ public override void OnNetworkSpawn()
+ {
+ // Only the server spawns, clients will disable this component on their side
+ enabled = IsServer;
+ if (!enabled || PrefabToSpawn == null)
+ {
+ return;
+ }
+ // Instantiate the GameObject Instance
+ m_PrefabInstance = Instantiate(PrefabToSpawn);
+
+ // Optional, this example applies the spawner's position and rotation to the new instance
+ m_PrefabInstance.transform.position = transform.position;
+ m_PrefabInstance.transform.rotation = transform.rotation;
+
+ // Get the instance's NetworkObject and Spawn
+ m_SpawnedNetworkObject = m_PrefabInstance.GetComponent();
+ m_SpawnedNetworkObject.Spawn();
+ }
+
+ public override void OnNetworkDespawn()
+ {
+ if (IsServer && DestroyWithSpawner && m_SpawnedNetworkObject != null && m_SpawnedNetworkObject.IsSpawned)
+ {
+ m_SpawnedNetworkObject.Despawn();
+ }
+ base.OnNetworkDespawn();
+ }
+ }
+```
+
+Consumable and/or items that can be picked up by a player or NPC(that is, a weapon, health, potion, etc.) would be some examples of when you might want to use non-pooled dynamically spawned `NetworkObjects`.
+
+:::caution
+While the NonPooledDynamicSpawner example is one of the simplest ways to spawn a NetworkObject, there is a memory allocation cost associated with instantiating and destroying the GameObject and all attached components. This design pattern can sometimes be all you need for the netcode game asset you are working with, and other times you might want to respawn/re-use the object instance. When performance is a concern and you want to spawn more than just one NetworkObject during the lifetime of the spawner or want to repeatedly respawn a single NetworkObject, the less proccessor and memory allocation intensive technique is to use [pooled dynamic spawning](#pooled-dynamic-spawning).
+:::
+
+:::note
+Really, when we use the term "non-pooled" more often than not we are referring to the concept that a `GameObject` will be instantiated on both the server and the clients each time an instance is spawned.
+:::
+
+### Pooled Dynamic Spawning
+
+Pooled dynamic spawning is when netcode objects (`GameObject` with one NetworkObject component) aren't destroyed on the server or the client when despawned. Instead, specific components are just disabled (or the `GameObject` itself) when a netcode object is despawned. A pooled dynamically spawned netcode object is typically instantiated during an already memory allocation heavy period of time (like when a scene is loaded or even at the start of your application before even establishing a network connection). Pooled dynamically spawned netcode objects are more commonly thought of as more than one netcode object that can be re-used without incurring the memory allocation and initialization costs. However, you might also run into scenarios where you need just one dynamically spawned netcode object to be treated like a pooled dynmically spawned netcode object.
+
+Fortunately, Netcode for GameObjects provides you with a way to be in control over the instatiation and destruction process for one or many netcode objects by via the `INetworkPrefabInstanceHandler` interface. Any `INetworkPrefabInstanceHandler`implementation should be registered with the `NetworkPrefabHandler`(for multiple netcode objects see [Object Pooling](../advanced-topics/object-pooling.md)) to accomplish this.
+
+The easiest way to not destroy a network Prefab instance is to have something, other than the instance itself, keeping a reference to the instance. This way you can simply set the root `GameObject` to be inactive when it's despawned while still being able to set it active when the same network Prefab type needs to be respawned. Below is one example of how you can accomplish this for a single netcode object instance:
+
+```csharp
+public class SinglePooledDynamicSpawner : NetworkBehaviour, INetworkPrefabInstanceHandler
+{
+ public GameObject PrefabToSpawn;
+ public bool SpawnPrefabAutomatically;
+
+ private GameObject m_PrefabInstance;
+ private NetworkObject m_SpawnedNetworkObject;
+
+
+ private void Start()
+ {
+ // Instantiate our instance when we start (for both clients and server)
+ m_PrefabInstance = Instantiate(PrefabToSpawn);
+
+ // Get the NetworkObject component assigned to the Prefab instance
+ m_SpawnedNetworkObject = m_PrefabInstance.GetComponent();
+
+ // Set it to be inactive
+ m_PrefabInstance.SetActive(false);
+ }
+
+ private IEnumerator DespawnTimer()
+ {
+ yield return new WaitForSeconds(2);
+ m_SpawnedNetworkObject.Despawn();
+ StartCoroutine(SpawnTimer());
+ yield break;
+ }
+
+ private IEnumerator SpawnTimer()
+ {
+ yield return new WaitForSeconds(2);
+ SpawnInstance();
+ yield break;
+ }
+
+ ///
+ /// Invoked only on clients and not server or host
+ /// INetworkPrefabInstanceHandler.Instantiate implementation
+ /// Called when Netcode for GameObjects need an instance to be spawned
+ ///
+ public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation)
+ {
+ m_PrefabInstance.SetActive(true);
+ m_PrefabInstance.transform.position = transform.position;
+ m_PrefabInstance.transform.rotation = transform.rotation;
+ return m_SpawnedNetworkObject;
+ }
+
+ ///
+ /// Client and Server side
+ /// INetworkPrefabInstanceHandler.Destroy implementation
+ ///
+ public void Destroy(NetworkObject networkObject)
+ {
+ m_PrefabInstance.SetActive(false);
+ }
+
+ public void SpawnInstance()
+ {
+ if (!IsServer)
+ {
+ return;
+ }
+
+ if (m_PrefabInstance != null && m_SpawnedNetworkObject != null && !m_SpawnedNetworkObject.IsSpawned)
+ {
+ m_PrefabInstance.SetActive(true);
+ m_SpawnedNetworkObject.Spawn();
+ StartCoroutine(DespawnTimer());
+ }
+ }
+
+ public override void OnNetworkSpawn()
+ {
+ // We register our network Prefab and this NetworkBehaviour that implements the
+ // INetworkPrefabInstanceHandler interface with the Prefab handler
+ NetworkManager.PrefabHandler.AddHandler(PrefabToSpawn, this);
+
+ if (!IsServer || !SpawnPrefabAutomatically)
+ {
+ return;
+ }
+
+ if (SpawnPrefabAutomatically)
+ {
+ SpawnInstance();
+ }
+ }
+
+ public override void OnNetworkDespawn()
+ {
+ if (m_SpawnedNetworkObject != null && m_SpawnedNetworkObject.IsSpawned)
+ {
+ m_SpawnedNetworkObject.Despawn();
+ }
+ base.OnNetworkDespawn();
+ }
+
+ public override void OnDestroy()
+ {
+ // This example destroys the
+ if (m_PrefabInstance != null)
+ {
+ // Always deregister the prefab
+ NetworkManager.Singleton.PrefabHandler.RemoveHandler(PrefabToSpawn);
+ Destroy(m_PrefabInstance);
+ }
+ base.OnDestroy();
+ }
+}
+```
+
+You might run across a situation where you still want other components on the root `GameObject` of your network Prefab instance to remain active. Primarily, you want to be able to easily disable the components that would normally be active when the netcode object is considered spawned.
+
+Below is an example of what a non-pooled friendly Prefab might look like:
+
+![image](/img/non-pooled-friendly-prefab.png)
+
+The issues you might run into with the above Prefab hierarchy is that everything is on a single `GameObject`, and as such if you wanted to disable the `MeshRenderer` and the `NetworkObjectLabel`, [one of our classes in the Netcode for GameObjects test project](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/f0631414e5a5358a5ac7811d43273b1a82a60ca9/testproject/Assets/Scripts/NetworkObjectLabel.cs#L4), you would need to get those component types before disabling them (that is, during `Start` or `OnNetworkSpawn` or get them when `OnNetworkDespawn` is invoked).
+
+To reduce this level of complexity, a more "pooled dynamic spawning" friendly Prefab heirarchy might look like this:
+
+![image](/img/pooled-friendly-prefab.png)
+
+The NetworkObject sits at the root `GameObject` of the network prefab. The child `GameObject`, SpawnedComponents, then has everything that you might want to have disabled when the network Prefab instance isn't spawned:
+
+![image](/img/pooled-friendly-prefab-child.png)
+
+This reduces the complexity down to setting the SpawnedComponents `GameObject` to inactive, which will also disable all of the components attached to it.
+
+:::tip
+Using this type of a hierarchical separation is useful in many ways (especially when you have a much more complex prefab). For more complex prefabs, you can further expand this pattern into specific categories (that is, visuals, physics, sound, etc) which will provide you with a more macrocosmic way to control enabling or disabling many different components without having to have references to all of them.
+:::
+
+## In-Scene Placed NetworkObject
+
+Any objects in the scene with active and spawned NetworkObject components will get automatically replicated by Netcode. There is no need to manually spawn them when scene management is enabled in the `NetworkManager`. In-scene placed `NetworkObjects` should typically be used like a "static" netcode object, where the netcode object is typically spawned upon the scene being loaded on the server-side and synchronized with clients once they finish loading the same scene.
+
+[Learn more about In-Scene Placed `NetworkObjects`](scenemanagement/inscene-placed-networkobjects.md)
+
+Generally, there are **two** modes that define how an in-scene placed NetworkObject is synchronized.
+
+- Soft Synchronization (Scene Management enabled)
+- Prefab Synchronization (Scene Management disabled)
+
+### Soft Synchronization
+
+`SoftSync` or "Soft Synchronization" is a term you might run across if you run into any issue with in-scene placed `NetworkObjects`. Soft synchronization only occurs if scene management is enabled in the `NetworkManager` properties. If you receive a "soft synchronization error", then this typically means that a client can't locate the same in-scene placed NetworkObject after loading a scene.
+
+### Prefab Synchronization
+
+`PrefabSync` or "Prefab Synchronization" is used if scene management is disabled in the `NetworkManager`. With Prefab synchronization, every in-scene placed NetworkObject has to be a network Prefab and must be registered with `NetworkPrefabs` list. When a client starts, Netcode will destroy all existing in-scene placed NetworkObjects and spawn its corresponding Prefab from the `NetworkPrefabs` list instead. This also means that you will have to implement your own scene manager and handle how you synchronize clients when they join a network session.
+
+**PrefabSync is ONLY recommended for advanced development and/or multi project setups**.
diff --git a/versioned_docs/version-2.0.0/basics/object-visibility.md b/versioned_docs/version-2.0.0/basics/object-visibility.md
new file mode 100644
index 000000000..9e3d637ae
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/object-visibility.md
@@ -0,0 +1,120 @@
+---
+id: object-visibility
+title: Object visibility
+sidebar_label: Object visibility
+---
+
+## What Is NetworkObject Visibility?
+Object (NetworkObject) visibility is a Netcode for GameObjects term used to describe whether a NetworkObject is visible to one or more clients as it pertains to a netcode/network perspective. When a NetworkObject is visible to a client, the server will assure the client has a spawned version (a clone) of the NetworkObject. This also means that all network traffic generated by the server for the visible NetworkObject will be sent to all clients that are aware (that is, it's "visible to the clients") of it. Likewise, when a NetworkObject is "hidden" (that is, not visible) from a client, then the client will despawn and destroy the NetworkObject if it was previously visible and no network traffic generated by the hidden NetworkObject will be received by the client(s) it's hidden from.
+
+
+## Using Visibility
+
+One way to determine visibility is to assign a callback to `NetworkObject.CheckObjectVisibility`. This callback is invoked when new clients connect or just before the associated NetworkObject is spawned. Looking at the example below, we can see the callback includes a client identifier (clientId) value as a parameter which is used to determine whether the NetworkObject is visible to the client. If `NetworkObject.CheckObjectVisibility` isn't assigned, then Netcode for GameObjects assumes it's visible to all clients.
+
+### CheckObjectVisibility Callback Example
+```csharp
+public class VisibilityCheckExample : NetworkBehaviour
+{
+ public bool ContinuallyCheckVisibility = true;
+ public float VisibilityDistance = 5.0f;
+
+ ///
+ /// This is automatically invoked when spawning the network prefab
+ /// relative to each client.
+ ///
+ /// client identifier to check
+ /// true/false whether it is visible to the client or not
+ private bool CheckVisibility(ulong clientId)
+ {
+ // If not spawned, then always return false
+ if (!IsSpawned)
+ {
+ return false;
+ }
+
+ // We can do a simple distance check between the NetworkObject instance position and the client
+ return Vector3.Distance(NetworkManager.ConnectedClients[clientId].PlayerObject.transform.position, transform.position) <= VisibilityDistance;
+ }
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer)
+ {
+ // The server handles visibility checks and should subscribe when spawned locally on the server-side.
+ NetworkObject.CheckObjectVisibility += CheckVisibility;
+ // If we want to continually update, we don't need to check every frame but should check at least once per tick
+ if (ContinuallyCheckVisibility)
+ {
+ NetworkManager.NetworkTickSystem.Tick += OnNetworkTick;
+ }
+ }
+ base.OnNetworkSpawn();
+ }
+
+ private void OnNetworkTick()
+ {
+ // If CheckObjectVisibility is enabled, check the distance to clients
+ // once per network tick.
+ foreach (var clientId in NetworkManager.ConnectedClientsIds)
+ {
+ var shouldBeVisibile = CheckVisibility(clientId);
+ var isVisibile = NetworkObject.IsNetworkVisibleTo(clientId);
+ if (shouldBeVisibile && !isVisibile)
+ {
+ // Note: This will invoke the CheckVisibility check again
+ NetworkObject.NetworkShow(clientId);
+ }
+ else if (!shouldBeVisibile && isVisibile)
+ {
+ NetworkObject.NetworkHide(clientId);
+ }
+ }
+ }
+
+ public override void OnNetworkDespawn()
+ {
+ if (IsServer)
+ {
+ NetworkObject.CheckObjectVisibility -= CheckVisibility;
+ NetworkManager.NetworkTickSystem.Tick -= OnNetworkTick;
+ }
+ base.OnNetworkDespawn();
+ }
+}
+```
+
+### Additional Visibility Methods and Properties:
+The `CheckObjectVisibility` callback helps you determine if a NetworkObject is visible to a specific client when the NetworkObject is spawned. However, you might have the need to change a NetworkObject's visibility after it's spawned. To change the visibility of a NetworkObject that is already spawned, you can use the following methods:
+
+Make a NetworkObject visible to a single client:
+```csharp
+NetworkObject netObject = GetComponent();
+netObject.NetworkShow(clientIdToShowTo);
+```
+
+Make a NetworkObject invisible/hidden from a single client:
+```csharp
+NetworkObject netObject = GetComponent();
+netObject.NetworkHide(clientIdToHideFrom);
+```
+
+Make several NetworkObjects visible to a single client (static method):
+```csharp
+/// networkObjects is of type List
+NetworkObject.NetworkShow(networkObjects, clientId);
+```
+
+Make several NetworkObjects invisible/hidden to a single client (static method):
+```csharp
+/// networkObjects is of type List
+NetworkObject.NetworkHide(networkObjects, clientId);
+```
+
+Spawn a NetworkObject with no observers (_i.e. not visible to any clients initially_):
+```csharp
+NetworkObject.SpawnWithObservers = false;
+NetworkObject.Spawn();
+```
+
+See [Spawning With (or Without) Observers](networkobject.md#spawning-with-or-without-observers) for more information.
diff --git a/versioned_docs/version-2.0.0/basics/ownership.md b/versioned_docs/version-2.0.0/basics/ownership.md
new file mode 100644
index 000000000..349b55381
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/ownership.md
@@ -0,0 +1,93 @@
+---
+id: ownership
+title: Understanding ownership and authority
+---
+
+By default, Netcode for GameObjects assumes a [client-server topology](../terms-concepts/client-server.md), in which the server owns all NetworkObjects (with [some exceptions](networkobject.md#ownership)) and has ultimate authority over [spawning and despawning](object-spawning.md).
+
+Netcode for GameObjects also supports building games with a [distributed authority topology](../terms-concepts/distributed-authority.md), which provides more options for ownership and authority over NetworkObjects.
+
+## Ownership and distributed authority
+
+In a distributed authority setting, authority over NetworkObjects isn't bound to a single server, but distributed across clients depending on a NetworkObject's [ownership permission settings](#ownership-permission-settings). NetworkObjects with the distributable permission set are automatically distributed amongst clients as they connect and disconnect.
+
+When a client starts a distributed authority session it spawns its player, locks the local player's permissions so that no other client can take ownership, and then spawns some NetworkObjects. At this point, Client-A has full authority over the distributable spawned objects and its player object.
+
+![Distributed authority start](/img/distributed-authority-start.jpg)
+
+When another player joins, as in the diagram below, authority over distributable objects is split between both clients. Distributing the NetworkObjects in this way reduces the overall processing and bandwidth load for both clients. The same distribution happens when a player leaves, either gracefully or unexpectedly. The ownership and last known state of the subset of objects owned by the leaving player is transferred over to the remaining connected clients with no interruption in gameplay.
+
+![Distributed authority new client](/img/distributed-authority-new-client.jpg)
+
+### Ownership permission settings
+
+The following ownership permission settings, defined by `NetworkObject.OwnershipStatus`, are only available when running in distributed authority mode:
+
+* `None`: Ownership of this NetworkObject is considered static and can't be redistributed, requested, or transferred (a Player would have this, for example).
+* `Distributable`: Ownership of this NetworkObject is automatically redistributed when a client joins or leaves, as long as ownership is not locked or a request is pending.
+* `Transferable`: Ownership of this NetworkObject can be transferred immediately, as long as ownership is not locked and there are no pending requests.
+* `RequestRequired`: Ownership of this NetworkObject must be requested before it can be transferred and will always be locked after transfer.
+
+You can also use `NetworkObject.SetOwnershipLock` to lock and unlock the permission settings of a NetworkObject for a period of time, preventing ownership changes on a temporary basis.
+
+## Checking for authority
+
+### `HasAuthority`
+
+The `HasAuthority` property, which is available on both NetworkObjects and NetworkBehaviours, is session-mode agnostic and works in both distributed authority and client-server contexts. It's recommended to use `HasAuthority` whenever you're working with individual objects, regardless of whether you're using a distributed authority or client-server topology.
+
+```
+public class MonsterAI : NetworkBehaviour
+{
+ public override void OnNetworkSpawn()
+ {
+ if (!HasAuthority)
+ {
+ return;
+ }
+ // Authority monster init script here
+ base.OnNetworkSpawn();
+ }
+
+ private void Update()
+ {
+ if (!IsSpawned || !HasAuthority)
+ {
+ return;
+ }
+ // Authority updates monster AI here
+ }
+}
+```
+
+Using distributed authority with Netcode for GameObjects requires a shift in the understanding of authority: instead of authority belonging to the server in all cases, it belongs to whichever client instance currently has authority. This necessitates a shift away from using local, non-replicated properties to store pertinent states; instead, [NetworkVariables](networkvariable.md) should be used to keep states synchronized and saved when all clients disconnect from a session or ownership is transferred to another client.
+
+Distributed authority supports all built-in NetworkVariable data types. Since there's no concept of an authoritative server in a distributed authority session, all NetworkVariables are automatically configured with owner write and everyone read permissions.
+
+### `IsServer`
+
+`IsServer` or `!IsServer` is the traditional client-server method of checking whether the current context has authority, and is only available in client-server topologies (because distributed authority games have no single authoritative server). You can use a mix of `HasAuthority` and `IsServer` when building a client-server game: `HasAuthority` is recommended when performing object-specific operations, while `IsServer` can be useful to check for authority when performing global actions.
+
+```
+public class MonsterAI : NetworkBehaviour
+{
+ public override void OnNetworkSpawn()
+ {
+ if (!IsServer)
+ {
+ return;
+ }
+ // Server-side monster init script here
+ base.OnNetworkSpawn();
+ }
+
+ private void Update()
+ {
+ if (!IsSpawned || !IsServer)
+ {
+ return;
+ }
+ // Server-side updates monster AI here
+ }
+}
+```
diff --git a/versioned_docs/version-2.0.0/basics/playerobjects.md b/versioned_docs/version-2.0.0/basics/playerobjects.md
new file mode 100644
index 000000000..fa0439b42
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/playerobjects.md
@@ -0,0 +1,102 @@
+---
+id: playerobjects
+title: PlayerObjects and player prefabs
+---
+
+PlayerObjects are an optional feature in Netcode for GameObjects that you can use to assign a [NetworkObject](networkobject.md) to a specific client. A client can only have one PlayerObject.
+
+PlayerObjects are instantiated by reference to a player prefab, which defines the characteristics of the PlayerObject.
+
+## Defining defaults for player prefabs
+
+If you're using `UnityEngine.InputSystem.PlayerInput` or `UnityEngine.PhysicsModule.CharacterController` components on your player prefab(s), you should disable them by default and only enable them for the local client's PlayerObject. Otherwise, you may get events from the most recently instantiated player prefab instance, even if it isn't the local client instance.
+
+You can disable these components in the **Inspector** view on the prefab itself, or disable them during `Awake` in one of your `NetworkBehaviour` components. Then you can enable the components only on the owner's instance using code like the example below:
+
+```
+PlayerInput m_PlayerInput;
+private void Awake()
+{
+ m_PlayerInput = GetComponent();
+ m_PlayerInput.enabled = false;
+}
+
+public override void OnNetworkSpawn()
+{
+ m_PlayerInput.enabled = IsOwner;
+ base.OnNetworkSpawn();
+}
+
+public override void OnNetworkDespawn()
+{
+ m_PlayerInput.enabled = false;
+ base.OnNetworkDespawn();
+}
+```
+
+## Spawning PlayerObjects
+
+## Session-mode agnostic methods
+
+Netcode for GameObjects can spawn a default PlayerObject for you. If you enable **Create Player Prefab** in the [NetworkManager](../components/networkmanager.md) and assign a valid prefab, then Netcode for GameObjects spawns a unique instance of the designated player prefab for each connected and approved client, referred to as the PlayerObject.
+
+To manually spawn an object as PlayerObject, use the following method:
+
+```csharp
+GetComponent().SpawnAsPlayerObject(clientId);
+```
+
+If the player already had a prefab instance assigned, then the client owns the NetworkObject of that prefab instance unless there's additional server-side specific user code that removes or changes the ownership.
+
+Alternatively, you can choose not to spawn anything immediately after a client connects and instead use a [NetworkBehaviour component](networkbehaviour.md) to handle avatar/initial player prefab selection. This NetworkBehaviour component could be configured by the server or initiating session owner, or be associated with an [in-scene](scenemanagement/inscene-placed-networkobjects.md) or [dynamically spawned](object-spawning.md#dynamically-spawned-network-prefabs) NetworkObject, as suits the needs of your project.
+
+### Client-server contexts only
+
+In addition to the [session-mode agnostic spawning methods](#session-mode-agnostic-methods) above, you can assign a unique player prefab on a per-client connection basis using a client [connection approval process](connection-approval.md) when in [client-server contexts](../terms-concepts/client-server.md).
+
+### Distributed authority contexts only
+
+In addition to the [session-mode agnostic spawning methods](#session-mode-agnostic-methods) above, you can use the [`OnFetchLocalPlayerPrefabToSpawn`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkManager.html#Unity_Netcode_NetworkManager_OnFetchLocalPlayerPrefabToSpawn) method to assign a unique player prefab on a per-client basis when in [distributed authority contexts](../terms-concepts/distributed-authority.md).
+
+To use `OnFetchLocalPlayerPrefabToSpawn` in your project, assign a callback handler to `OnFetchLocalPlayerPrefabToSpawn` and whatever the client script returns is what will be spawned for that client. Ensure that the prefab being spawned is in a NetworkPrefabList [registered with the NetworkManager](object-spawning.md#registering-a-network-prefab).
+
+If you don't assign a callback handler to `OnFetchLocalPlayerPrefabToSpawn`, then the default behaviour is to return the `NetworkConfig.PlayerPrefab` (or null if neither are set).
+
+:::note `AutoSpawnPlayerPrefabClientSide` required
+For `OnFetchLocalPlayerPrefabToSpawn` to work, [`AutoSpawnPlayerPrefabClientSide`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkManager.html#Unity_Netcode_NetworkManager_AutoSpawnPlayerPrefabClientSide) must be enabled.
+:::
+
+## PlayerObject spawning timeline
+
+When using automatic methods of PlayerObject spawning (such as enabling **Create Player Prefab** in the [NetworkManager](../components/networkmanager.md)), PlayerObjects are spawned at different times depending on whether you have [scene management](scenemanagement/scene-management-overview.md) enabled.
+
+- When scene management is disabled, PlayerObjects are spawned when a joining client's connection is approved.
+- When scene management is enabled, PlayerObjects are spawned when a joining client finishes initial synchronization.
+
+If you choose not to automatically spawn a PlayerObject when a client joins, then the timing of when a PlayerObject is spawned is up to you based on your own implemented code.
+
+## Finding PlayerObjects
+
+To find a PlayerObject for a specific client ID, you can use the following methods:
+
+Within a NetworkBehaviour, you can check the local `NetworkManager.LocalClient` to get the local PlayerObjects:
+
+```csharp
+NetworkManager.LocalClient.PlayerObject
+```
+
+Conversely, on the server-side, if you need to get the PlayerObject instance for a specific client, you can use the following:
+
+```csharp
+NetworkManager.Singleton.ConnectedClients[clientId].PlayerObject;
+```
+
+To find your own player object just pass `NetworkManager.Singleton.LocalClientId` as the `clientId` in the sample above.
+
+## Additional resources
+
+- [NetworkObject](networkobject.md)
+- [NetworkManager](../components/networkmanager.md)
+- [Distributed authority topologies](../terms-concepts/distributed-authority.md)
+- [Client-server topologies](../terms-concepts/client-server.md)
+- [Object spawning](objectspawning.md)
diff --git a/versioned_docs/version-2.0.0/basics/race-conditions.md b/versioned_docs/version-2.0.0/basics/race-conditions.md
new file mode 100644
index 000000000..08f2bd793
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/race-conditions.md
@@ -0,0 +1,40 @@
+---
+id: race-conditions
+title: Ownership race conditions
+---
+
+:::info Distributed authority only
+
+The race conditions described on this page only affect games using a [distributed authority topology](../terms-concepts/distributed-authority.md).
+
+:::
+
+Ownership race conditions can occur when two players (clients) want to take ownership of the same NetworkObject at the same time. The following diagram illustrates a typical race condition where two clients (A and B) want to take ownership of an object (the star owned by Client-C) simultaneously.
+
+![Race condition](/img/race-condition.jpg)
+
+## Potential race conditions
+
+When two clients attempt to take ownership of the same NetworkObject at the same time, the outcome can vary depending on the `OwnershipStatus` of the NetworkObject.
+
+* `OwnershipStatus.None`: If ownership status isn't transferable, but Client-A and Client-B attempt to request ownership anyway, they’ll both receive a local ownership notification, via `NetworkObject.OnOwnershipPermissionsFailure`, with a status of `OwnershipPermissionsFailureStatus.NotTransferable`. This only occurs if the user script of both clients don't check the NetworkObject ownership permissions first.
+* `OwnershipStatus.Distributable`: If this is the only ownership flag on the NetworkObject, then the end result for both clients is the same as `OwnershipStatus.None` above.
+* `OwnershipStatus.RequestRequired`: If ownership transfer requires a request, then there are a few potential outcomes:
+ * If both clients attempt to locally change the ownership of the NetworkObject without first making a request, they'll both receive a local ownership notification, via `NetworkObject.OnOwnershipPermissionsFailure`, that they must request ownership (`OwnershipPermissionsFailureStatus.RequestRequired`).
+ * If both clients send a request for ownership to the authoritative client, then it can be treated as a 'first come first serve' request (this is the default response of an authoritative client) or, if the user script assigns a callback handler to the `NetworkObject.OnOwnershipRequested`, it will be up to the user script as to whether Client-A or Client-B is granted ownership. This is still handled in a 'first come first serve' fashion, but does provide an additional level of control over granting ownership upon request.
+* `OwnershipStatus.Transferable`: If ownership is transferable and requests are not required, then ownership can be acquired by both clients simultaneously if the action or user script performed happens at the same time and occurs within a period of time less than the average RTT of both clients. This is where a true race condition can occur, and the end result can be ownership getting out of sync across clients. See the diagram below.
+
+![True race condition](/img/true-race-condition.jpg)
+
+## Preventing race conditions
+
+There are broadly three ways to help prevent these types of race conditions.
+
+* **Require ownership requests**: You can use the `RequestRequired` permission flag to ensure that any changes in ownership require a request first. This prevents race conditions, but requires two RTTs to complete the transfer of ownership, and can be too slow in situations where acquisition of ownership is time sensitive.
+* **Use the distributed authority service**: The distributed authority service provides a certain level of governance over ownership transfer during a change in ownership of a NetworkObject with just the `Transferable` flag set.
+* **Lock ownership**: When changing ownership, the user script can lock ownership for any period of time using `NetworkObject.SetOwnershipLock`. If this operation is performed immediately after changing ownership, then both the change in ownership and the updated ownership permissions are sent in the same message batch at the end of the frame. This helps the distributed authority service to govern and prevent race conditions more effectively, while also preventing immediate turnover of ownership to another client shortly after (within a few network ticks period of time) changing ownership locally.
+
+How you choose to prevent race conditions depends on how quickly you need to transfer ownership from one client to another, and how much contingency you intend to implement.
+
+* `OwnershipStatus.RequestRequired`: Is not prone to race conditions, but can take two RTTs (one RTT for the requestor and one RTT for the grantor/authority). If immediate ownership transfer is not required (that is, acquiring ownership in the same frame), then this is the recommended permissions setting to use.
+* `OwnershipStatus.Transferable`: If not used in conjunction with ownership locking, can be prone to potential race-like conditions. Moreover, ownership could be transferred, locally, to a client for a full RTT period before receiving a change in ownership message that gives ownership to a client that had changed ownership slightly earlier. While this type of scenario can be managed, it’s worth noting that while immediate (i.e. `Transferable`) ownership transfer permissions provide a much faster transfer in ownership, it should be used with caution and a denial of ownership contingency script could be needed to handle such scenarios.
diff --git a/versioned_docs/version-2.0.0/basics/scenemanagement/client-synchronization-mode.md b/versioned_docs/version-2.0.0/basics/scenemanagement/client-synchronization-mode.md
new file mode 100644
index 000000000..5c6cd9f0e
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/scenemanagement/client-synchronization-mode.md
@@ -0,0 +1,55 @@
+---
+id: client-synchronization-mode
+title: Client synchronization mode
+sidebar_label: Client synchronization mode
+---
+
+## Introduction
+Client synchronization occurs when immediately after a client connects to a host or server and the connection is approved. During the client synchronization process, the server will determine everything that a client might need to know about in order to join an in-progress network session (networked game session). Netcode for GameObjects provides you with the ability to select the client synchronization mode that best suits your project's needs. During client synchronization a client will automatically set its local client synchronization mode to match that of the server or host setting.
+
+The client synchronization mode should be set when the server or host is first provided via the `NetworkSceneManager.SetClientSynchronizationMode` method that takes a [`LoadSceneMode`](https://docs.unity3d.com/ScriptReference/SceneManagement.LoadSceneMode.html) value as a parameter. Each client synchronization mode behaves in a similar way to loading a scene based on the chosen `LoadSceneMode`.
+
+:::note Distributed authority contexts
+When using a [distributed authority network topology](../../terms-concepts/distributed-authority.md), any client can set the client synchronization mode when they're promoted to session owner. Late-joining clients are synchronized using whatever setting the current session owner has.
+:::
+
+## Single Client Synchronization Mode
+_(Existing Client-Side Scenes Unloaded During Synchronization)_
+
+If you are already familiar with Netcode for GameObjects, then this is most likely the client synchronization mode you are familiar with. When client synchronization mode is set to `LoadSceneMode.Single`, a client treats the synchronization similar to that of loading a scene using `LoadSceneMode.Single`. When loading a scene in `LoadSceneMode.Single`, any currently loaded scene will be unloaded and then the new scene is loaded. From a client synchronization mode perspective, the host or server will always have a default active scene. As such, the default active scene is loaded first in `LoadSceneMode.Single` mode and then any other additional scenes that need to be synchronized are loaded as `LoadSceneMode.Additive`.
+
+
+This means any scene that is loaded on the client side prior to being synchronized will be unloaded when the first/default active scene is loaded.
+
+![image](/img/ClientSynchronizationModeSingle.png)
+
+The above image shows a high level overview of single mode client synchronization. For this scenario, a client had just left a network session where the game session was on Level 1. The client still has two common scenes to all levels, Enemy Spawner and World Items scenes, and the Level scenes contain unique assets/settings based on the level number reached. The client then joins a new game session that is on Level 3. With single mode client synchronization, the currently active scene on the server-side is the first scene loaded in `LoadSceneMode.Single` on the client-side (thus why we refer to the client synchronization mode as "single"). By default, loading a new scene in `LoadSceneMode.Single` mode will unload all currently loaded scenes before loading the new scene. Then, for each additional scene that the server requires the client to have loaded in order to be fully synchronized, all remaining scenes are loaded additively (`LoadSceneMode.Additive`).
+
+For some games/projects this type of client synchronization is all that is needed. However, there are scenarios where you might want to have more control over which scenes are unloaded (if any) during the client synchronization process or you might want to reduce the client synchronization time by having certain commonly shared scenes pre-loaded (and possibly never unloaded) prior to connecting. If your project's needs falls into this realm, then the recommended solution is to use additive client synchronization mode.
+
+## Additive Client Synchronization Mode
+_(Existing Client-Side Scenes Used During Synchronization)_
+
+Additive client synchronization is mode similar to additive scene loading in that any scenes the client has currently loaded, prior to connecting to a server or host, will remain loaded and be taken into consideration as scenes to be used during the synchronization process.
+
+This can be particularly useful if you have common UI element scenes (i.e. menu interfaces) that you would like to persist throughout the duration of the application instance's life cycle (i.e. from the time the application starts to the time it is stopped/exited). It can also be useful to have certain scenes pre-loaded ahead of time to reduce load times when connecting to an existing network session.
+
+![image](/img/ClientSynchronizationModeAdditive.png)
+
+In the above image we can see a scenario where a server has a Menu UI Scene that it ignores using `NetworkSceneManager.VerifySceneBeforeLoading`, two scenes that the project is configured to always have pre-loaded _(Enemy Spawner and World Items scenes)_, and the server has reached "level 3" of the networked game session so it has the Level 3 scene loaded. The client side almost mirrors the server side (scenes loaded relative) when it began the synchronization process. The only difference between the server and the client was the Level 3 scene that the client has to load in order to be fully synchronized with the server.
+
+_If the server was running in client synchronization mode `LoadSceneMode.Single`, the client would have had to load (at a minimum) three scenes if the Level3 scene was the currently active scene on the server side (not to mention having to reload the Menu UI scene if the user on the client side wanted to adjust a global setting like the audio level of the game). By using `LoadSceneMode.additive` client synchronization, the synchronizing client only has to load one scene in order to be "scene synchronized" with the server._
+
+While additive client synchronization mode might cover the majority of your project's needs, you could find scenarios where you need to be a bit more selective with the scenes a client should keep loaded and the scenes that should be unloaded. There are two additional settings that you can use (only when client synchronization mode set to `LoadSceneMode.Additive`) to gain further control over this process.
+
+### NetworkSceneManager.PostSynchronizationSceneUnloading
+When this flag is set on the client side any scenes that were not synchronized with the server or host will be unloaded. This can be useful if your project primarily uses `LoadSceneMode.Additive` to load the majority of your scenes (i.e. sometimes referred to a "bootstrap scene loading approach"). A client could have additional scenes specific to a portion of your game/project from a previous game network session that are not pertinent in a newly established game network session. Any scenes that are not required to become fully synchronized with the current server or host will get unloaded upon the client completing the synchronization process.
+
+### NetworkSceneManager.VerifySceneBeforeUnloading
+When `NetworkSceneManager.PostSynchronizationSceneUnloading` is set to `true` and the client synchronization mode is `LoadSceneMode.Additive`, if this callback is set then for each scene that is about to be unloaded the set callback will be invoked. If it returns `true` the scene will be unloaded and if it returns `false` the scene will remain loaded. This is useful if you have specific scenes you want to persist (menu interfaces etc.) but you also want some of the unused scenes (i.e. not used during synchronization) to be unloaded.
+
+![image](/img/ClientSynchronizationModeAdditive2.png)
+
+Let's take the previous client synchronization mode scenario into consideration with the client side having `NetworkSceneManager.PostSynchronizationSceneUnloading` set to `true` and registering a callback for `NetworkSceneManager.VerifySceneBeforeUnloading` where it returns false when client synchronization attempts to unload the Menu UI Scene. Let's also assume this game allows clients to join other network sessions while still in a current network session and that the client had just come from a previous game where the server was still on "level 1" (so the client has the level 1 scene still loaded). When the client begins to synchronize the two pre-loaded scenes are used for synchronization, the client still has to load the Level 3 scene, but at the end of the synchronization `NetworkSceneManager` begins to unload any remaining scenes not synchronized by the server and the client. When the Menu UI Scene is checked if it can be unloaded, the client side `NetworkSceneManager.VerifySceneBeforeUnloading` callback returns `false` so that scene remains loaded. Finally, the Level 1 scene is verified to be unloaded via `NetworkSceneManager.VerifySceneBeforeUnloading` which the user logic determines is "ok" to unload so it returns `true` and the Level 1 scene is unloaded.
+
+Additive client synchronization can help you to reduce client synchronization times while providing you with additional capabilities tailored for additively loaded scene usage patterns.
diff --git a/versioned_docs/version-2.0.0/basics/scenemanagement/custom-management.md b/versioned_docs/version-2.0.0/basics/scenemanagement/custom-management.md
new file mode 100644
index 000000000..d49285bb3
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/scenemanagement/custom-management.md
@@ -0,0 +1,67 @@
+---
+id: custom-management
+title: Custom scene management
+sidebar_label: Custom management
+---
+
+:::caution
+If you haven't already read the [Using NetworkSceneManager](using-networkscenemanager.md) section, it's highly recommended to do so before proceeding.
+Custom Scene Management currently has some drawbacks that we hope to improve upon over time.
+:::
+
+## Building Your Own Scene Management Solution
+Netcode for GameObjects is designed to provide a scene management solution that should meet most projects' needs. However, some projects might still need to build their own scene management solution. The first step is to disable **Enable Scene Management** in your `NetworkManager`'s properties. All of your scene loading and unloading must be handled via the `UnityEngine.SceneManagement.SceneManager` class.
+
+### Integrated NetworkSceneManager Comparison (Enabled vs Disabled)
+Network Scene Management | Enabled | Disabled
+------------------------------|----------|----------
+Scene Event Synchronizing | Yes | No
+In-Scene Network Prefab Synchronizing | Yes | Yes
+In-Scene NetworkObject Synchronizing | Yes | No
+Auto Scene Migration Synchronizing | Yes | No
+
+#### Scene Event Synchronizing
+When integrated scene management is enabled, scene-related events are automatically synchronized for you. When integrated scene management is disabled, you need to handle the synchronization of scenes yourself.
+
+#### In-Scene Placed Network Prefabs and NetworkObjects
+Clients are always synchronized with any in-scene placed Network Prefab instances when they join a session, regardless of whether integrated scene management is enabled. When scene management is disabled, only scenes loaded prior to a client joining are synchronized — any scenes loaded *after* a client is connected won't be synchronized (you would want to only dynamically spawn NetworkObjects at that point).
+
+:::warning Any in-scene defined NetworkObject (i.e. not a network prefab instance) will not get synchronized with a newly-joined client when scene management is disabled.
+:::
+
+When the integrated `NetworkSceneManager` is enabled, both in-scene placed network prefab instances and in-scene defined NetworkObjects get synchronized, and when new scenes are loaded they get synchronized also.
+
+#### Auto (NetworkObject) Scene Migration Synchronization
+When integrated scene management is enabled, you can have the server migrate an already spawned NetworkObject from one scene to another and it will automatically be synchronized with connected and late-joining clients.
+
+When integrated scene management is disabled, this is not handled and you need to use either NetworkVariables, Rpcs, or custom messages to handle synchronizing clients with any migration of `NetworkObjects`s from one scene to another.
+
+### Registering In-Scene Placed Network Prefab Instances
+While integrated scene management handles the synchronization of in-scene placed NetworkObjects, custom scene management treats everything like a dynamically spawned NetworkObject. As such, you can only use network prefabs defined in your NetworkPrefabList assigned to your NetworkManager, and any in-scene defined NetworkObjects will not synchronize with clients.
+
+Once you've registered your in-scene placed Network Prefabs with your `NetworkPrefabList` and assigned that to your `NetworkManager`, you can then start a server or host and have a client connect and synchronize with the in-scene placed Network Prefab instances (as long as both client and server have pre-loaded the scene or scenes required).
+
+:::important
+When a client first connects, it deletes any in-scene placed `NetworkObjects` in any of the scenes it has currently loaded. When using a custom scene management solution, in-scene placed NetworkObjects are actually dynamically spawned. This means any changes you make to your in-scene placed Network Prefabs will *not* be synchronized with clients automatically.
+:::
+
+### Synchronizing In-Scene Placed Network Prefab Instances
+If you want to change an in-scene placed network prefab instance, you need to handle the serialization of these settings yourself. You can do this by overriding `NetworkBehaviour.OnSynchronize` and serializing any property updates you want to have synchronized with clients when they join. [Read More About OnSynchronize Here](../../basics/networkbehaviour.md#pre-spawn-synchronization).
+
+## Starting a Netcode Enabled Game Session
+The recommended way of starting session using your own scene management solution is to assure that when a client attempts to join a netcode game session it should already have (as best as possible) any scenes that the server might have loaded. While this does not assure that your newly connecting client will load any additional scenes that might have been loaded, using this approach initially will get you started so you can then come up with a strategy to handling:
+- Scene Synchronization
+- Scene Loading and Unloading
+
+### Scene synchronization
+ While you might have an initial set of scenes loaded, you are bound to want to load more scenes as your netcode enabled game session progresses. Once a client has fully connected (you can use `NetworkManager.OnClientConnected` for this), you will want to send the client a list of additional scenes to be loaded.
+ - You will want to come up with your own "client state" as it progresses through this synchronization process to determine when a client has loaded all scenes.
+ - For example: a client might be connected and has synchronized with the default scenes required to connect, but then you have one or more additional scenes you might have loaded (additively) that the client needs to load and synchronize (spawn) any in-scene placed Network Prefab instances.
+ - Remember, once a client has connected, if you load additional scenes then any in-scene placed network prefab instances will not be synchronized for you. It's recommended to dynamically spawn network prefab instances after the initial client synchronization if you plan on loading more scenes.
+
+### Scene Loading and Unloading
+You can accomplish this using either RPCs or custom messages. You might even use your own `INetworkSerializable` implementation that has a list of scenes and whether they should be loaded or unloaded. You should always have some form of "complete" response factored into your design so you know when a client has finished loading/unloading a scene. You will also want to devise a strategy for loading a scene in `LoadSceneMode.Additive` and `LoadSceneMode.Single` modes.
+
+:::tip
+Creating a global scene management script and attaching it to the same GameObject as the `NetworkManager` is one way to assure your custom netcode scene management solution persists while a game session is in progress.
+:::
diff --git a/versioned_docs/version-2.0.0/basics/scenemanagement/inscene-placed-networkobjects.md b/versioned_docs/version-2.0.0/basics/scenemanagement/inscene-placed-networkobjects.md
new file mode 100644
index 000000000..3f0df24f8
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/scenemanagement/inscene-placed-networkobjects.md
@@ -0,0 +1,281 @@
+---
+id: inscene-placed-networkobjects
+title: In-scene placed NetworkObjects
+sidebar_label: In-scene NetworkObjects
+---
+:::caution
+If you haven't already read the [Using NetworkSceneManager](using-networkscenemanager.md) section, it's highly recommended to do so before proceeding.
+:::
+
+In-scene placed NetworkObjects are GameObjects with a NetworkObject component that was added to a scene from within the Editor. You can use in-scene placed NetworkObjects for:
+
+- Management systems
+ - For example, a NetworkObject pool management system that dynamically spawns network prefabs.
+- Interactive world objects that are typically easier to place in-scene than spawn
+ - For example, a door that can only be unlocked by a key. If a player unlocks it then you want other players to know about it being unlocked, and making it an in-scene placed NetworkObject simplifies the positioning of the door relative to the surrounding world geometry.
+ - Static visual elements
+ - For example, a heads up display (HUD) that includes information about other items or players.
+ - Or some form of platform or teleporter that moves a player from one location to the next when a player enters a trigger or uses an object.
+
+Another benefit of in-scene placed NetworkObjects is that they don't require you to register them with the [`NetworkManager`](../../components/networkmanager.md). In-scene placed `NetworkObjects` are registered internally, when scene management is enabled, for tracking and identification purposes.
+
+:::tip
+Items that can be picked up are typically better implemented using a [hybrid approach](#hybrid-approach) with both an in-scene placed and a dynamically spawned NetworkObject. The in-scene placed NetworkObject can be used to configure additional information about the item (what kind, does another one respawn after one is picked up, and if so how much time should it wait before spawning a new item), while the dynamically spawned object is the item itself.
+:::
+
+## In-scene placed vs. dynamically spawned NetworkObjects (order of operations)
+
+Because in-scene placed NetworkObjects are instantiated when a scene loads, they have a different order of operations than dynamically spawned NetworkObjects when it comes to spawning. The table below illustrates that spawning occurs after `Awake` but before `Start` for dynamically spawned NetworkObjects, but for in-scene placed NetworkObjects it occurs after both `Awake` and `Start` are invoked.
+
+Dynamically spawned | In-scene placed
+------------------- | ---------------
+`Awake` | `Awake`
+`OnNetworkSpawn` | `Start`
+`Start` | `OnNetworkSpawn`
+
+In-scene placed NetworkObjects are instantiated when the scene is loaded, which means that both the `Awake` and `Start` methods are invoked before an in-scene placed NetworkObject is spawned. This distinct difference is important to keep in mind when doing any form of dependency-related initializations that might require an active network session. This is especially important to consider when you're using the same `NetworkBehaviour` component with both dynamically spawned and in-scene placed `NetworkObjects`.
+
+## In-scene placed network prefab instances
+
+For frequently used in-scene `NetworkObjects`, you can use a [network prefab](../object-spawning.md#network-prefabs) to simplify the creation process.
+
+### Creating in-scene placed network prefab instances
+
+To create a network prefab that can be used as an in-scene placed NetworkObject, do the following:
+
+1. Create a prefab asset (from a GameObject in a scene or creating it directly in a subfolder within Assets).
+2. Add only one NetworkObject component to the root GameObject of the prefab.
+3. Add any other `NetworkBehaviour`s (on the root or on any level of child GameObject under the root prefab GameObject).
+4. If you created the prefab asset from an existing scene, then the original in-scene placed object will automatically become a network prefab instance.
+5. If you created the prefab asset directly in a subfolder under the Assets directory, then drag and drop the newly created network prefab into the scene of choice.
+
+:::note
+You may need to deactivate **Enter Play Mode Options** if your `NetworkBehaviour` components do not spawn.
+:::
+
+## Using in-scene placed NetworkObjects
+
+There are some common use cases where in-scene placed NetworkObjects can prove useful.
+
+### Static objects
+
+You can use an in-scene placed NetworkObject to keep track of when a door is opened, a button pushed, a lever pulled, or any other type of state with a simple on/off toggle. These are referred to as static objects, and have the following in common:
+
+ - Static objects are spawned while the originating scene is loaded and only despawned when the originating scene is unloaded.
+ - The originating scene is the scene in which the in-scene NetworkObject was placed.
+ - Static objects are typically associated with some world object that's visible to players (such as a door or switch).
+ - Static objects aren't migrated into other scenes or parented under another NetworkObject.
+ - For example, a drawbridge that comes down when a certain game state is reached. The drawbridge is most likely connected to some castle or perhaps a section of the castle and would never need to be migrated to another scene.
+
+### Netcode managers
+
+You can use an in-scene placed NetworkObject as a netcode manager, for tracking game states, or as a NetworkObject spawn manager. Typically, a manager stays instantiated and spawned as long as the scene it was placed in remains loaded. For scenarios where you want to keep a global game state, the recommended solution is to place the in-scene NetworkObject in an additively loaded scene that remains loaded for the duration of your network game session.
+
+If you're using scene switching (that is, loading a scene in `LoadSceneMode.Single`), then you can migrate the in-scene placed NetworkObject (used for management purposes) into the DDoL by sending its `GameObject` to the DDoL:
+
+```csharp
+private void Start()
+{
+ // Don't use this for dynamically spawned NetworkObjects
+ DontDestroyOnLoad(gameObject);
+}
+```
+
+:::warning
+Once migrated into the DDoL, migrating the in-scene placed NetworkObject back into a different scene after it has already been spawned will cause soft synchronization errors with late-joining clients. Once in the DDoL it should stay in the DDoL. This is only for scene switching. If you aren't using scene switching, then it's recommended to use an additively loaded scene and keep that scene loaded for as long as you wish to persist the in-scene placed NetworkObject(s) being used for state management purposes.
+:::
+
+## Complex in-scene NetworkObjects
+
+The most common mistake when using an in-scene placed NetworkObject is to try and use it like a dynamically spawned NetworkObject. When trying to decide if you should use an in-scene placed or dynamically spawned NetworkObject, you should ask yourself the following questions:
+
+- Do you plan on despawning and destroying the NetworkObject?
+ - If yes, then it's highly recommended that you use a dynmically spawned NetworkObject.
+- Can it be parented, at runtime, under another NetworkObject?
+- Excluding any special case DDoL scenarios, will it be moved into another scene other than the originating scene?
+- Do you plan on having full scene-migrations (that is, `LoadSceneMode.Single` or scene switching) during a network session?
+
+If you answered yes to any of the above questions, then using only an in-scene placed NetworkObject to implement your feature might not be the right choice. However, you can use a hybrid approach to get the best of both methods.
+
+### Hybrid approach
+
+Because there are additional complexities involved with in-scene placed NetworkObjects, some use cases are more suited to dynamically spawned NetworkObjects, or require a combination of both types. Perhaps your project's design includes making some world items that can either be consumed (such as health) or picked up (such as weapons and items) by players. Initially, using a single in-scene placed NetworkObject might seem like the best approach for this world item feature.
+
+However, there's another way to accomplish the same thing while maintaining a clear distinction between dynamically spawned and in-scene placed NetworkObjects. Rather than combining everything into a single network prefab and handling the additional complexities involved with in-scene placed NetworkObjects, you can create two network prefabs:
+
+1. A world item network prefab: since this will be dynamically spawned, you can re-use this network prefab with any spawn manager (pooled or single).
+2. A single-spawn manager (non-pooled): this will spawn the world item network prefab. The single-spawn manager can spawn the dynamically spawned NetworkObject at its exact location with an option to use the same rotation and scale.
+
+:::tip
+ Your single-spawn manager can also have a list of GameObjects used as spawn points if you want to spawn world items in various locations randomly and/or based on game state.
+:::
+
+Using this approach allows you to:
+1. Re-use the same single-spawn manager with any other network prefab registered with a `NetworkPrefabsList`.
+2. Not worry about the complexities involved with treating an in-scene placed NetworkObject like a dynamically spawned one.
+
+[You can see a hybrid approach example here.](../object-spawning.md#dynamic-spawning-non-pooled)
+
+## Spawning and despawning in-scene placed NetworkObjects
+
+By default, an in-scene placed NetworkObject is spawned when the scene it's placed in is loaded and a network session is in progress. In-scene placed NetworkObjects differ from dynamically spawned NetworkObjects when it comes to spawning and despawning: when despawning a dynamically spawned NetworkObject, you can always spawn a new instance of the NetworkObject's associated network prefab. So, whether you decide to destroy a dynamically spawned NetworkObject or not, you can always make another clone of the same network prefab, unless you want to preserve the current state of the instance being despawned.
+
+With in-scene placed NetworkObjects, the scene it's placed in is similar to the network prefab used to dynamically spawn a NetworkObject, in that both are used to uniquely identify the spawned NetworkObject. The primary difference is that where you use a network prefab to create a new dynamically spawned instance, for in-scene placed objects you need to additively load the same scene to create another in-scene placed NetworkObject instance.
+
+### Identifying spawned NetworkObjects
+
+Dynamically spawned | In-scene placed
+------------------- | ---------------
+`NetworkPrefab` | Scene
+`GlobalObjectIdHash` | Scene handle (when loaded) and `GlobalObjectIdHash`
+
+Once the NetworkObject is spawned, Netcode for GameObjects uses the `NetworkObjectId` to uniquely identify it for both types. An in-scene placed NetworkObject will continue to be uniquely identified by the scene handle that it originated from and the `GlobalObjectIdHash`, even if the in-scene placed NetworkObject is migrated to another additively loaded scene and the originating scene is unloaded.
+
+### Despawning and respawning the same in-scene placed NetworkObject
+
+When invoking the `Despawn` method of a NetworkObject with no parameters, it defaults to destroying the NetworkObject:
+
+```csharp
+NetworkObject.Despawn(); // Will despawn and destroy (!!! not recommended !!!)
+```
+
+If you want an in-scene placed NetworkObject to persist after it's been despawned, it's recommended to always set the first parameter of the `Despawn` method to `false`:
+
+```csharp
+NetworkObject.Despawn(false); // Will only despawn (recommended usage for in-scene placed NetworkObjects)
+```
+
+Now that you have a despawned NetworkObject, you might notice that the associated `GameObject` and all of its components are still active and possibly visible to all players (that is, like a `MeshRenderer` component). Unless you have a specific reason to keep the associated `GameObject` active in the hierarchy, you can override the virtual `OnNetworkDespawn` method in a `NetworkBehaviour`-derived component and set the `GameObject` to inactive:
+
+```csharp
+using UnityEngine;
+using Unity.Netcode;
+
+public class MyInSceneNetworkObjectBehaviour : NetworkBehaviour
+{
+ public override void OnNetworkDespawn()
+ {
+ gameObject.SetActive(false);
+ base.OnNetworkDespawn();
+ }
+}
+```
+
+This ensures that when your in-scene placed NetworkObject is despawned, it won't consume processing or rendering cycles and will become invisible to all players (either currently connected or that join the session later). Once the NetworkObject has been despawned and disabled, you might want to respawn it at some later time. To do this, set the server-side instance's `GameObject` back to being active and spawn it:
+
+```csharp
+using UnityEngine;
+using Unity.Netcode;
+
+public class MyInSceneNetworkObjectBehaviour : NetworkBehaviour
+{
+ public override void OnNetworkDespawn()
+ {
+ gameObject.SetActive(false);
+ base.OnNetworkDespawn();
+ }
+
+ public void Spawn(bool destroyWithScene)
+ {
+ if (IsServer && !IsSpawned)
+ {
+ gameObject.SetActive(true);
+ NetworkObject.Spawn(destroyWithScene);
+ }
+ }
+}
+```
+
+:::info
+You only need to enable the NetworkObject on the server-side to be able to respawn it. Netcode for GameObjects only enables a disabled in-scene placed NetworkObject on the client-side if the server-side spawns it. This **does not** apply to dynamically spawned `NetworkObjects`. Refer to [the object pooling page](../../advanced-topics/object-pooling.md) for an example of recycling dynamically spawned NetworkObjects.
+:::
+
+### Setting an in-scene placed NetworkObject to a despawned state when instantiating
+
+Since in-scene placed NetworkObjects are automatically spawned when their respective scene has finished loading during a network session, you might run into the scenario where you want it to start in a despawned state until a certain condition has been met. To do this, you need to add some additional code in the `OnNetworkSpawn` part of your `NetworkBehaviour` component:
+
+```csharp
+using UnityEngine;
+using Unity.Netcode;
+
+ public class MyInSceneNetworkObjectBehaviour : NetworkBehaviour
+ {
+ public bool StartDespawned;
+
+ private bool m_HasStartedDespawned;
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer && StartDespawned && !m_HasStartedDespawned)
+ {
+ m_HasStartedDespawned = true;
+ NetworkObject.Despawn(false);
+ }
+ base.OnNetworkSpawn();
+ }
+
+ public override void OnNetworkDespawn()
+ {
+ gameObject.SetActive(false);
+ base.OnNetworkDespawn();
+ }
+
+ public void Spawn(bool destroyWithScene)
+ {
+ if (IsServer && !IsSpawned)
+ {
+ gameObject.SetActive(true);
+ NetworkObject.Spawn(destroyWithScene);
+ }
+ }
+ }
+```
+
+The above example keeps track of whether the in-scene placed NetworkObject has started in a despawned state (to avoid despawning after its first time being spawned), and it only allows the server to execute that block of code in the overridden `OnNetworkSpawn` method. The above `MyInSceneNetworkObjectBehaviour` example also declares a public `bool` property `StartDespawned` to provide control over this through the inspector view in the Editor.
+
+### Synchronizing late-joining clients when an in-scene placed NetworkObject has been despawned and destroyed
+
+Referring back to the [section on complex in-scene NetworkObjects](#complex-in-scene-networkobjects), it's recommended to use dynamically spawned NetworkObjects if you intend to destroy the object when it's despawned. However, if either despawning but not destroying or using the [hybrid approach](#a-hybrid-approach-example) don't appear to be options for your project's needs, then there are two other possible (but not recommended) alternatives:
+
+- Have another in-scene placed NetworkObject track which in-scene placed NetworkObjects have been destroyed and upon a player late-joining (that is, `OnClientConnected`) you would need to send the newly-joined client the list of in-scene placed NetworkObjects that it should destroy. This adds an additional in-scene placed NetworkObject to your scene hierarchy and will consume memory keeping track of what was destroyed.
+- Disable the visual and physics-related components (in Editor as a default) of the in-scene placed NetworkObject(s) in question and only enable them in `OnNetworkSpawn`. This doesn't delete/remove the in-scene placed NetworkObject(s) for the late-joining client and can be tricky to implement without running into edge case scenario bugs.
+
+These two alternatives aren't recommended, but are worth briefly exploring to better understand why it's recommend to use a [non-pooled hybrid approach](../object-spawning.md#dynamic-spawning-non-pooled), or just not destroying the in-scene placed NetworkObject when despawning it.
+
+## Parenting in-scene placed NetworkObjects
+
+In-scene placed NetworkObjects follow the same parenting rules as [dynamically spawned NetworkObjects](../../advanced-topics/networkobject-parenting.md) with only a few differences and recommendations:
+
+- You can create complex nested NetworkObject hierarchies when they're in-scene placed.
+- If you plan on using full scene-migration (that is, `LoadSceneMode.Single` or scene switching) then parenting an in-scene placed NetworkObject that stays parented during the scene migration isn't recommended.
+ - In this scenario, you should use a hybrid approach where the in-scene placed NetworkObject dynamically spawns the item to be picked up.
+- If you plan on using a bootstrap scene usage pattern with additive scene loading and unloading with no full scene-migration(s), then you can parent in-scene placed NetworkObjects.
+
+### Auto object parent sync option
+
+ Already parented in-scene placed NetworkObjects auto object parent sync usage:
+
+- When disabled, the NetworkObject ignores its parent and considers all of its transform values as being world space synchronized (that is, no matter where you move or rotate its parent, it will keep its current position and rotation).
+ - Typically, when disabling this you need to handle synchronizing the client either through your own custom messages or RPCS, or add a `NetworkTransform` component to it. This is only useful if you want to have some global parent that might shift or have transform values that you don't want to impact the NetworkObject in question.
+- When enabled, the NetworkObject is aware of its parent and will treat all of its transform values as being local space synchronized.
+ - This also applies to being pre-parented under a `GameObject` with no NetworkObject component.
+
+:::note
+_**The caveat to the above is scale**:_
+Scale is treated always as local space relative for pre-parented in-scene placed `NetworkObjects`.
+
+*For dynamically spawned NetworkObjects:*
+It depends upon what WorldPositionStays value you use when parenting the NetworkObject in question.
+WorldPositionStays = true: Everything is world space relative. _(default)_
+WorldPositionStays = false: Everything is local space relative. _(children offset relative to the parent)_
+:::
+
+### Parenting and transform synchronization
+
+Without the use of a `NetworkTransform`, clients are only synchronized with the transform values when:
+
+- A client is being synchronized with the NetworkObject in question:
+ - During the client's first synchronization after a client has their connection approved.
+ - When a server spawns a new NetworkObject.
+- A NetworkObject has been parented (or a parent removed).
+- The server can override the `NetworkBehaviour.OnNetworkObjectParentChanged` method and adjust the transform values when that is invoked.
+ - These transform changes will be synchronized with clients via the `ParentSyncMessage`.
diff --git a/versioned_docs/version-2.0.0/basics/scenemanagement/scene-events.md b/versioned_docs/version-2.0.0/basics/scenemanagement/scene-events.md
new file mode 100644
index 000000000..3484d2c5a
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/scenemanagement/scene-events.md
@@ -0,0 +1,281 @@
+---
+id: scene-events
+title: Scene events
+sidebar_label: Scene events
+---
+:::caution
+If you haven't already read the [Using NetworkSceneManager](using-networkscenemanager.md) section, it's highly recommended to do so before proceeding.
+:::
+
+## Scene Event Associations
+We learned that the term "Scene Event" refers to all (associated) subsequent scene events that transpire over time after a server has initiated a load or unload Scene Event. For most cases this is true, however `SceneEventType.Synchronize` is a unique type of Scene Event that handles much more than loading or unloading a single scene. to better understand the associations between scene event types, it's better to first see them grouped together:
+
+### Loading:
+**Initiating Scene Event**: `SceneEventType.Load`
+**Associated Scene Events**:
+- `SceneEventType.LoadComplete`:
+signifies that a scene has been loaded locally. Clients send this event to the server.
+- `SceneEventType.LoadEventCompleted`:
+signifies that the server and all clients have finished loading the scene and signifies that the Scene Event has completed.
+
+### Unloading:
+**Initiating Scene Event**: `SceneEventType.Unload`
+**Associated Scene Events**:
+- `SceneEventType.UnloadComplete`:
+signifies that a scene has been unloaded locally. Clients send this event to the server.
+- `SceneEventType.UnloadEventCompleted`:
+signifies that the server and all clients have finished unloading the scene and signifies that the Scene Event has completed.
+
+### Synchronization:
+This is automatically happens after a client is connected and approved.
+**Initiating Scene Event**: `SceneEventType.Synchronize`
+**Associated Scene Events**:
+- `SceneEventType.SynchronizeComplete`:
+signifies that the client has finished loading all scenes and locally spawned all Netcode objects. The client sends this scene event message back to the server. This message also includes a list of `NetworkObject.NetworkObjectId`s for all of the NetworkObjects the client spawned.
+- `SceneEventType.ReSynchronize`:
+signifies that the server determines the client needs to be "re-synchronized" because one or more NetworkObjects were despawned while the client was synchronizing. This message is sent to the client with a `NetworkObject.NetworkObjectId` list for all NetworkObjects the client needs to despawn.
+
+
+## Client Synchronization Details
+While client synchronization does fall partially outside of the scene management realm, it ended up making more sense to handle the initial client synchronization via the `NetworkSceneManager` since a large part of the synchronization process involves loading scenes and synchronizing (in-scene placed and dynamically spawned) `NetworkObjects`.
+- Scene synchronization is the first thing a client processes.
+ - The synchronization message includes a list of all scenes the server has loaded via the `NetworkSceneManager`.
+ - The client will load all of these scenes before proceeding to the NetworkObject synchronization.
+ - This approach was used to assure all `GameObject`, NetworkObject, and `NetworkBehaviour` dependencies are loaded and instantiated before a client attempts to locally spawn a NetworkObject.
+- Synchronizing with all spawned `NetworkObjects`.
+ - Typically this involves both in-scene placed and dynamically spawned `NetworkObjects`.
+ - Learn more about [Object Spawning here](..\object-spawning.md).
+ - The NetworkObject list sent to the client is pre-ordered, by the server, to account for certain types of dependencies such as when using [Object Pooling](../../advanced-topics/object-pooling.md).
+ - Typically object pool managers are in-scene placed and need to be instantiated and spawned before spawning any of its pooled `NetworkObjects` on a client that is synchronizing. As such, `NetworkSceneManager` takes this into account to assure that all `NetworkObjects` spawned via the `NetworkPrefabHandler` will be instantiated and spawned after their object pool manager dependency has been instantiated and spawned locally on the client.
+ - You can have parented in-scene placed NetworkObjects (that is, items that are picked up or consumed by players)
+ - `NetworkSceneManager` uses a combination of the `NetworkObject.GlobalObjectIdHash` and the instantiating scene's handle to uniquely identify in-scene placed NetworkObjects.
+
+:::info
+With additively loaded scenes, you can run into situations where your object pool manager, instantiated when the scene it's defined within is additively loaded by the server, is leaving its spawned NetworkObject instances within the [currently active scene](https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.GetActiveScene.html). While assuring that newly connected clients being synchronized have loaded all of the scenes first helps to avoid scene dependency issues, this alone does not resolve issue with the NetworkObject spawning order. The integrated scene management, included in Netcode for GameObjects, takes scenarios such as this into consideration.
+:::
+
+### The Client Synchronization Process
+:::info
+The following information isn't required information, but can be useful to better understand the integrated scene management synchronization process.
+:::
+
+Below is a diagram of the client connection approval and synchronization process:
+
+![image](/img/scenemanagement_synchronization_overview.png)
+
+Starting with the "Player" in the top right part of the above diagram, the client (Player) runs through the connection and approval process first which occurs within the `NetworkManager`. Once approved, the server-side `NetworkSceneManager` begins the client synchronization process by sending the `SceneEventType.Synchronize` Scene Event message to the approved client. The client then processes through the synchronization message. Once the client is finished processing the synchronize message, it responds to the server with a `SceneEventType.SynchronizeComplete` message. At this point the client is considered "synchronized". If the server determines any NetworkObject was despawned during the client-side synchronization message processing period, it will send a list of NetworkObject identifiers to the client via the `SceneEventType.ReSynchronize` message and the client will locally despawn the NetworkObjects.
+
+:::tip
+When the server receives and processes the `SceneEventType.SynchronizeComplete` message, the client is considered connected (that is, `NetworkManager.IsConnectedClient` is set to `true`) and both the `NetworkManager.OnClientConnected` delegate handler and the scene event notification for `SceneEventType.SynchronizeComplete` are invoked locally. This can be useful to know if your server sends any additional messages to the already connected clients about the newly connected client's status (that is, a player's status needs to transition from joining to joined).
+:::
+
+## Scene Event Notifications
+
+### When are Load or Unload SceneEvents Truly Complete?
+There are two special scene event types that generate messages for the server and all connected clients:
+`SceneEventType.LoadEventCompleted` and `SceneEventType.UnloadEventCompleted`
+
+:::note
+Both of these server generated messages will create local notification events (on all clients and the server) that will contain the list of all client identifiers (ClientsThatCompleted) that have finished loading or unloading a scene. This can be useful to make sure all clients are synchronized with each other before allowing any netcode related game logic to begin. If a client disconnects or there is a time out, then any client that did not load or unload the scene will be included in a second list of client identifiers (ClientsThatTimedOut).
+:::
+
+### Tracking Event Notifications (OnSceneEvent)
+The following code provides an example of how to subscribe to and use `NetworkSceneManager.OnSceneEvent`. Since we want the server or host to receive all scene event notifications, we will want to subscribe immediately after we start the server or host. Each case has additional comments about each scene event type. Starting the client is fairly straight forward and follows the same pattern by subscribing to `NetworkSceneManager.OnSceneEvent` if the client successfully started.
+
+```csharp
+public bool StartMyServer(bool isHost)
+{
+ var success = false;
+ if (isHost)
+ {
+ success = NetworkManager.Singleton.StartHost();
+ }
+ else
+ {
+ success = NetworkManager.Singleton.StartServer();
+ }
+
+ if (success)
+ {
+ NetworkManager.Singleton.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent;
+ }
+
+ return success;
+}
+
+public bool StartMyClient()
+{
+ var success = NetworkManager.Singleton.StartClient();
+ if (success)
+ {
+ NetworkManager.Singleton.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent;
+ }
+ return success;
+}
+
+private void SceneManager_OnSceneEvent(SceneEvent sceneEvent)
+{
+ // Both client and server receive these notifications
+ switch (sceneEvent.SceneEventType)
+ {
+ // Handle server to client Load Notifications
+ case SceneEventType.Load:
+ {
+ // This event provides you with the associated AsyncOperation
+ // AsyncOperation.progress can be used to determine scene loading progression
+ var asyncOperation = sceneEvent.AsyncOperation;
+ // Since the server "initiates" the event we can simply just check if we are the server here
+ if (IsServer)
+ {
+ // Handle server side load event related tasks here
+ }
+ else
+ {
+ // Handle client side load event related tasks here
+ }
+ break;
+ }
+ // Handle server to client unload notifications
+ case SceneEventType.Unload:
+ {
+ // You can use the same pattern above under SceneEventType.Load here
+ break;
+ }
+ // Handle client to server LoadComplete notifications
+ case SceneEventType.LoadComplete:
+ {
+ // This will let you know when a load is completed
+ // Server Side: receives thisn'tification for both itself and all clients
+ if (IsServer)
+ {
+ if (sceneEvent.ClientId == NetworkManager.LocalClientId)
+ {
+ // Handle server side LoadComplete related tasks here
+ }
+ else
+ {
+ // Handle client LoadComplete **server-side** notifications here
+ }
+ }
+ else // Clients generate thisn'tification locally
+ {
+ // Handle client side LoadComplete related tasks here
+ }
+
+ // So you can use sceneEvent.ClientId to also track when clients are finished loading a scene
+ break;
+ }
+ // Handle Client to Server Unload Complete Notification(s)
+ case SceneEventType.UnloadComplete:
+ {
+ // This will let you know when an unload is completed
+ // You can follow the same pattern above as SceneEventType.LoadComplete here
+
+ // Server Side: receives thisn'tification for both itself and all clients
+ // Client Side: receives thisn'tification for itself
+
+ // So you can use sceneEvent.ClientId to also track when clients are finished unloading a scene
+ break;
+ }
+ // Handle Server to Client Load Complete (all clients finished loading notification)
+ case SceneEventType.LoadEventCompleted:
+ {
+ // This will let you know when all clients have finished loading a scene
+ // Received on both server and clients
+ foreach (var clientId in sceneEvent.ClientsThatCompleted)
+ {
+ // Example of parsing through the clients that completed list
+ if (IsServer)
+ {
+ // Handle any server-side tasks here
+ }
+ else
+ {
+ // Handle any client-side tasks here
+ }
+ }
+ break;
+ }
+ // Handle Server to Client unload Complete (all clients finished unloading notification)
+ case SceneEventType.UnloadEventCompleted:
+ {
+ // This will let you know when all clients have finished unloading a scene
+ // Received on both server and clients
+ foreach (var clientId in sceneEvent.ClientsThatCompleted)
+ {
+ // Example of parsing through the clients that completed list
+ if (IsServer)
+ {
+ // Handle any server-side tasks here
+ }
+ else
+ {
+ // Handle any client-side tasks here
+ }
+ }
+ break;
+ }
+ }
+}
+```
+
+:::tip
+ This code can be applied to a component on your `GameObject` that has a `NetworkManager` component attached to it. Since the `GameObject`, with the `NetworkManager` component attached to it, is migrated into the DDOL (Dont Destroy on Load) scene, it will remain active for the duration of the network game session.
+ With that in mind, you can cache your scene events that occurred (for debug or reference purposes) and/or add your own events that other game objects can subscribe to. The general idea is that if you want to receive all notifications from the moment you start `NetworkManager` then you will want to subscribe to `NetworkSceneManager.OnSceneEvent` immediately after starting it.
+:::
+
+Scene event notifications provide users with all NetworkSceneManager related scene events (and associated data) through a single event handler. The one exception would be scene loading or unloading progress which users can handle with a coroutine (upon receiving a Load or Unload event) and checking the `SceneEvent.AsyncOperation.progress` value over time.
+
+:::caution
+You will want to assign the SceneEvent.AsyncOperation to a local property of the subscribing class and have a coroutine use that to determine the progress of the scene being loaded or unloaded.
+:::
+
+You can stop the coroutine checking the progress upon receiving any of the following event notifications for the scene and event type in question: `LoadComplete`, `UnloadComplete` to handle local scene loading progress tracking. Otherwise, you should use the `LoadEventCompleted` or `UnloadEventCompleted` to assure that when your "scene loading progress" visual handler stops it will stop at ~roughly~ the same time as the rest of the connected clients. The server will always be slightly ahead of the clients since it notifies itself locally and then broadcasts this message to all connected clients.
+
+### SceneEvent Properties
+The SceneEvent class has values that may or may not be set depending upon the `SceneEventType`. Below are two quick lookup tables to determine which property is set for each `SceneEventType`.
+
+**Part-1**
+![image](/img/SceneEventProperties-1.png)
+
+**Part-2**
+![image](/img/SceneEventProperties-2.png)
+
+So, the big "take-away" from the above table is that you need to understand the `SceneEventType` context of the `SceneEvent` you are processing to know which properties are valid and you can use. As an example, it wouldn't make sense to provide the AsyncOperation for the following `SceneEventType`s:
+- LoadComplete or LoadEventCompleted
+- UnloadComplete or UnloadEventCompleted
+- Synchronize or Resynchronize
+
+### SceneEventType Specific Notifications
+There might be a time where you aren't interested in all of the details for each scene event type that occurs. As it just so happens, `NetworkSceneManager` includes a single delegate handler for each `SceneEventType` that is only triggered for the associated `SceneEventType`.
+You can explore the [NetworkSceneManager](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.SceneEventType.html) for a full listing of the corresponding single `SceneEventType` events.
+Some examples:
+- NetworkSceneManager.OnLoad: Triggered when for `OnLoad` scene events.
+- NetworkSceneManager.OnUnload: Triggered when for `OnUnload` scene events.
+- NetworkSceneManager.OnSynchronize: Triggered when a client begins synchronizing.
+
+:::info
+The general idea was to provide several ways to get scene event notifications. You might have a component that needs to know when a client is finished synchronizing on the client side but you don't want that component to receive notifications for loading or unloading related events. Under this scenario you would subscribe to the `NetworkManager.OnSynchronizeComplete` event on the client-side.
+:::
+
+### When is it "OK" to Subscribe?
+Possibly the more important aspect of scene event notifications is knowing when/where to subscribe. The recommended time to subscribe is immediately upon starting your `NetworkManager` as a client, server, or host. This will avoid problematic scenarios like trying to subscribe to the `SceneEventType.Synchronize` event within an overridden `NetworkBehaviour.OnNetworkSpawn` method of your `NetworkBehaviour` derived child class. The reason that is "problematic" is that the NetworkObject has to be spawned before you can subscribe to and receive events of type `SceneEventType.Synchronize` because that will occur before anything is spawned. Additionally, you would only receive notifications of any scenes loaded after the scene that has the NetworkObject (or the object that spawns it) is loaded.
+
+An example of subscribing to `NetworkSceneManager.OnSynchronize` for a client:
+```csharp
+ public bool ConnectPlayer()
+ {
+ var success = NetworkManager.Singleton.StartClient();
+ if (success)
+ {
+ NetworkManager.Singleton.SceneManager.OnSynchronize += SceneManager_OnSynchronize;
+ }
+ return success;
+ }
+
+ private void SceneManager_OnSynchronize(ulong clientId)
+ {
+ Debug.Log($"Client-Id ({clientId}) is synchronizing!");
+ }
+```
+_The general idea is that this would be something you would want to do immediately after you have started the server, host, or client._
diff --git a/versioned_docs/version-2.0.0/basics/scenemanagement/scene-management-overview.md b/versioned_docs/version-2.0.0/basics/scenemanagement/scene-management-overview.md
new file mode 100644
index 000000000..fc1517044
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/scenemanagement/scene-management-overview.md
@@ -0,0 +1,20 @@
+---
+id: scene-management-overview
+title: Scene management overview
+sidebar_label: Scene management overview
+---
+## Netcode Scene Management
+Generally speaking, netcode aware scene management complexity can vary depending upon your project's needs and goals. Netcode for GameObjects (Netcode) provides you with two potential paths:
+
+### [Integrated Scene Management](using-networkscenemanager.md):
+The Netcode for GameObjects scene management solution is enabled by default and provides you with a fully functional netcode scene management solution.
+:::info
+We highly recommend advanced developers new to Netcode for GameObjects become familiar with the integrated scene management solution before creating their own netcode scene management solution.
+:::
+
+### [Custom Scene Management](custom-management.md):
+If your project has needs that go beyond the scope of the Netcode integrated scene management solution, you can disable scene management in the editor through `NetworkManager`'s properties.
+
+:::caution
+Writing your own scene management can be time consuming and complex. We highly recommend that only advanced users already familiar with Netcode for GameObjects take this path.
+:::
diff --git a/versioned_docs/version-2.0.0/basics/scenemanagement/timing-considerations.md b/versioned_docs/version-2.0.0/basics/scenemanagement/timing-considerations.md
new file mode 100644
index 000000000..5a54a771e
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/scenemanagement/timing-considerations.md
@@ -0,0 +1,162 @@
+---
+id: timing-considerations
+title: Timing considerations
+sidebar_label: Timing considerations
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+:::caution
+If you haven't already read the [Using NetworkSceneManager](using-networkscenemanager.md) and/or [Scene Events](scene-events.md) sections, it's highly recommended to do so before proceeding.
+:::
+
+## Introduction
+Netcode for GameObjects handles many of the more complicated aspects of scene management. This section is tailored towards those who want to better understand the client-server communication sequence for scene events as they occur over time.
+In each diagram, you will see two types of arrows:
+- Horizontal arrows: Denotes a progression to the next state and/or event.
+- Diagonal arrows: Denotes a message being sent (server to client or vice versa).
+ - These arrows will have the name of the message being sent or the type of the scene event message being sent.
+
+
+## Client Synchronization:
+The below diagram, Client Synchronization Updates, steps you through the entire client synchronization process from starting the client all the way to the client being fully synchronized and connected.
+
+Above, we can see that the client will first send a connection request to the server that will process the request, handle the approval process via ConnectionApprovalCallback (if connection approval is enabled), and if approved the server will:
+- Send a connection approved message back to the client
+ - This only means the connection is approved, but the client isn't yet synchronized.
+- Start a `SceneEventType.Synchronize` scene event
+ - Build the synchronization message ("Synchronize NetworkObjects") that will contain all of the
+ information a client will need to properly synchronize with the current netcode game session.
+ - Send the scene event message to the client
+
+:::info
+Throughout the integrated scene management sections, we have used the term "client synchronization period" to denote the time it takes a client to:
+- Receive the synchronization message
+- Process the synchronization message
+- Send the `SceneEventType.SynchronizeComplete` message back to the server
+If you look at the server part of the timeline in the above diagram, the "client synchronization period" is everything that occurs within the green bracketed section between "Synchronize NetworkObjects" and "Synchronization" on the server-side. On the client-side, it includes the time it takes to receive the `SceneEventType.Synchronize` message, "Handle (the) SceneEvent", and the time it takes for the server to receive the `SceneEventType.SynchronizeComplete` that is sent by the client once it has completed synchronizing.
+:::
+
+Upon receiving the synchronization event message, the client processes it, and when finished the client sends the `SceneEventType.SynchronizeComplete` scene event message. The client-side will (within the same frame) invoke the following local `NetworkSceneManager` callbacks (if subscribed to):
+- `OnSceneEvent` with the scene event type being set to `SceneEventType.SynchronizeComplete`
+- `OnSynchronizeComplete`
+
+:::important
+Take note that after the client finishes processing the synchronization event, the server lags, in regards to when callbacks are triggered, behind the client. Typically this client-server latency is half RTT, and so you should be aware that just because a client hasn'tified locally that it has finished there is a small period of time (commonly in the 10's to 100's of milliseconds) where the server is still unaware of the client having finished synchronizing.
+:::
+
+### Client-Side Synchronization Timeline
+Now that we have covered the high-level synchronization process, we can dive a little deeper into what happens on the client side as it processes the synchronize message. The below sub-diagram, "Scene Event Synchronization Timeline", provides you with a more detailed view of how the client processes the synchronize message:
+
+You can see that upon receiving the message, the client appears to be iterating over portions of the data included in the synchronize message. This is primarily the asynchronous scene loading phase of the client synchronization process. This means the more scenes loaded, the more a client will be required to load which means the Client Synchronization Period is directly proportional to the number of scene being loaded and the size of each scene being loaded. Once all scenes are loaded, the client will then locally spawn all NetworkObjects. As a final step, the client sends the list of all `NetworkObjectId`s it spawned as part of its `SceneEventType.SynchronizeComplete` scene event message so the server can determine if it needs to resynchronize the client with a list of any `NetworkObjects` that might have despawned during the Client Synchronization Period.
+
+## Loading Scenes
+
+### LoadSceneMode.Additive
+Looking at the timeline diagram below, "Loading an Additive Scene", we can see that it includes a server, two clients, and that the server will always precede all clients when it comes to processing the scene loading event. The big-picture this diagram is conveying is that only when the server has finished loading the scene and spawning any in-scene placed NetworkObjects, instantiated by the newly loaded scene, will it send the scene loading event message to the clients.
+
+Another point of interest in the below diagram is how Client 1 receives the scene loading event, processes it, and then responds with a `SceneEventType.LoadComplete` scene event message before client 2. This delta between client 1 and client 2 represents the varying client-server latencies and further enforces the underlying concept behind the `SceneEventType.LoadEventCompleted` message. Once a server has received all `SceneEventType.LoadComplete` messages from the connected clients, it will then broadcast the `SceneEventType.LoadEventCompleted` message to all connected clients. At this point, we can consider the scene loading event (truly) complete and all connected clients are able to receive and process netcode messages.
+
+:::caution
+While a client can start sending the server messages (including NetworkVariable changes) upon local `SceneEventType.LoadComplete` event notifications, under more controlled testing environments where the network being used has little to no latency (that is, using loopback with multiple instances running on the same system or using your LAN), this approach won't expose latency related issues. Even though the timing might "work out" under controlled low latency conditions you can still run into edge case scenarios where if a client approaches or exceeds a 500ms RTT latency you can potentially run into issues.
+:::
+
+:::tip
+It is recommended that if your project's design requires that one or more `NetworkBehaviour`s immediately send any form of client to server message (that is, changing a `NetworkVariable`, sending an RPC, sending a custom message, etc.) upon a client being locally notified of a `SceneEventType.LoadComplete` then you should test with artificial/simulated network conditions.
+[Learn More About Simulating NetworkConditions Here](../../tutorials/testing/testing_with_artificial_conditions.md)
+:::
+
+### LoadSceneMode.Single (a.k.a. Scene Switching)
+Loading a scene in `LoadSceneMode.Single` mode via `NetworkSceneManager` is almost exactly like loading a scene additively. The primary difference between additively loading and single mode loading is that when loading a scene in single mode:
+- all currently loaded scenes are unloaded
+- all NetworkObjects that have `DestroyWithScene` set to `true` will be despawned and destroyed.
+
+How you load scenes is up to your project/design requirements.
+
+- **Boot Strap Usage Pattern (Additive Loading Only)**
+ - Your only single mode loaded scene is the first scene loaded (that is, scene index of 0 in the scenes in build list within your project's build settings).
+ - Because your single mode loaded scene is automatically loaded, the server and all clients will already have this scene loaded
+ - To prevent clients from loading the bootstrap scene, you should use server-side [scene validation](using-networkscenemanager.md#scene-validation)
+ - All other scenes are loaded additively
+ - There is no real need to preserve any NetworkObject you want to persist when loading a scene additively.
+ - You need to keep track of the scenes loaded by `NetworkSceneManager` to be able to unload them.
+
+- **Scene Switch Usage Pattern (Single and Additive Loading)**
+ - Typically this usage pattern is desirable when your project's design separates "areas" by a primary scene that may have companion additively loaded scenes.
+ - Any scenes loaded by `NetworkSceneManager`, before scene switching, will be unloaded and any NetworkObject that has the `DestroyWithScene` set to `true` will be destroyed.
+ - If `DestroyWithScene` is set to `false` it will be "preserved" (_see the sub-diagram "Load New Scene Timeline" below_)
+
+
+
+## Load New Scene Timeline (Sub-Diagram)
+Both scene loading diagrams (Additive and Single) refer to the below sub-diagram that provides additional details of the scene loading process.
+:::important
+When looking at the below sub-diagram, both single and additive scene loading modes use close to the exact same flow with the exception that additively loaded scenes only flow through the four middle steps that are grouped together by the light red filled region highlighted by red dashed lines. When loading a scene additively, no other scenes are unloaded nor are any NetworkObjects moved into the DDoL temporarily. This setting, by default, is true for dynamically spawned NetworkObjects unless otherwise specified when using `NetworkObject.Spawn`, `NetworkObject.SpawnWithOwnership`, or `NetworkObject.SpawnAsPlayerObject`. In-scene placed NetworkObject's, by default, will be destroyed with the scene that instantiated them. At any point, within a `NetworkBehaviour` you can change the `NetworkObject.DestroyWithScene` property.
+:::
+
+
+
+**Load New Scene Additively**
+1. Starts loading the scene
+2. During the scene loading process, in-scene placed NetworkObjects are instantiated and their `Awake` and then `Start` methods are invoked (in that order).
+3. Scene loading completes.
+4. All in-scene placed NetworkObjects are spawned.
+:::caution
+Step #3 above signifies that the `UnityEngine.SceneManagement.SceneManager` has finished loading the scene. If you subscribe to the `UnityEngine.SceneManagement.SceneManager.sceneLoaded` event, then step #3 would happen on the same frame that your subscribed handler is invoked. **Don't use this event** as a way to determine that the current Load SceneEvent has completed.
_Doing so will result in unexpected results that most commonly are associated with "yet-to-be-spawned" (locally) NetworkObject's and/or their related `NetworkBehaviour` dependencies._
When using Netcode Integrated SceneManagement, it's recommended to use the `NetworkSceneManager` scene events to determine when the "netcode scene loading event" has completed locally or for all clients.
+:::
+
+**Load New Scene Single (a.k.a "Scene Switching")**
+1. All `NetworkObjects` that have their `DestroyWithScene` property set to `false` are migrated into the DDoL (temporarily).
+2. All currently loaded scenes are unloaded. If you loaded any scenes additively, they will be automatically unloaded.
+3. _(refer to the 4 steps outlined above)_
+4. After any newly instantiated NetworkObjects are spawned, the newly loaded scene is set as the currently active scene and then the NetworkObjects that were previously migrated into th DDoL (from step 1) are now migrated into the newly loaded scene.
+
+## Unloading a Scene
+Primarily, this applies to unloading additively loaded scenes via th `NetworkSceneManager.UnloadScene` method. to unload a scene it must:
+- have been additively loaded by `NetworkSceneManager`
+- still be loaded
+
+
+### Unloading an Additive Scene
+If you look at the below diagram, "Unloading an Additive Scene", you will see a similar flow as that of loading a scene. The server still initiates the `SceneEventType.Unload` scene event and won't send this message to clients until it has completed the `Unload` scene event locally.
+
+
+
+### Unloading Scenes Timeline:
+Review over the below diagram and take note of the following things:
+- **Server Side:**
+ - When a server starts the `SceneEventType.Unload` event, Unity will naturally being to destroy all `GameObjects` in the scene being unloaded.
+ - If a `GameObject` has a NetworkObject component attached to it and it's still considered spawned at the time the `GameObject` is destroyed, then the NetworkObject will be despawned before the `GameObject` being destroyed.
+ - This will cause a series of server-to-client despawn messages to be sent to all clients.
+- **Client Side:**
+ - While a server is unloading a scene, the client can begin to receive a bunch of despawn messages for the NetworkObjects being destroyed on the server-side while the scene is being unloaded.
+ - By the time a client receives the `SceneEventType.Unload` scene event message, it well can have no remaining NetworkObjects in the scene being unloaded. This won't impact the client-side scene unloading process, but it's useful to know that this will happen.
+
+
diff --git a/versioned_docs/version-2.0.0/basics/scenemanagement/using-networkscenemanager.md b/versioned_docs/version-2.0.0/basics/scenemanagement/using-networkscenemanager.md
new file mode 100644
index 000000000..6ea7b4e74
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/scenemanagement/using-networkscenemanager.md
@@ -0,0 +1,374 @@
+---
+id: using-networkscenemanager
+title: Using NetworkSceneManager
+sidebar_label: Using NetworkSceneManager
+---
+
+## Netcode for GameObjects Integrated Scene Management
+### The `NetworkSceneManager` Provides You With:
+- An existing framework that supports both the bootstrap and scene transitioning scene management usage patterns.
+- Automated client synchronization that occurs when a client is connected and approved.
+ - All scenes loaded via `NetworkSceneManager` will be synchronized with clients during client synchronization.
+ - _Later in this document, you will learn more about using scene validation to control what scenes are synchronized on the client, server, or both side(s)_.
+ - All spawned Netcode objects are synchronized with clients during client synchronization.
+- A comprehensive scene event notification system that provides you with a plethora of options.
+ - It provides scene loading, unloading, and client synchronization events ("Scene Events") that can be tracked on both the client and server.
+ - The server is notified of all scene events (including the clients')
+ - The server tracks each client's scene event progress (scene event progress tracking)
+ - Clients receive scene event messages from the server, trigger local notifications as it progresses through a Scene Event's, and send local notifications to the server.
+ - _clients **aren't** aware of other clients' scene events_
+ - In-Scene placed NetworkObject synchronization
+
+:::info
+In-Scene placed NetworkObjects can be used in many ways and are treated uniquely from that of dynamically spawned NetworkObjects. An in-scene placed NetworkObject is a GameObject with a NetworkObject and typically at least one `NetworkBehaviour` component attached to a child of or the same `GameObject`. it's recommended to read through all integrated scene management materials (this document, [Scene Events](scene-events.md), and [Timing Considerations](timing-considerations.md)) before learning about more advanced [In-Scene (placed) NetworkObjects](inscene-placed-networkobjects.md) topics.
+:::
+
+All of these scene management features (and more) are handled by the [`NetworkSceneManager`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkSceneManager.html).
+
+### Accessing `NetworkSceneManager`
+The `NetworkSceneManager` lives within the `NetworkManager` and is instantiated when the `NetworkManager` is started.
+`NetworkSceneManager` can be accessed in the following ways:
+- From within a `NetworkBehaviour` derived component, you can access it by using `NetworkManager.SceneManager`
+- From anything else that does not already have a reference to `NetworkManager`, you can access it using `NetworkManager.Singleton.SceneManager`.
+
+**Here are some genral rules about accessing and using `NetworkSceneManager`:**
+- Don't try to access the `NetworkSceneManager` when the `NetworkManager` is shutdown (it won't exist).
+ - The `NetworkSceneManager` is only instantiated when a `NetworkManager` is started.
+- As a server:
+ - Any scene you want synchronized with currently connected or late joining clients **must** be loaded via the `NetworkSceneManager`
+ - If you use the `UnityEngine.SceneManagement.SceneManager` during a netcode enabled game session, then those scenes won't be synchronized with currently connected clients.
+ - A "late joining client" is a client that joins a game session that has already been started and there are already one or more clients connected.
+ - _All netcode aware objects spawned before a late joining client will be synchronized with a late joining client._
+ - If you load a scene on the server-side using `UnityEngine.SceneManagement.SceneManager` then it will be synchronized with late joining clients unless you use server-side scene validation (see [Scene Validation](using-networkscenemanager.md#scene-validation)).
+ - _It is a best practice to use `NetworkSceneManager` when loading scenes _
+ - The server does not require any clients to be currently connected before it starts loading scenes via the `NetworkSceneManager`.
+ - Any scene loaded via `NetworkSceneManager` will always default to being synchronized with clients.
+ - _Scene validation is explained later in this document._
+
+:::warning
+Don't try to access the `NetworkSceneManager` when the `NetworkManager` is shutdown. The `NetworkSceneManager` is only instantiated when a `NetworkManager` is started. _This same rule is true for all Netcode systems that reside within the `NetworkManager`_.
+:::
+
+### Loading a Scene
+In order to load a scene, there are four requirements:
+1. The `NetworkManager` instance loading the scene must be a host or server.
+2. The `NetworkSceneManager.Load` method is used to load the scene.
+3. The scene being loaded must be registered with your project's [build settings scenes in build list](https://docs.unity3d.com/Manual/BuildSettings.html)
+4. A Scene Event can't already be in progress.
+
+#### Basic Scene Loading Example
+Imagine that you have an in-scene placed NetworkObject, let's call it "ProjectSceneManager", that handles your project's scene management using the `NetworkSceneManager` and you wanted your server to load a scene when the ProjectSceneManager is spawned.
+In its simplest form, it can look something like:
+```csharp
+public class ProjectSceneManager : NetworkBehaviour
+{
+ /// INFO: You can remove the #if UNITY_EDITOR code segment and make SceneName public,
+ /// but this code assures if the scene name changes you won't have to remember to
+ /// manually update it.
+#if UNITY_EDITOR
+ public UnityEditor.SceneAsset SceneAsset;
+ private void OnValidate()
+ {
+ if (SceneAsset != null)
+ {
+ m_SceneName = SceneAsset.name;
+ }
+ }
+#endif
+ [SerializeField]
+ private string m_SceneName;
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer && !string.IsNullOrEmpty(m_SceneName))
+ {
+ var status = NetworkManager.SceneManager.LoadScene(m_SceneName, LoadSceneMode.Additive);
+ if (status != SceneEventProgressStatus.Started)
+ {
+ Debug.LogWarning($"Failed to load {m_SceneName} " +
+ $"with a {nameof(SceneEventProgressStatus)}: {status}");
+ }
+ }
+ }
+}
+```
+In the above code snippet, we have a `NetworkBehaviour` derived class, `ProjectSceneManager`, that has a public `SceneAsset` property (editor only property) that specifies the scene to load. In the `OnNetworkSpawn` method, we make sure that only the server loads the scene and we compare the `SceneEventProgressStatus` returned by the `NetworkSceneManager.Load` method to the `SceneEventProgressStatus.Started` status. If we received any other status, then typically the name of the status provides you with a reasonable clue as to what the issue might be.
+
+### Scene Events and Scene Event Progress
+The term "Scene Event" refers to all subsequent scene events that transpire over time after a server has started a `SceneEventType.Load` ("load") or `SceneEventType.Unload` ("unload") Scene Event. For example, a server might load a scene additively while clients are connected. The following high-level overview provides you with a glimpse into the events that transpire during a load Scene Event(_it assumes both the server and clients have registered for scene event notifications_):
+- Server starts a `SceneEventType.Load` event
+ - The server begins asynchronously loading the scene additively
+ - The server will receive a local notification that the scene load event has started
+ - Once the scene is loaded, the server spawns any in-scene placed `NetworkObjects` locally
+ - After spawning, the server will send the `SceneEventType.Load` message to all connected clients along with information about the newly instantiated and spawned NetworkObjects.
+ - The server will receive a local `SceneEventType.LoadComplete` event
+ - This only means the server is done loading and spawning `NetworkObjects` instantiated by the scene being loaded.
+- The clients receive the scene event message for the `SceneEventType.Load` event and begin processing it.
+ - Upon starting the scene event, the clients will receive a local notification for the SceneEventType.Load event.
+ - As each client finishes loading the scene, they will generate a `SceneEventType.LoadComplete` event
+ - The client sends this event message to the server.
+ - The client is notified locally of this scene event.
+ - This notification only means that it has finished loading and synchronizing the scene, but does not mean all other clients have!
+- The server receives the `SceneEventType.LoadComplete` events from the clients
+ - When all `SceneEventType.LoadComplete` events have been received, the server will generate a `SceneEventType.LoadEventCompleted` notification
+ - This notification is triggered locally on the server
+ - The server broadcasts this scene event to the clients
+- Each client receives the `SceneEventType.LoadEventCompleted` event
+ - At this point all clients have completed the `SceneEventType.Load` event and are synchronized with all newly instantiated and spawned `NetworkObjects`.
+
+The purpose behind the above outline is to show that a Scene Event can lead to other scene event types being generated and that the entire sequence of events that transpire occur over a longer period of time than if you were loading a scene in a single player game.
+
+:::tip
+When you receive the `SceneEventType.LoadEventCompleted` or the `SceneEventType.SynchronizeComplete` you know that the server or clients can start invoking netcode specific code (that is, sending Rpcs, updating `NetworkVariable`s, etc.). Alternately, `NetworkManager.OnClientConnectedCallback` is triggered when a client finishes synchronizing and can be used in a similar fashion. _However, that only works for the initial client synchronization and not for scene loading or unloading events._
+:::
+
+:::warning
+Because the `NetworkSceneManager` still has additional tasks to complete once a scene is loaded, it isn't recommended to use `UnityEngine.SceneManagement.SceneManager.sceneLoaded` or `UnityEngine.SceneManagement.SceneManager.sceneUnloaded` as a way to know when a scene event has completed. These two callbacks will occur before `NetworkSceneManager` has finished the final processing after a scene is loaded or unloaded and you can run into timing related issues. If you are using the netcode integrated scene management, then it's highly recommended to subscribe to the `NetworkSceneManager`'s scene event notifications.
+:::
+
+#### Scene Event Notifications
+You can be notified of scene events by registering in one of two ways:
+1. Receive all scene event notification types: `NetworkSceneManager.OnSceneEvent`
+2. Receive only a specific scene event notification type: [`NetworkSceneManager`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkSceneManager.html#events) has one for each [`SceneEventType`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.SceneEventType.html)
+:::info
+Receiving (via subscribing to the associated event callback) only specific scene event notification types does not change how a server or client receives and processes notifications.
+:::
+
+**Receiving All Scene Event Notifications**
+Typically, this is used on the server side to receive notifications for every scene event notification type for both the server and clients. You can receive all scene event type notifications by subscribing to the `NetworkSceneManager.OnSceneEvent` callback handler.
+
+**Receiving A Specific Scene Event Notification**
+Typically, this is used with clients or components that might only need to be notified of a specific scene event type. There are 9 scene event types and each one has a corresponding "single event type" callback handler in `NetworkSceneManager`.
+
+**As an example:**
+You might want to register for the `SceneEventType.LoadEventCompleted` scene event type to know, from a client perspective, that the server and all other clients have finished loading a scene. This notification lets you know when you can start performing other netcode related actions on the newly loaded and spawned NetworkObjects.
+
+#### Scene Event Progress Status
+As we discussed in the earlier code example, it's important to check the status returned by `NetworkSceneManager.Load` to make sure your scene loading event has started. The following is a list of all [SceneEventProgressStatus](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.SceneEventProgressStatus.html) `enum` values with some additional helpful information:
+- Started
+ - The scene event has started (success)
+- SceneNotLoaded
+ - This is returned when you attempt to unload a scene that isn't loaded (or no longer is loaded)
+- SceneEventInProgress
+ - This is returned if you attempt to start a new scene event (loading or unloading) while one is still in progress
+- InvalidSceneName
+ - This can happen for one of the two reasons:
+ - The scene name isn't spelled correctly or the name of the scene changed
+ - The scene name isn't in your project's scenes in build list
+- SceneFailedVerification
+ - This is returned if you fail scene verification on the server side (more about scene verification later)
+- InternalNetcodeError
+ - Currently, this error will only happen if the scene you are trying to unload was never loaded by the `NetworkSceneManager`.
+
+### Unloading a Scene
+Now that we understand the loading process, scene events, and can load a scene additively, the next step is understanding the integrated scene management scene unloading process. to unload a scene, here are the requirements:
+1. The `NetworkManager` instance unloading the scene should have already been started in host or server mode and already loaded least one scene additively.
+ 1.1 Only additively loaded scenes can be unloaded.
+ 1.2 You can't unload the currently active scene (see info dialog below)
+2. The `NetworkSceneManager.Unload` method is used to unload the scene
+3. A Scene Event can't already be in progress
+
+:::info
+Unloading the currently active scene, in Netcode, is commonly referred to as "scene switching" or loading another scene in `LoadSceneMode.Single` mode. This will unload all additively loaded scenes and upon the new scene being loaded in `LoadSceneMode.Single` mode it's set as the active scene and the previous active scene is unloaded.
+:::
+
+#### Basic Scene Unloading Example
+Below we are taking the previous scene loading example, the `ProjectSceneManager` class, and modifying it to handle unloading. This includes keeping a reference to the `SceneEvent.Scene` locally in our class because `NetworkSceneManager.Unload` requires the `Scene` to be unloaded.
+
+**Below is an example of how to:**
+- Subscribe the server to `NetworkSceneManager.OnSceneEvent` notifications.
+- Save a reference to the `Scene` that was loaded.
+- Unload a scene loaded additively by `NetworkSceneManager`.
+- Detect the scene event types associated with loading and unloading.
+
+```csharp
+public class ProjectSceneManager : NetworkBehaviour
+{
+ /// INFO: You can remove the #if UNITY_EDITOR code segment and make SceneName public,
+ /// but this code assures if the scene name changes you won't have to remember to
+ /// manually update it.
+#if UNITY_EDITOR
+ public UnityEditor.SceneAsset SceneAsset;
+ private void OnValidate()
+ {
+ if (SceneAsset != null)
+ {
+ m_SceneName = SceneAsset.name;
+ }
+ }
+#endif
+ [SerializeField]
+ private string m_SceneName;
+ private Scene m_LoadedScene;
+
+ public bool SceneIsLoaded
+ {
+ get
+ {
+ if (m_LoadedScene.IsValid() && m_LoadedScene.isLoaded)
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer && !string.IsNullOrEmpty(m_SceneName))
+ {
+ NetworkManager.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent;
+ var status = NetworkManager.SceneManager.LoadScene(m_SceneName, LoadSceneMode.Additive);
+ CheckStatus(status);
+ }
+
+ base.OnNetworkSpawn();
+ }
+
+ private void CheckStatus(SceneEventProgressStatus status, bool isLoading = true)
+ {
+ var sceneEventAction = isLoading ? "load" : "unload";
+ if (status != SceneEventProgressStatus.Started)
+ {
+ Debug.LogWarning($"Failed to {sceneEventAction} {m_SceneName} with" +
+ $" a {nameof(SceneEventProgressStatus)}: {status}");
+ }
+ }
+
+ ///
+ /// Handles processing notifications when subscribed to OnSceneEvent
+ ///
+ /// class that has information about the scene event
+ private void SceneManager_OnSceneEvent(SceneEvent sceneEvent)
+ {
+ var clientOrServer = sceneEvent.ClientId == NetworkManager.ServerClientId ? "server" : "client";
+ switch (sceneEvent.SceneEventType)
+ {
+ case SceneEventType.LoadComplete:
+ {
+ // We want to handle this for only the server-side
+ if (sceneEvent.ClientId == NetworkManager.ServerClientId)
+ {
+ // *** IMPORTANT ***
+ // Keep track of the loaded scene, you need this to unload it
+ m_LoadedScene = sceneEvent.Scene;
+ }
+ Debug.Log($"Loaded the {sceneEvent.SceneName} scene on " +
+ $"{clientOrServer}-({sceneEvent.ClientId}).");
+ break;
+ }
+ case SceneEventType.UnloadComplete:
+ {
+ Debug.Log($"Unloaded the {sceneEvent.SceneName} scene on " +
+ $"{clientOrServer}-({sceneEvent.ClientId}).");
+ break;
+ }
+ case SceneEventType.LoadEventCompleted:
+ case SceneEventType.UnloadEventCompleted:
+ {
+ var loadUnload = sceneEvent.SceneEventType == SceneEventType.LoadEventCompleted ? "Load" : "Unload";
+ Debug.Log($"{loadUnload} event completed for the following client " +
+ $"identifiers:({sceneEvent.ClientsThatCompleted})");
+ if (sceneEvent.ClientsThatTimedOut.Count > 0)
+ {
+ Debug.LogWarning($"{loadUnload} event timed out for the following client " +
+ $"identifiers:({sceneEvent.ClientsThatTimedOut})");
+ }
+ break;
+ }
+ }
+ }
+
+ public void UnloadScene()
+ {
+ // Assure only the server calls this when the NetworkObject is
+ // spawned and the scene is loaded.
+ if (!IsServer || !IsSpawned || !m_LoadedScene.IsValid() || !m_LoadedScene.isLoaded)
+ {
+ return;
+ }
+
+ // Unload the scene
+ var status = NetworkManager.SceneManager.UnloadScene(m_LoadedScene);
+ CheckStatus(status, false);
+ }
+}
+```
+Really, if you take away the debug logging code the major differences are:
+- We store the Scene loaded when the server receives its local `SceneEventType.SceneEventType.LoadComplete` notification
+- When the `ProjectSceneManager.UnloadScene` method is invoked (_assuming this occurs outside of this class_) the `ProjectSceneManager.m_LoadedScene` is checked to make sure it's a valid scene and that it's indeed loaded before we invoke the `NetworkSceneManager.Unload` method.
+
+### Scene Validation
+Sometimes you might need to prevent the server or client from loading a scene under certain conditions. Here are a few examples of when you might do this:
+- One or more game states determine if a scene is loaded additively
+ - Typically, this is done on the server-side.
+- The scene is already pre-loaded on the client
+ - Typically, this is done on the client-side.
+- Security purposes
+ - As we mentioned earlier, `NetworkSceneManager` automatically considers all scenes in the build settings scenes in build list valid scenes to be loaded. You might use scene validation to prevent certain scenes from being loaded that can cause some form of security and/or game play issue.
+ - it's common to do this on either the server or client side depending upon your requirements/needs.
+
+**Usage Example**
+The below example builds upon the previous example's code, and adds some psuedo-code for server-side scene validation:
+```csharp
+ private bool ServerSideSceneValidation(int sceneIndex, string sceneName, LoadSceneMode loadSceneMode)
+ {
+ // Comparing against the name or sceneIndex
+ if (sceneName == "SomeSceneName" || sceneIndex == 3)
+ {
+ return false;
+ }
+
+ // Don't allow single mode scene loading (that is, bootstrap usage patterns might implement this)
+ if (loadSceneMode == LoadSceneMode.Single)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer && !string.IsNullOrEmpty(m_SceneName))
+ {
+ NetworkManager.SceneManager.VerifySceneBeforeLoading = ServerSideSceneValidation;
+ NetworkManager.SceneManager.OnSceneEvent += SceneManager_OnSceneEvent;
+ var status = NetworkManager.SceneManager.LoadScene(m_SceneName, LoadSceneMode.Additive);
+ CheckStatus(status);
+ }
+
+ base.OnNetworkSpawn();
+ }
+```
+The callback is the first thing invoked on the server-side when invoking the `NetworkSceneManager.Load` method. If the scene validation fails, `NetworkSceneManager.Load` will return `SceneEventProgressStatus.SceneFailedVerification` and the scene event is cancelled.
+
+:::caution
+**Client-Side Scene Validation**
+This is where you need to be cautious with scene validation, because any scene that you don't validate on the client side should not contain Netcode objects that are considered required dependencies for a connecting client to properly synchronize with the current netcode (game) session state.
+:::
+
+### Dynamically Generated Scenes
+You might find yourself in a scenario where you just need to dynamically generate a scene. A common use for dynamically generated scenes is when you need to dynamically generate collision geometry that you wish to only create on the server-host side. For this scenario you most likely would only want the server to have this scene loaded, but you might run into issues when synchronizing clients. For single player games, you can just create a new scene at runtime, dynamically generate the collision geometry, add the collision geometry to the newly created scene, and everything works out. With Netcode for GameObjects there are two extra steps you need to take to assure you don't run into any issues:
+- Create an empty scene for each scene you plan on dynamically generating and add them to the "Scenes in Build" list found within the "Build Settings".
+ - For this example we would only need one (that is, we might call the scene "WorldCollisionGeometry")
+- Have the server-host register for `NetworkManager.SceneManager.VerifySceneBeforeLoading` handler and return false when one of the blank scene names is being validated as a valid scene for a client to load.
+ - For this example we would return false any time `VerifySceneBeforeLoading` was invoked with the scene name "WorldCollisionGeometry".
+
+ :::caution
+ This only works under the scenario where the dynamically generated scene is a server-host side only scene unless you write server-side code that sends enough information to a newly connected client to replicate the dynamically generated scene via RPC, a custom message, a `NetworkVariable`, or an in-scene placed NetworkObject that is in a scene, other than the dynamically generated one, and has a `NetworkBehaviour` component with an overridden `OnSynchronize` method that includes additional serialization information about how to construct the dynamically generated scene. The limitation on this approach is that the scene should not contain already spawned NetworkObjects as those won't get automatically synchronized when a client first connects.
+ :::
+
+### Active Scene Synchronization
+Setting `NetworkSceneManager.ActiveSceneSynchronizationEnabled` to true on the host or server instance will automatically synchronize both connected and late joining clients with changes in the active scene by the server or host. When enabled, the server or host instance subscribes to the `SceneManager.activeSceneChanged` event and generates `SceneEventType.ActiveSceneChanged` messages when the active scene is changed. Disabling this property just means the server or host instance unsubscribes from the event and will no longer send `SceneEventType.ActiveSceneChanged` messages to keep client's synchronized with the server or host's currently active scene.
+
+This typically is most useful when the `NetworkSceneManager.ClientSynchronizationMode` is set to `LoadSceneMode.Additive` via the `NetworkSceneManager.SetClientSynchronizationMode` method on a server or host instance.
+
+See Also: [Client Synchronization Mode](client-synchronization-mode.md)
+
+
+### What Next?
+We have covered how to access the `NetworkSceneManager`, how to load and unload a scene, provided a basic overview on scene events and notifications, and even briefly discussed in-scene placed NetworkObjects. You now have the fundamental building-blocks one needs to learn more advanced integrated scene management topics.
+_We recommend proceeding to the next integrated scene management topic, "Client Synchronization Mode", in the link below._
+
+
diff --git a/versioned_docs/version-2.0.0/basics/spawning-synchronization.md b/versioned_docs/version-2.0.0/basics/spawning-synchronization.md
new file mode 100644
index 000000000..118c56487
--- /dev/null
+++ b/versioned_docs/version-2.0.0/basics/spawning-synchronization.md
@@ -0,0 +1,126 @@
+---
+id: spawning-synchronization
+title: Spawning synchronization
+---
+
+Ensuring that objects spawn in a synchronized manner across clients can be difficult, although the challenges differ depending on which [network topology](../terms-concepts/network-topologies.md) you're using.
+
+## Spawning synchronization in client-server
+
+Due to the restrictive nature of only the server having the authority to spawn objects, visual anomalies between clients are common in [client-server](../terms-concepts/client-server.md) contexts. This typically occurs when using an owner-authoritative motion model, also known as a ClientNetworkTransform, and trying to visually synchronize the spawning of an object relative to a local player's current position (for example, a player shooting a projectile).
+
+![Client server spawn synchronization](/img/client-server-spawn-sync.jpg)
+
+In the diagram above, a client-owned object (a player) is in motion while firing a projectile. The code implementing this behavior involves sending a message (typically an [RPC](../advanced-topics/messaging-system.md)) from the client to the server to get an object to spawn based on the player's input. Due to the latency involved in sending this message to the server and then propagating the resulting spawn message across all clients, including back to the initiating client, the spawn projectile message reaches the initiating client after the client's local player has moved, resulting in a visual disconnect between the local player and the projectile.
+
+These types of issues are commonly resolved using a client prediction system or by separating the visual representation of the projectile from the NetworkObject and writing a script that moves the visual representation in the desired direction of the yet-to-be-spawned NetworkObject and then synchronizing the two over time once the NetworkObject is spawned. Both approaches are complex to implement in a client-server topology.
+
+## Spawning synchronization in distributed authority
+
+Managing spawning synchronization is easier in [distributed authority](../terms-concepts/distributed-authority.md) contexts, because the authority to spawn objects is shared between clients. Instead of a client having to send an RPC to the server, wait roughly the round trip time (RTT) between itself and the server-host, and then receive and process the spawn message, the client just spawns the projectile in the precise position desired relative to the player object, as explained in the diagram below.
+
+![Distributed authority spawn synchronization](/img/distributed-authority-spawn-sync.jpg)
+
+Handling this visual synchronization issue is similar to the traditional Unity development flow, with one additional step:
+
+1. Instantiate a (network) prefab instance.
+2. Position/Configure the instantiated prefab instance.
+3. (New step) Spawn the prefab instance.
+
+Transform changes on non-authoritative instances are network tick synchronized by the distributed authority service. This allows for remote-client cloned object instances to be visually synchronized with other spawned objects across all clients, since consumption and processing of transform state updates are processed relative to each clients' currently known network tick value.
+
+Distributed authority also provides a simpler way to visually synchronize the despawning of NetworkObjects (relative to a client-server session). Refer to the [deferred despawning page](deferred-despawning.md) for more details.
+
+## Examples
+
+Below are two example scripts, one that handles spawning using the client-server mode, and one that uses distributed authority mode.
+
+* The client-server script requires splitting the logic between client and server. The client has to send a message to the server in order to spawn the projectile, which introduces the latency previously described between a player's motion and the projectile being spawned.
+* With distributed authority, spawning follows a more traditional single-player usage pattern. The notable difference from the client-server approach is that there's no need to send a message to a server in order to spawn the NetworkObject.
+
+### Client-server
+
+```
+///
+/// Client-Server Spawning
+/// Pseudo player weapon that is assumed to be
+/// attached to a fixed child node of the player.
+/// (i.e. like a hand node or the like)
+///
+public class PlayerWeapon : NetworkBehaviour
+{
+ // For example purposes, the projectile to spawn
+ public GameObject Projectile;
+
+
+ // For example purposes, an offset from the weapon
+ // to spawn the projectile.
+ public GameObject WeaponFiringOffset;
+
+
+ public void FireWeapon()
+ {
+ if (!IsOwner)
+ {
+ return;
+ }
+
+
+ if (IsServer)
+ {
+ OnFireWeapon();
+ }
+ else
+ {
+ OnFireWeaponServerRpc();
+ }
+ }
+
+
+ [ServerRpc]
+ private void OnFireWeaponServerRpc()
+ {
+ OnFireWeapon();
+ }
+
+
+ private void OnFireWeapon()
+ {
+ var instance = Instantiate(Projectile);
+ var instanceNetworkObject = instance.GetComponent();
+ instance.transform.position = WeaponFiringOffset.transform.position;
+ instance.transform.forward = transform.forward;
+ instanceNetworkObject.Spawn();
+ }
+}
+```
+
+### Distributed authority
+
+```
+///
+/// Pseudo player weapon that is assumed to be
+/// attached to a fixed child node of the player.
+/// (i.e. like a hand node or the like)
+///
+public class PlayerWeapon : NetworkBehaviour
+{
+ // For example purposes, the projectile to spawn
+ public GameObject Projectile;
+
+
+ // For example purposes, an offset from the weapon
+ // to spawn the projectile.
+ public GameObject WeaponFiringOffset;
+
+
+ public void FireWeapon()
+ {
+ var instance = Instantiate(Projectile);
+ var instanceNetworkObject = instance.GetComponent();
+ instance.transform.position = WeaponFiringOffset.transform.position;
+ instance.transform.forward = transform.forward;
+ instanceNetworkObject.Spawn();
+ }
+}
+```
diff --git a/versioned_docs/version-2.0.0/community-contributions/codemonkey-videos.md b/versioned_docs/version-2.0.0/community-contributions/codemonkey-videos.md
new file mode 100644
index 000000000..60d381b04
--- /dev/null
+++ b/versioned_docs/version-2.0.0/community-contributions/codemonkey-videos.md
@@ -0,0 +1,63 @@
+---
+id: codemonkey
+title: Code Monkey tutorial videos
+---
+
+Code Monkey has a Multiplayer Unity Networking tutorial video that teachs various concepts of Netcode for GameObjects. Learn more about Code Monkey and his [Youtube channel](https://www.youtube.com/c/CodeMonkeyUnity), and don't forget to click the **Subscribe** button.
+
+This Unity Multiplayer video tutorial teaches you how to use Unity's Netcode For GameObjects to create a multiplayer game.
+
+
+
+
+
+Video published Sept 26, 2022
+
+This video covers
+
+- Getting Started with Unity Multiplayer (Netcode for Game Objects)
+- Installing Netcode for Game Objects
+- NetworkManager
+- Unity Transport
+- Creating the Player
+- NetworkObject
+- Assigning the PlayerPrefab and NetworkPrefab List
+- First Quick Test
+- What is Server, Host, Client
+- Creating UI Buttons
+- NetworkManagerUI
+- Set Verbose Logging
+- Optional: Add Quantum Console to easily read the logs
+- Making a Build
+- Testing Host and Client
+- PlayerNetwork Script, Movement, NetworkBehaviour
+- NetworkTransform
+- Server-Client Authoritative, Ownership
+- ClientNetworkTransform
+- NetworkVariable
+- NetworkVariable with Custom Data Type, INetworkSerializable
+- ServerRpc
+- ClientRpc
+- Spawning and Despawning Network Objects
+- NetworkAnimator
+- Multiplayer Tools Package
+- How to Connect to a IP
+- Online Multiplayer Issues, Port Forwarding, NAT Punchthrough
+- Unity Gaming Services (UGS), Relay, Lobby, Matchmaker, Multiplay
+
+
+
+:::contribution Community Contribution
+[Code Monkey](https://www.youtube.com/c/CodeMonkeyUnity) for the video tutorials! These contributions are a fantastic help to the community.
+:::
+
+import Iframe from 'react-iframe'
diff --git a/versioned_docs/version-2.0.0/community-contributions/dapper-videos.md b/versioned_docs/version-2.0.0/community-contributions/dapper-videos.md
new file mode 100644
index 000000000..de15967b1
--- /dev/null
+++ b/versioned_docs/version-2.0.0/community-contributions/dapper-videos.md
@@ -0,0 +1,33 @@
+---
+id: dapper
+title: Dapper Dino tutorial videos
+---
+
+Dapper Dino teaches various concepts about upgrading Unity's previous Multiplayer Networking solution, MLAPI to Netcode for GameObjects. Learn more about Dapper Dino and his [Youtube channel](https://www.youtube.com/channel/UCjCpZyil4D8TBb5nVTMMaUw), and don't forget to click the **Subscribe** button.
+
+This Unity Multiplayer tutorial will teach you how to upgrade your project from MLAPI to Unity's Netcode For GameObjects.
+
+
+
+
+
+Video published Nov 19, 2021
+
+:::important
+These tutorials use Unity v2021.1, and MLAPI 0.1.0. For information on modifying the code for use with Netcode for GameObjects please see [here](../installation/migratingfrommlapi.md)
+:::
+
+:::contribution Community Contribution
+Thank you to [DapperDino](https://www.youtube.com/channel/UCjCpZyil4D8TBb5nVTMMaUw) for the video tutorial! These contributions are a fantastic help to the community.
+:::
+
+import Iframe from 'react-iframe'
diff --git a/versioned_docs/version-2.0.0/community-contributions/dilmer-videos.md b/versioned_docs/version-2.0.0/community-contributions/dilmer-videos.md
new file mode 100644
index 000000000..a5b3e5491
--- /dev/null
+++ b/versioned_docs/version-2.0.0/community-contributions/dilmer-videos.md
@@ -0,0 +1,98 @@
+---
+id: dilmer
+title: Dilmer Valecillos tutorial videos
+---
+
+Dilmer Valecillos teaches various concepts about Netcode for GameObjects in the following video tutorials. Learn more about Dilmer Valecillos and his [Youtube channel](https://www.youtube.com/channel/UCHM37DnT_QGJT5Zyl4EmqcA), and don't forget to click the **Subscribe** button.
+
+:::important
+These tutorials use Unity v2021.1, and Netcode for GameObjects 1.0.0 prerelease.
+:::
+
+This Unity Multiplayer tutorial will teach you how to implement connection approval so that clients have to send the correct password to be able to connect to the server.
+
+
+
+Video published 14th Nov 2021
+
+This Unity Multiplayer tutorial will teach you how to implement:
+- NetworkVariable types and how to use them
+- Network Transforms to synchronize player position across the network
+- Synchronization of Player HUD over many clients
+- Player client controller and Network Behaviors
+- How and why should you use ServerRpc (Remote Procedure Calls)
+
+
+
+Video published 15th Nov 2021
+
+Dilmer takes a look at the Network Animator component and how you can synchronise animation states with other clients connected to the server or client-host. Features covered:
+
+
NetworkAnimator component
+
NetworkVariables Vector3 and permissions
+
NetworkVariables with enum type for player state
+
Using CharacterController to control the player
+
Using ServerRpc to keep track of player state
+
Animation state based on NetworkVariable player state
+
+
+
+
+Video published 15th Nov 2021
+
+Dilmer looks at how to set up multiplayer capabilities available over the internet
+
+
+
Setting up Relay server through Unity Services
+
Adding Unity Relay and Unity Transport UDP packages
+
Adding a new multiplayer relay scene with the Unity Transport in the NetworkManager
+
Creating a RelayManager singleton to create a Relay allocation and also provide a join code to clients connecting via relay
+
+
+
+
+Video published 25th Nov 2021
+
+For project files access, check out the repository here: https://github.com/dilmerv/UnityMultiplayerPlayground
+
+:::contribution Community Contribution
+Thank you to Dilmer Valecillos and his [Youtube channel](https://www.youtube.com/channel/UCHM37DnT_QGJT5Zyl4EmqcA) for the video tutorials! These contributions are a fantastic help to the community.
+:::
+
+import Iframe from 'react-iframe'
diff --git a/versioned_docs/version-2.0.0/components/networkanimator.md b/versioned_docs/version-2.0.0/components/networkanimator.md
new file mode 100644
index 000000000..34840e172
--- /dev/null
+++ b/versioned_docs/version-2.0.0/components/networkanimator.md
@@ -0,0 +1,149 @@
+---
+id: networkanimator
+title: NetworkAnimator
+---
+The `NetworkAnimator` component provides a fundamental example of how to synchronize animations during a network session. You can also use [RPCs](../advanced-topics/messaging-system.md), [NetworkVariables](../basics/networkvariable.md), and [custom messages](../advanced-topics/message-system/custom-messages.md) to create a custom animation synchronization system, if it suits the needs of your project better.
+
+Using `NetworkAnimator`, animation states are synchronized with players joining an existing network session and any client already connected before the animation state changes.
+
+* Players joining an existing network session are synchronized with:
+ * All the `Animator`'s current properties and states.
+ * *With the exception of [`Animator` trigger properties](#animator-trigger-property). These are only synchronized with already-connected clients.*
+ * Any in progress transition.
+* Players already connected are synchronized with changes to `Animator`:
+ * States
+ * Transitions
+ * Properties
+ * `NetworkAnimator` only synchronizes properties that have changed since the earlier frame property values.
+ * Since triggers are similar to an event, when an `Animator` property is set to `true` it will always be synchronized.
+
+`NetworkAnimator` can operate in two authoritative modes:
+
+* [Server authoritative](#server-authoritative-mode): The server initiates animation state changes. This is the default in [client-server topologies](../terms-concepts/client-server.md).
+ * Owners can still invoke `NetworkAnimator.SetTrigger`.
+* [Client authoritative](#owner-authoritative-mode): Client owners start animation state changes. This is the default in [distributed authority topologies](../terms-concepts/distributed-authority.md).
+
+
+:::note
+
+You need to use `Unity.Netcode.Components` to reference components such as `NetworkAnimator`.
+
+:::
+
+## `Animator` trigger property
+
+The `Animator` trigger property type is a Boolean value that, when set to `true`, is automatically reset back to `false` after the `Animator` component has processed the trigger. Usually, a trigger is used to start a transition between `Animator` layer states. You can use the trigger as a way to signal the beginning of an event. Because trigger properties have this unique behavior, you must set the trigger value via the `NetworkAnimator.SetTrigger` method.
+
+:::caution
+
+If you set a trigger property using `Animator.SetTrigger` then this won't be synchronized with non-owner clients.
+
+:::
+
+## Server authoritative mode
+
+In [client-server contexts](../terms-concepts/client-server.md), the default setting for `NetworkAnimator` is server authoritative mode. When operating in server authoritative mode, any animation state changes that are set (triggers) or detected (change in layer, state, or any `Animator` properties excluding triggers) on the server side will be synchronized with all clients. Because the server initiates any synchronization of changes to an `Animator`'s state, a client that's the owner of the NetworkObject associated with the `NetworkAnimator` can lag by roughly the full round trip time (RTT). Below is a timing diagram to show this:
+
+![ServerAuthMode](/img/NetworkAnimatorServerAuthTiming.png)
+
+In the above diagram, a client might be sending the server an RPC to tell the server that the player is performing some kind of action that can change the player's animations (including setting a trigger). In this scenario, the client sends an RPC to the server (half RTT), the server processes the RPC, the associated `Animator` state changes are detected by the `NetworkAnimator` (server-side), and then all clients (including the owner client) are synchronized with the change.
+
+**Server authoritative model benefits:**
+
+* If running a non-host server, this model reduces the synchronization latency between all client animations.
+
+**Server authoritative model drawbacks:**
+
+* Hosts are always slightly ahead of all other clients, which may or may not be an issue for your project.
+* Client owners will experience latency between performing an action (moving, picking something up, anything that causes an `Animator` state change).
+
+## Owner authoritative mode
+
+Your project's design (or personal preference) might require that owners are immediately updated with any `Animator` state changes, typically to give the local player instantaneous visual (animation) feedback. In [distributed authority contexts](../terms-concepts/distributed-authority.md), the default setting for `NetworkAnimator` is owner authoritative mode.
+
+To create an owner authoritative `NetworkAnimator` in a client-server context, you need to create a new class that's derived from `NetworkAnimator`, override the `NetworkAnimator.OnIsServerAuthoritative` method, and within the overridden `OnIsServerAuthoritative` method you should return false like in the example provided below:
+
+```csharp
+ public class OwnerNetworkAnimator : NetworkAnimator
+ {
+ protected override bool OnIsServerAuthoritative()
+ {
+ return false;
+ }
+ }
+```
+
+The diagram below illustrates that with an owner authoritative `NetworkAnimator`, the owner client gets an immediate visual animation response, while non-owner clients end up being roughly one full RTT behind the owner client and a host would be half RTT behind the owner client.
+
+![ServerAuthMode](/img/NetworkAnimatorOwnerAuthTiming.png)
+
+The diagram above shows that the owner client has an `Animator` state change that's detected by the `NetworkAnimator` ( `OwnerNetworkAnimator`) which automatically synchronizes the server with the changed state. The server applies the change(s) locally and then broadcasts this state change to all non-owner clients.
+
+**Owner authoritative model benefits:**
+
+* The owner is provided instant visual feedback of `Animator` state changes, which provides a smoother experience for the local player.
+
+**Owner authoritative model drawbacks:**
+
+* Non-owner clients lag behind the owner client's animation by roughly one full RTT.
+* A host lags behind the owner client's animation by roughly half RTT.
+
+:::caution
+
+The same rule for setting trigger properties still applies to owner clients. As such, if you want to programmatically set a trigger then you still need to use `NetworkAnimator.SetTrigger`.
+
+:::
+
+## Using NetworkAnimator
+
+Using `NetworkAnimator` is relatively straightforward, with the only difference being whether you implement a server or owner authoritative model.
+
+:::important
+
+`NetworkAnimator` is one of several possible ways to synchronize animations during a network session. Netcode for GameObjects provides you with the building blocks ([RPCs](../advanced-topics/messaging-system.md), [NetworkVariables](../basics/networkvariable.md), and [custom messages](../advanced-topics/message-system/custom-messages.md)) needed to create an alternative animation synchronization system that has a completely different and potentially more optimized approach. `NetworkAnimator` is a basic approach provided for users already familiar with the `Animator` component and, depending upon your project's design requirements, might be all that you need.
+
+:::
+
+### Server authoritative
+
+If you want to use a server authoritative model, then you can add a `NetworkAnimator` component to either the same GameObject that has the NetworkObject component attached to it, or any child `GameObject`. In the screenshot below, you can see a network prefab that contains two authoritative models. The `NetworkAnimatorCube-Server` `GameObject` has an `Animator` component, an `AnimatedCubeController` component (used for manual testing), and the `NetworkAnimator` component that has a reference to the `Animator` component.
+
+![Usage-1](/img/NetworkAnimatorUsage-1.png)
+
+### Owner authoritative
+
+If you want to use an owner authoritative model, then (for example purposes) you can use your derived `OwnerNetworkAnimator` component instead of the default `NetworkAnimator` component like in the screenshot below:
+
+![Usage-1](/img/NetworkAnimatorUsage-2.png)
+
+:::info
+
+While it isn't recommended to have different `NetworkAnimator` authoritative models under the same root network prefab `GameObject`, you can have multiple children that each have their own `Animator` and `NetworkAnimator`, all contained under a single NetworkObject and all using the same authoritative model. However, you should always consider the balance between performance (CPU or bandwidth consumption) and convenience/modularity.
+
+:::
+
+### Changing animator properties
+
+For all `Animator` properties (except for triggers), you can set them directly via the `Animator` class. For example, you might use the player's normalized velocity as a way to control the walking or running animation of a player. You might have an `Animator` `float` property called `"AppliedMotion"` that you set on the authoritative instance (server or owner) like so:
+
+```csharp
+public void ApplyMotion(Vector3 playerVelocity)
+{
+ m_Animator.SetFloat("AppliedMotion", playerVelocity.normalized.magnitude);
+}
+```
+
+For triggers, you always want to use `NetworkAnimator`. One example might be that you use a trigger, called " `IsJumping`, " to start a blended transition between the player's walking/running animation and the jumping animation:
+
+```csharp
+public void SetPlayerJumping(bool isJumping)
+{
+ m_NetworkAnimator.SetTrigger("IsJumping");
+}
+```
+
+:::tip Changing meshes
+
+When swapping a skinned mesh with another reparented skinned mesh, you can invoke the `Rebind ` method on the `Animator` components: `Animator.Rebind()`.
+
+:::
diff --git a/versioned_docs/version-2.0.0/components/networkmanager.md b/versioned_docs/version-2.0.0/components/networkmanager.md
new file mode 100644
index 000000000..8eb91f548
--- /dev/null
+++ b/versioned_docs/version-2.0.0/components/networkmanager.md
@@ -0,0 +1,249 @@
+---
+id: networkmanager
+title: NetworkManager
+---
+
+The `NetworkManager` is a required Netcode for GameObjects component that has all of your project's netcode-related settings. Think of it as the central netcode hub for your netcode-enabled project.
+
+### `NetworkManager` Inspector properties
+
+- **LogLevel**: Sets the network logging level
+- **PlayerPrefab**: When a prefab is assigned, the prefab will be instantiated as the PlayerObject and assigned to the newly connected and authorized client. For more information about player prefabs, refer to [PlayerObjects and player prefabs](../basics/playerobjects.md).
+- **NetworkPrefabs**: Where you register your network prefabs. You can also create a single network prefab override per registered network prefab here.
+- **Protocol Version**: Set this value to help distinguish between builds when the most current build has new assets that can cause issues with older builds connecting.
+- **Network Transport**: Where your network specific settings and transport type is set. This field accepts any INetworkTransport implementation. However, unless you have unique transport specific needs UnityTransport is the recommended transport to use with Netcode for GameObjects.
+- **Tick Rate**: This value controls the network tick update rate.
+- **Ensure Network Variable Length Safety**: (Increases cpu processing and bandwidth) When this property is checked, Netcode for GameObjects will prevent user code from writing past the boundaries of a NetworkVariable.
+- **Connection Approval**: This enables [connection approval](../basics/connection-approval.md) when this is checked and the `NetworkManager.ConnectionApprovalCallback` is assigned.
+- **Client Connection Buffer Timeout**: This value sets the amount of time that has to pass for a connecting client to complete the connection approval process. If the time specified is exceeded the connecting client will be disconnected.
+- **Force Same Prefabs**: When checked it will always verify that connecting clients have the same registered network prefabs as the server. When not checked, Netcode for GameObjects will ignore any differences.
+- **Recycle Network Ids**: When checked this will re-use previously assigned `NetworkObject.NetworkObjectIds` after the specified period of time.
+- **Network Id Recycle Delay**: The time it takes for a previously assigned but currently unassigned identifier to be available for use.
+- **Enable Scene Management**: When checked, Netcode for GameObjects will handle scene management and client synchronization for you. When not checked, you will have to create your own scene management scripts and handle client synchronization.
+- **Load Scene Time Out**: When Enable Scene Management is checked, this specifies the period of time the `NetworkSceneManager` will wait while a scene is being loaded asynchronously before `NetworkSceneManager` considers the load/unload scene event to have failed/timed out.
+
+### `NetworkManager` sub-systems
+
+`NetworkManager` is also where you can find references to other Netcode related management systems:
+
+:::caution
+All `NetworkManager` sub-systems are instantiated once the `NetworkManager` is started (that is, `NetworkManager.IsListening == true`). A good general "rule of thumb" is to not attempt to access the below sub-systems before starting the `NetworkManager`, otherwise they won't yet be initialized.
+:::
+
+- [NetworkManager.PrefabHandler](../advanced-topics/object-pooling.md): This provides access to the NetworkPrefabHandler that is used for NetworkObject pools and to have more control overriding network prefabs.
+- [NetworkManager.SceneManager](../basics/scenemanagement/using-networkscenemanager.md): When scene management is enabled, this is used to load and unload scenes, register for scene events, and other scene management related actions.
+- [NetworkManager.SpawnManager](../basics/object-spawning.md): This handles NetworkObject spawn related functionality.
+- [NetworkManager.NetworkTimeSystem](../advanced-topics/networktime-ticks.md): a synchronized time that can be used to handle issues with latency between a client and the server.
+- [NetworkManager.NetworkTickSystem](../advanced-topics/networktime-ticks#network-ticks.md): Use this to adjust the frequency of when NetworkVariables are updated.
+- [NetworkManager.CustomMessagingManager](../advanced-topics/message-system/custom-messages.md): Use this system to create and send custom messages.
+
+## Starting a server, host, or client
+
+To perform any netcode-related action that involves sending messages, you must first have a server started and listening for connections with at least one client (_a server can send RPCs to itself when running as a host_) that is connected. To accomplish this, you must first start your `NetworkManager` as a server, host, or client. There are three `NetworkManager` methods you can invoke to accomplish this:
+
+```csharp
+NetworkManager.Singleton.StartServer(); // Starts the NetworkManager as just a server (that is, no local client).
+NetworkManager.Singleton.StartHost(); // Starts the NetworkManager as both a server and a client (that is, has local client)
+NetworkManager.Singleton.StartClient(); // Starts the NetworkManager as just a client.
+```
+
+:::warning
+Don't start a `NetworkManager` within any `NetworkBehaviour` component's method; doing so can produce timing-related issues that cause the `NetworkManager` to only start once or not at all. `NetworkManager`s begin and end a network session, while `NetworkBehaviour` components are used during a network session. By the time you're using `NetworkBehaviour`s, a `NetworkManager` should already be running.
+:::
+
+:::note
+ When starting a Server or joining an already started session as client, the `NetworkManager` can spawn a "Player Object" belonging to the client.
+
+ For more information about player prefabs see:
+ - [NetworkObject Player Prefab Documentation](../basics/networkobject.md#player-objects)
+ - [Connection Approval](../basics/connection-approval)
+:::
+
+## Connecting
+
+When starting a client, the `NetworkManager` uses the IP and the Port provided in your `Transport` component for connecting. While you can set the IP address in the editor, many times you might want to be able to set the IP address and port during runtime.
+
+The below examples use [Unity Transport](../../../transport/current/about) to show a few ways you can gain access to the `UnityTransport` component via the `NetworkManager.Singleton` to configure your project's network settings programmatically:
+
+If you are only setting the IP address and port number, then you can use the `UnityTransport.SetConnectionData` method:
+```csharp
+NetworkManager.Singleton.GetComponent().SetConnectionData(
+ "127.0.0.1", // The IP address is a string
+ (ushort)12345 // The port number is an unsigned short
+);
+```
+
+If you are using the same code block to configure both your server and your client and you want to configure your server to listen to all IP addresses assigned to it, then you can also pass a 'listen address' of "0.0.0.0" to the `SetConnectionData` method, like so:
+```csharp
+NetworkManager.Singleton.GetComponent().SetConnectionData(
+ "127.0.0.1", // The IP address is a string
+ (ushort)12345, // The port number is an unsigned short
+ "0.0.0.0" // The server listen address is a string.
+);
+```
+
+:::note
+Using an IP address of 0.0.0.0 for the server listen address will make a server or host listen on all IP addresses assigned to the local system. This can be particularly helpful if you are testing a client instance on the same system as well as one or more client instances connecting from other systems on your local area network. Another scenario is while developing and debugging you might sometimes test local client instances on the same system and sometimes test client instances running on external systems.
+:::
+
+It is possible to access the current connection data at runtime, via `NetworkManager.Singleton.GetComponent().ConnectionData`. This will return a [`ConnectionAddressData` **struct**](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/11922a0bc100a1615c541aa7298c47d253b74937/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs#L239-L286), holding this info. You are strongly advised to use the `SetConnectionData` method to update this info.
+
+If you are using Unity Relay to handle connections, however, **don't use `SetConnectionData`**. The host should call [`SetHostRelayData`](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/11922a0bc100a1615c541aa7298c47d253b74937/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs#L575), and clients should call [`SetClientRelayData`](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/11922a0bc100a1615c541aa7298c47d253b74937/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs#L588). Attempting to join a **Relay**-hosted game via entering IP/port number (via `SetConnectionData`) **won't work**.
+
+
+[More information about Netcode for GameObjects Transports](../advanced-topics/transports.md)
+
+## Disconnecting and shutting down
+
+### Disconnect from a network
+
+When you disconnect from a network you can't use or access any subsystems, for example `NetworkSceneManager`, because they become unavailable when `NetworkManager` stops. For client, host, or server modes, call the `NetworkManager.Shutdown` method to disconnect and shut down at the same time.
+
+:::info
+When no network session is active and the `NetworkManager` has been shutdown, you will need to use `UnityEngine.SceneManagement` to load any non-network session related scene.
+:::
+
+```csharp
+public void Disconnect()
+{
+ NetworkManager.Singleton.Shutdown();
+ // At this point we must use the UnityEngine's SceneManager to switch back to the MainMenu
+ UnityEngine.SceneManagement.SceneManager.LoadScene("MainMenu");
+}
+```
+
+### Shut down a network session
+
+When you invoke `NetworkManager.Shutdown` it closes any existing transport connections. The shutdown sequence for a client finishes before the next player loop update or frame. However, the shutdown sequence can take a bit longer for a server or host (server-host).
+
+The server-host notifies all clients when it shuts down. To do this, when you invoke `NetworkManager.Shutdown` the server-host sends out a disconnect notification to all currently connected clients and populates the `NetworkManager.Disconnect` reason with one of the two following messages, depending upon whether it's a server or host instance:
+
+- "Disconnected due to server shutting down."
+- "Disconnected due to host shutting down."
+
+The server-host attempts to wait for all client connections to close before it finishes the shutdown sequence. This additional step on the server-host side helps to assure that clients receive a disconnect notification and prevents the client transport connection from timing out. If some client connections take longer than five seconds to close after `NetworkManager.Shutdown` is invoked, the server-host automatically finishes the shutdown sequence and closes any remaining connections.
+
+## Disconnecting clients (server only)
+
+At times you might need to disconnect a client for various reasons without shutting down the server. To do this, you can call the `NetworkManager.DisconnectClient` method while passing the identifier of the client you wish to disconnect as the only parameter. The client identifier can be found within:
+
+- The `NetworkManager.ConnectedClients` dictionary that uses the client identifier as a key and the value as the [`NetworkClient`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkClient.html).
+- As a read only list of `NetworkClients` via the `NetworkManager.ConnectedClientsList`.
+- A full list of all connected client identifiers can be accessed via `NetworkManager.ConnectedClientsIds`.
+- The client identifier is passed as a parameter to all subscribers of the `NetworkManager.OnClientConnected` event.
+- The player's NetworkObject has the `NetworkObject.OwnerClientId` property.
+
+:::tip
+One way to get a player's primary NetworkObject is via `NetworkClient.PlayerObject`.
+:::
+
+```csharp
+void DisconnectPlayer(NetworkObject player)
+{
+ // Note: If a client invokes this method, it will throw an exception.
+ NetworkManager.DisconnectClient(player.OwnerClientId);
+}
+```
+
+### Client disconnection notifications
+
+Both the client and the server can subscribe to the `NetworkManager.OnClientDisconnectCallback` event to be notified when a client is disconnected.
+
+**When disconnect notifications are triggered:**
+- Clients are notified when they're disconnected by the server.
+- The server is notified when any client disconnects from the server, whether the server disconnects the client or the client disconnects itself.
+- Both the server and clients are notified when their network connection is unexpectedly disconnected (network interruption).
+
+**Client notification identifiers**
+- On the server-side, the client identifier parameter is the identifier of the client that disconnects.
+- On the client-side, the client identifier parameter is the identifier assigned to the client.
+ - _The exception to this is when a client is disconnected before its connection is approved._
+
+You can also use the `NetworkManager.OnServerStopped` and `NetworkManager.OnClientStopped` callbacks to get local notifications when the server or client stops respectively.
+
+### Connection notification manager example
+Below is one example of how you can provide client connect and disconnect notifications to any type of NetworkBehaviour or MonoBehaviour derived component.
+
+:::important
+The `ConnectionNotificationManager` example below should only be attached to the same GameObject as `NetworkManager` to assure it persists as long as the `NetworkManager.Singleton` instance.
+:::
+
+
+```csharp
+using System;
+using UnityEngine;
+using Unity.Netcode;
+
+///
+/// Only attach this example component to the NetworkManager GameObject.
+/// This will provide you with a single location to register for client
+/// connect and disconnect events.
+///
+public class ConnectionNotificationManager : MonoBehaviour
+{
+ public static ConnectionNotificationManager Singleton { get; internal set; }
+
+ public enum ConnectionStatus
+ {
+ Connected,
+ Disconnected
+ }
+
+ ///
+ /// This action is invoked whenever a client connects or disconnects from the game.
+ /// The first parameter is the ID of the client (ulong).
+ /// The second parameter is whether that client is connecting or disconnecting.
+ ///
+ public event Action OnClientConnectionNotification;
+
+ private void Awake()
+ {
+ if (Singleton != null)
+ {
+ // As long as you aren't creating multiple NetworkManager instances, throw an exception.
+ // (***the current position of the callstack will stop here***)
+ throw new Exception($"Detected more than one instance of {nameof(ConnectionNotificationManager)}! " +
+ $"Do you have more than one component attached to a {nameof(GameObject)}");
+ }
+ Singleton = this;
+ }
+
+ private void Start()
+ {
+ if (Singleton != this){
+ return; // so things don't get even more broken if this is a duplicate >:(
+ }
+
+ if (NetworkManager.Singleton == null)
+ {
+ // Can't listen to something that doesn't exist >:(
+ throw new Exception($"There is no {nameof(NetworkManager)} for the {nameof(ConnectionNotificationManager)} to do stuff with! " +
+ $"Please add a {nameof(NetworkManager)} to the scene.");
+ }
+
+ NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnectedCallback;
+ NetworkManager.Singleton.OnClientDisconnectCallback += OnClientDisconnectCallback;
+ }
+
+ private void OnDestroy()
+ {
+ // Since the NetworkManager can potentially be destroyed before this component, only
+ // remove the subscriptions if that singleton still exists.
+ if (NetworkManager.Singleton != null)
+ {
+ NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnectedCallback;
+ NetworkManager.Singleton.OnClientDisconnectCallback -= OnClientDisconnectCallback;
+ }
+ }
+
+ private void OnClientConnectedCallback(ulong clientId)
+ {
+ OnClientConnectionNotification?.Invoke(clientId, ConnectionStatus.Connected);
+ }
+
+ private void OnClientDisconnectCallback(ulong clientId)
+ {
+ OnClientConnectionNotification?.Invoke(clientId, ConnectionStatus.Disconnected);
+ }
+}
+```
diff --git a/versioned_docs/version-2.0.0/components/networktransform.md b/versioned_docs/version-2.0.0/components/networktransform.md
new file mode 100644
index 000000000..570a85984
--- /dev/null
+++ b/versioned_docs/version-2.0.0/components/networktransform.md
@@ -0,0 +1,222 @@
+---
+id: networktransform
+title: NetworkTransform
+---
+
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+## Introduction
+
+The synchronization of an object's transform is one of the core netcode tasks. The outline of operations is simple:
+- Determine which transform axis you want to have synchronized
+- Serialize the values
+- Send the serialized values as messages to all other connected clients
+- Process the messages and deserialize the values
+- Apply the values to the appropriate axis
+
+Except the implementation is far more complicated than one might expect. For example, we need to take into consideration:
+- Who controls the synchronization (i.e. each client or the server or perhaps both depending upon the object being synchronized)?
+- How often do you synchronize the values?
+- What logic should you use to determine when and which values need to be synchronized?
+- For objects with one or more child objects, should you synchronize world or local space axis values?
+- How can you optimize the bandwidth for a transform update?
+
+Fortunately, Netcode for GameObjects provides you with the NetworkTransform component. It handles many of the tricky aspects of transform synchronization and can be configured via Inspector properties.
+
+## Adding the component
+
+When adding a NetworkTransform component to a GameObject, it requires a NetworkObject on the same or a parent GameObject for it to function.
+
+In this image both NetworkTransform and NetworkObject components are on the same GameObject:
+
+![image](/img/NetworkTransformSimple.png)
+
+Alternatively, a parent GameObject can have the NetworkObject component while the NetworkTransform is attached to a child object:
+
+![image](/img/NetworkTransformSimpleParent.png)
+
+You can also have NetworkTransform components on several child objects, all sharing the same NetworkObject in their common parent object:
+
+![image](/img/NetworkTransformNestedParent.png)
+
+With such nested NetworkTransforms you can theoretically have a NetworkTransform on every child object. _However, we recommend exercising caution with the amount of nested NetworkTransforms in a network prefab. Particularly if there will be many instances of this network prefab._
+
+
+:::tip
+**The general rule to follow is:**
+
+ As long as there is at least one (1) NetworkObject at the same GameObject hierarchical level or above, you can attach a NetworkTransform component to a GameObject.
+
+ _You could have a single root-parent GameObject that has a NetworkObject component and under the root-parent several levels of nested child GameObjects that all have NetworkTransform components attached to them. Each child GameObject would not require a NetworkObject component in order for each respective NetworkTransform component to function/synchronize properly._
+:::
+
+
+## Configuring
+
+When you select a NetworkTransform component, you will see the following properties in the inspector view:
+
+![image](/img/NetworkTransformProperties.png)
+
+### Property synchronization
+
+Some of the `NetworkTransform` properties are automatically synchronized by the authoritative instance to all non-authoritative instances. It is **important to note** that when any synchronized property changes the NetworkTransform is effectively "teleported" (i.e. all values re-synchronized and interpolation is reset) which can cause a single frame delta in position, rotation, and scale (depending upon what is being synchronized). _Always keep this in mind when making adjustments to NetworkTransform properties during runtime._
+
+### Synchronizing
+
+You often don't need to synchronize all transform values of a GameObject over the network. For instance, if the scale of the GameObject never changes, you can deactivate it in the **syncing scale** row in the Inspector. Deactivating synchronization saves CPU costs and network bandwidth.
+
+The term "synchronizing" refers to the synchronization of axis values over time. This is not to be confused with the initial synchronization of a transform's values. As an example:
+ If you don't plan on changing the transform's scale after the initial first synchronization (i.e. upon joining a network session or when a network prefab instance is spawned for the first time), then un-checking/disabling the X, Y, and Z properties for Scale synchronization would remove the additional processing overhead per instance.
+
+Since these values really only apply to the authoritative instance, changes can be made to these values during runtime and non-authoritative instances will only receive updates for the axis marked for synchronization on the authoritative side.
+
+### Thresholds
+
+You can use the threshold values to set a minimum threshold value. This can be used to help reduce the frequency of synchronization updates by only synchronizing changes above or equal to the threshold values (changes below won't be synchronized). As an example:
+
+If your `NetworkTransform` has `Interpolate` enabled, you might find that you can lower your position threshold resolution (i.e. by increasing the position threshold value) without impacting the "smoothness" of an object's motion while also reducing the frequency of position updates (i.e. reduces the bandwidth cost per instance). Increasing the threshold resolution (i.e. by lowering the position threshold value) will increase the potential frequency of when the object's position will be synchronize (i.e. can increase the bandwidth cost per instance).
+
+:::info
+Threshold values are not synchronized, but they can be updated on the [authoritative instance](networktransform#authority-modes). You should keep this in mind when using [owner authoritative mode](networktransform#owner-authoritative-mode) instances since changing ownership will use whatever values are currently set on the new owner instance. If you plan on changing the threshold value during runtime and plan on changing ownership, then you might need to synchronize the threshold values as well.
+:::
+
+### Delivery
+
+Sometimes network conditions are not exactly "optimal" where packets can have both undesirable latency and even the dreaded packet loss. When NetworkTransform interpolation is enabled, packet loss can mean undesirable visual artifacts (_i.e. large visual motion gaps often referred to as "stutter"_). Originally, NetworkTransform sent every state update using reliable fragmented sequenced network delivery. For interpolation, with enough latency and packet loss this could cause a time gap between interpolation points which eventually would lead to the motion "stutter". Fortunately, NetworkTransform has been continually evolving and defaults to sending the more common delta state updates (_i.e. position, rotation, or scale changes_) as unreliable sequenced network delivered messages. If one state is dropped then the `BufferedLinearInterpolator` can recover easily as it doesn't have to wait precisely for the next state update and can just lose a small portion of the over-all interpolated path (_i.e. with a TickRate setting of 30 you could lose 5 to 10% of the over-all state updates over one second and still have a relatively similar interpolated path to that of a perfectly delivered 30 delta state updates generated path_). As such, the UseUnreliableDeltas NetworkTransform property, default to enabled, controls whether you send your delta state updates unreliably or reliably.
+
+Of course, you might wonder what would happen if say 5% of a jumping motion, towards the end of the jumping motion, were dropped how NetworkTransform might recover since each state update sent is only based on axial deltas defined by each axis threshold settings. The answer is that there is a small bandwidth penalty for sending standard delta state updates unreliably: Axial Frame Synchronization.
+
+#### Axial frame synchronization
+
+When unreliable delta state updates is enabled (UseUnreliableDeltas is enabled), NetworkTransform instances are assigned a constantly rolling tick position relative to a 1 second period of time. So, if you are using the default `NetworkConfig.TickRate` value (30) there are 30 "tick slots" that each NetworkTransform instance is distributed amongst on the authoritative instance. This means that each instance will send 1 Axial Frame Synchronization update per second while the NetworkObject in question is moving, rotating, or scaling enough to trigger delta state updates. When a NetworkObject comes to rest (i.e. no longer sending delta state updates) the Axial Frame Synchronization stops. This assures that if a vital portion of a state update is dropped, within a 1 second period of time, all axis marked to be synchronized will be synchronized to provide an eventual consistency in axis synchronization between the authority and non-authority instances.
+
+:::info
+If bandwidth consumption becomes a concern and you have tested your project under normal network conditions with UseUnreliableDeltas disabled with no noticeable visual artifacts, then you can opt out of unreliable delta state updates to recover the minor penalty for being packet loss tolerant or you might opt to make that an in-game configuration setting that players can enable or disable. You just need to update the authoritative NetworkTransform instances with any change in the setting during runtime.
+:::
+
+### Local space
+
+By default, `NetworkTransform` synchronizes the transform of an object in world space. The **In Local Space** configuration option allows you to change to synchronizing the transform in local space instead. A child's local space axis values (position and rotation primarily) are always relative offsets from the parent transform. Where a child's world space axis values include the parent's axis values.
+
+Using **local space** on a parented NetworkTransform can improve the synchronization of the transform when the object gets re-parented because the re-parenting won't change the **local space** transform of the object but does change the **world space** position.
+
+:::info
+The authority instance does synchronize changes to the LocalSpace property. As such,you can make adjustments to this property on the authoritative side during runtime and the non-authoritative instances will automatically be updated.
+:::
+
+### Interpolation
+
+Interpolation is enabled by default and is recommended if you desire smooth transitions between transform updates on non-authoritative instances.Interpolation will buffer incoming state updates that can introduce a slight delay between the authority and non-authority instances. When the **Interpolate** property is disabled, changes to the transform are immediately applied on non-authoritative instances which can result in a visual "jitter" and/or seemingly "jumping" to newly applied state updates when latency is high.
+
+Changes to the **Interpolation** property during runtime on the authoritative instance will be synchronized with all non-authoritative instances.
+
+:::note
+The `NetworkTransform` component only interpolates client-side. For smoother movement on the host or server, users might want to implement interpolation server-side as well. While the server won't have the jitter caused by the network, some stutter can still happen locally (for example, movement done in `FixedUpdate` with a low physics update rate).
+:::
+
+
+
+### Slerp position
+
+When this property and **Interpolation** are both set, non-authoritative instances will [Slerp](https://docs.unity3d.com/ScriptReference/Vector3.Slerp.html) towards their destination position as opposed to [Lerp](https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html). Typically this can be used when your object is following a circular and/or spline based motion path and you want to preserve the curvature of that path. Since "lerping" between two points yields a linear progression over a line between two points, there can be scenarios where the frequency of delta position state updates could yield a loss in the curvature of an object's motion.
+
+### Use quaternion synchronization
+
+By default, rotation deltas are synchronized using Euler values. For many scenarios, using Euler values might be all that is needed. However, there are scenarios where synchronizing Euler deltas will yield undesirable results. One scenario is when you have complex nested NetworkTransforms where there are varying rotations between the parents and children transforms. When you add interpolation into the mix (_remember interpolation is buffered and has an inherent delay between the non-authoritative's current rotation and the target rotation_), there are adjustments that occur immediately within a Quaternion that handle more complex transform related issues (i.e. Gimbal Lock, etc).
+
+With Quaternion synchronization enabled, the authoritative instance still compares threshold values against the Euler axis values to determine if an update in a transform's rotation is needed but the entire Quaternion itself is updated as opposed to just the Euler axis where the change(s) is/are detected. This means that you are guaranteed the proper rotation for an object will be applied to non-authoritative instances and the changes will have already accounted for more complex issues that can arise with Euler angles.
+
+Quaternion synchronization comes with a price. It will increase the bandwidth cost, 16 bytes per instance, in exchange for handling the more complex rotation issues that more often occur when using nested NetworkTransform (one or more parent transforms with one or more child transforms). However, when you enable the **Use Quaternion Synchronization** property you will notice a change in both the **Syncing** axis selection check boxes and a new **Use Quaternion Compression** property will appear:
+
+![image](/img/NetworkTransformQuaternionSynch.png)
+
+:::note
+
+The rotation synchronization axis checkboxes are no longer available when **Use Quaternion Synchronization** is enabled (_since synchronizing the quaternion of a transform will always update all rotation axis_) and **Use Quaternion Compression** becomes a visible option.
+
+:::
+
+### Use quaternion compression
+
+Since synchronizing a quaternion can increase the bandwidth cost per update of a `NetworkTransform`'s rotation state, there are two ways to reduce the over-all bandwidth cost of quaternion synchronization:
+- **Quaternion Compression:** This provides the highest compression (16 bytes reduced down to 4 bytes per update) with a slightly higher precision loss than half float precision.
+- **Half Float Precision:** When enabled and **Use Quaternion Compression** is disabled, this provides an alternate mid-level compression (16 bytes reduced down to 8 bytes per update) with less precision than full float values but higher precision than quaternion compression.
+
+Quaternion compression is based on a smallest three algorithm that can be used when rotation precision is less of a concern than the bandwidth cost. You might have ancillary objects/projectiles that require some form of rotation synchronization, but in the over-all scheme of your project do not require perfect alignment. If bandwidth cost and precision are both a concern, then the alternate recommended compression is half float precision. It is also recommended to try out the different compression options, you might find that the fractional loss in precision is perfectly acceptable for your project's needs (_with the bonus of being able to reduce the over-all bandwidth cost by up to 50% for all instances than when using full precision_).
+
+This property value can be updated on the authority during runtime and will be synchronized on all non-authority instances. _Reminder: Updating this value during runtime on the authoritative instance will result in a full synchronization of the NetworkTransform and all non-authority instances will have their interpolators reset._
+
+### Use half float precision
+
+Enabling this property does exactly what it sounds like, it converts any transform axial value from a 4 byte float to a 2 byte half-float at the expense of a loss in precision. When this option is enabled, half float precision is used for all transform axis marked for synchronization. However, there are some unique aspects of half float precision when it comes to position and rotation.
+
+Since there is a loss in precision, position state updates only provide the delta in position relative to the last known full position. The `NetworkDeltaPosition` serializable structure keeps track of the current delta between the last known full position and the current delta offset from the last known full position. Additionally, `NetworkDeltaPosition` auto-corrects precision loss by determining any loss of precision on the authoritative side when sending an update. Any precision delta from the previous update will be included in the next position update. _In other words, non-authoritative instances can potentially have a fractional delta (per applied update) from the authoritative instance for the duration of 1 network tick period or until the next transform state update is received._ Additionally, `NetworkDeltaPosition` bridges the gap between the [maximum half float value](https://github.com/Unity-Technologies/Unity.Mathematics/blob/701d58fde76f3b93e40d0a792cd8fa4c130f1450/src/Unity.Mathematics/half.cs#L25) and the maximum boundaries of the Unity World space (global/project scale relative).
+
+:::info
+
+**Recommended Unity World Space Units Per Second:**
+
+The maximum delta per update should not exceed 64 Unity world space units. If you are using the default network tick (30) then an object should not move at speeds that are equal to or exceed 1,920 Unity world space units per second (i.e. 30 x 64). To give you a frame of reference, the default camera far clipping plane is 1,000 Unity world space units which means something moving at 1,920 Unity world space units would most likely not be visually detectable or appear as a brief "blip" in the render view frustum.
+
+:::
+
+When **Use Quaternion Synchronization** and **Use Half Float Precision** are both enabled and **Use Quaternion Compression** is disabled, the quaternion values are synchronized via the `HalfVector4` serializable structure where each axial value (x, y, z, and w) are stored as [half values](https://docs.unity3d.com/Packages/com.unity.mathematics@1.2/api/Unity.Mathematics.half.html). This means that each rotation update is reduced from a full precision 16 bytes per update down to 8 bytes per update. Using half float precision for rotation provides a better precision than quaternion compression at 2x the bandwidth cost but half the cost of full precision.
+
+When **Use Quaternion Synchronization**, **Use Half Float Precision**, and **Use Quaternion Compression** are enabled, quaternion compression is used in place of half float precision for rotation.
+
+All of these properties are synchronized to non-authoritative instances when updated on the authoritative instance.
+
+
+## Authority modes
+
+### Server authoritative mode
+
+By default, `NetworkTransform` operates in server authoritative mode. This means that changes to transform axis (marked to be synchronized) are detected on the server-side and pushed to connected clients. This also means any changes to the transform axis values will be overridden by the authoritative state (in this case the server-side transform state).
+
+There is another concept to keep in mind about axis synchronization vs the initial synchronized transform values. Any axis not marked to be synchronized will still be updated with the authority's initial state when a NetworkObject is spawned or when a client is synchronized for the first time.
+
+:::info
+**As an example:**
+Say you have marked only the position and rotation axis to be synchronized but exclude all scale axis on a NetworkTransform component for a network prefab. When you spawn an instance of the network prefab the initial authoritative side scale values are synchronized upon spawning. From that point forward, the non-authoritative instances (in this case the client-side instances) will maintain those same scale axis values even though they are never updated again.
+:::
+
+### Owner authoritative mode
+**(a.k.a. ClientNetworkTransform)**
+
+ Server-side authority NetworkTransforms provide a balance between synchronized transforms and the latency between applying the updates on all connected clients. However, there are times when you want the position to update immediately for a specific NetworkObject (common the player) on the client-side. Owner authority of a NetworkTransform is dictated by the `NetworkTransform.OnIsServerAuthoritative` method when a NetworkTransform component is first initialized. If it returns `true` (the default) then it initializes as a server authoritative `NetworkTransform`. If it returns `false` then it initializes as an owner authoritative `NetworkTransform` (a.k.a. `ClientNetworkTransform`). This can be achieved by deriving from `NetworkTransform`, overriding the `OnIsServerAuthoritative` virtual method, and returning false like in the code example below:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs
+```
+
+Netcode for GameObjects also comes with a sample containing a `ClientNetworkTransform`. This transform synchronizes the position of the owner client to the server and all other client allowing for client authoritative gameplay.
+
+You can use the existing `ClientNetworkTransform` in the Multiplayer Samples Utilities package.
+
+To add the Multiplayer Samples Utilities package:
+
+* Open the Package Manager by selecting **Window** > **Package Manager**.
+* Select **Add** (+) > **Add from git URL…**.
+* Copy and paste the following Git URL: `https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main`
+* Select **Add**.
+
+Optionally, you can directly add this line to your `manifest.json` file:
+
+`"com.unity.multiplayer.samples.coop": "https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main"`
+
+## Additional virtual methods of interest
+
+`NetworkTransform.OnAuthorityPushTransformState`: This virtual method is invoked when the authoritative instance is pushing a new `NetworkTransformState` to non-authoritative instances. This can be used to better determine the precise values updated to non-authoritative instances for prediction related tasks.
+
+`NetworkTransform.OnNetworkTransformStateUpdated`: This virtual method is invoked when the non-authoritative instance is receiving a pushed `NetworkTransformState` update from the authoritative instance. This can be used to better determine the precise values updated to non-authoritative instances for prediction related tasks.
+
+`NetworkTransform.Awake`: This method has been made virtual in order to provide you with the ability to do any custom initialization. If you override this method, you are required to invoke `base.Awake()` (recommended invoking it first).
+
+`NetworkTransform.OnInitialize`: This virtual method is invoked when the associated NetworkObject is first spawned and when ownership changes.
+
+`NetworkTransform.Update`: This method has been made virtual in order to provide you with the ability to handle any customizations to a derived `NetworkTransform` class. If you override this method, it is required that all non-authoritative instances invoke `base.Update()` but not required for authoritative instances.
diff --git a/versioned_docs/version-2.0.0/installation/installation.md b/versioned_docs/version-2.0.0/installation/installation.md
new file mode 100644
index 000000000..769b2b271
--- /dev/null
+++ b/versioned_docs/version-2.0.0/installation/installation.md
@@ -0,0 +1,55 @@
+---
+id: install
+title: Install Netcode for GameObjects
+description: How to install Unity Netcode for GameObjects.
+---
+
+Follow the instructions on this page to set up Netcode for GameObjects in your Unity project.
+
+## Prerequisites
+
+Before you begin, you need the following:
+
+- An active Unity account with a valid license.
+- A supported version of Unity. Check [Netcode for GameObjects' requirements](#netcode-installation-requirements) for the specific version details.
+- An existing Unity project. If you're new to Unity, you can refer to the [get started](../tutorials/get-started-with-ngo.md) section for guidance.
+
+### Compatibility
+
+- Unity Editor version 2021.3 or later
+- Mono and IL2CPP [scripting backends](https://docs.unity3d.com/Manual/scripting-backends.html)
+
+### Supported platforms
+
+- Windows, MacOS, and Linux
+- iOS and Android
+- XR platforms on Windows, Android, and iOS
+- Most [**closed platforms**](https://unity.com/platform-installation), such as consoles. Contact the [development team](https://discord.com/channels/449263083769036810/563033158480691211) for more information about specific closed platforms.
+- WebGL (requires Netcode for GameObjects 1.2.0+ and [Unity Transport](https://docs-multiplayer.unity3d.com/transport/current/about/) 2.0.0+)
+
+:::note
+When working with closed platforms like consoles (PlayStation, Xbox, Nintendo Switch), there may be specific policies and considerations. Refer to your console's documentation for more information.
+:::
+
+## Install Netcode for GameObjects with the Package Manager
+
+1. From the Unity Editor, select **Window** > **Package Manager**.
+1. From the Package Manager, select **Add** ![add symbol](/img/add.png) > **Add package by name…**
+1. Type (or copy and paste) `com.unity.netcode.gameobjects` into the package name field, then select **Add**.
+
+### For Unity Editor versions 2020.3 LTS or earlier
+
+1. From the Unity Editor, select **Window** > **Package Manager**.
+1. From the Package Manager, select **Add** ![add symbol](/img/add.png) > **Add package by git URL…**
+1. Type (or copy and paste) `https://github.com/Unity-Technologies/com.unity.netcode.gameobjects` into the git URL field, then select **Add**.
+
+## Next Steps
+
+After installing Netcode for GameObjects, see the following content to continue your journey:
+
+* Use the [Get started with Netcode for GameObjects tutorial](../tutorials/get-started-with-ngo.md) to create a project, test your installation, and learn how to use the basic features of Netcode for GameObjects.
+* Check out the educational samples to further explore Netcode for GameObjects and its abilities:
+ * [Boss Room](../learn/bossroom/getting-started-boss-room.md)
+ * [2D Spaceshooter Bitesize sample](../learn/bitesize/bitesize-spaceshooter.md)
+ * [Invaders Bitesize sample](../learn/bitesize/bitesize-invaders.md)
+ * [Client-driven Bitesize sample](../learn/bitesize/bitesize-clientdriven.md)
diff --git a/versioned_docs/version-2.0.0/installation/migratingfromUNet.md b/versioned_docs/version-2.0.0/installation/migratingfromUNet.md
new file mode 100644
index 000000000..0896b3497
--- /dev/null
+++ b/versioned_docs/version-2.0.0/installation/migratingfromUNet.md
@@ -0,0 +1,676 @@
+---
+id: upgrade_from_UNet
+title: Migrate from UNet to Netcode for GameObjects
+---
+
+UNet is deprecated and no longer supported. Follow this guide to migrate from UNet to Netcode for GameObjects. If you need help, contact us in the [Unity Multiplayer Networking Discord](https://discord.gg/buMxnnPvTb).
+
+## Comparison between Netcode for GameObjects and UNet
+
+There are some differences between UNet and Netcode for GameObjects that you should be aware of as part of your migration:
+
+* Naming constraints may cause issues. UNet prefixed methods with `Cmd` or `Rpc`, whereas Netcode requires postfix. This may require either complicated multi-line regex to find and replace, or manual updates. For example, `CommandAttribute` has been replaced with `RpcAttribute(SendTo.Server)` and `ClientRPCAttribute` has been replaced with `RpcAttribute(SendTo.NotServer)` or `RpcAttribute(SendTo.ClientsAndHost)`, depending on whether you want the host client to receive the RPC.
+* Errors for RPC postfix naming patterns don't show in your IDE.
+* Client and server have separate representations in UNet. UNet has a number of callbacks that don't exist in Netcode for GameObjects.
+* Prefabs need to be added to the Prefab registration list in Netcode for GameObjects.
+* Matchmaking isn't available in Netcode for GameObjects at this time.
+
+## Back up your project
+
+It's strongly recommended that you back up your existing UNet project before migration. You can do one or both of the following:
+
+* Create a copy of your entire project folder.
+* Use source control software, like Git.
+
+## Install Netcode for GameObjects and restart Unity
+
+Follow the [installation guide](installation.md) to install Netcode for GameObjects.
+
+Installing Netcode for GameObjects also installs some other packages such as [Unity Transport](https://docs.unity3d.com/Packages/com.unity.transport@latest/), [Unity Collections](https://docs.unity3d.com/Packages/com.unity.collections@latest/), and [Unity Burst](https://docs.unity3d.com/Packages/com.unity.burst@latest/).
+
+## RPC Invoking
+
+Invoking an RPC works the same way as in UNet. Just call the function and it will send an RPC.
+
+
+
+## Replace NetworkIdentity with NetworkObject
+
+UNet's `NetworkIdentity` is called NetworkObject in Netcode for GameObjects and works in a similar way.
+
+## Replace UNet NetworkTransform with Netcode NetworkTransform
+
+UNet's `NetworkTransform` is also called `NetworkTransform` in Netcode for GameObjects and works in a similar way.
+
+`NetworkTransform` doesn't have full feature parity with UNET's `NetworkTransform`. It lacks features like position synchronizing for rigid bodies.
+
+## Replace UNet NetworkAnimator with Netcode NetworkAnimator
+
+Replace UNet's `NetworkAnimator` with Netcode for GameObjects' `NetworkAnimator` component everywhere in your project.
+
+## Update NetworkBehaviour
+
+Replace UNet `NetworkBehaviour` with Netcode for GameObjects' `NetworkBehaviour` everywhere in your project.
+
+
+
+
+
+```csharp
+public class MyUnetClass : NetworkBehaviour
+{
+ [SyncVar]
+ public float MySyncFloat;
+ public void Start()
+ {
+ if (isClient)
+ {
+ CmdExample(10f);
+ }
+ else if (isServer)
+ {
+ RpcExample(10f);
+ }
+ }
+ [Command]
+ public void CmdExample(float x)
+ {
+ Debug.Log(“Runs on server”);
+ }
+ [ClientRpc]
+ public void RpcExample(float x)
+ {
+ Debug.Log(“Runs on clients”);
+ }
+}
+```
+
+
+
+
+```csharp
+public class MyNetcodeExample : NetworkBehaviour
+{
+ public NetworkVariable MyNetworkVariable = new NetworkVariable();
+ public override void OnNetworkSpawn()
+ {
+ ExampleClientRpc(10f);
+ ExampleServerRpc(10f);
+ }
+ [Rpc(SendTo.Server)]
+ public void ExampleServerRpc(float x)
+ {
+ Debug.Log(“Runs on server”);
+ }
+ [Rpc(SendTo.ClientsAndHost)]
+ public void ExampleClientRpc(float x)
+ {
+ Debug.Log(“Runs on clients”);
+ }
+}
+```
+
+
+
+
+See [NetworkBehaviour](../basics/networkbehaviour.md) for more information.
+
+## Replace SyncVar
+
+Replace `SyncVar` with `NetworkVariable` everywhere in your project.
+
+To achieve equivalent functionality to `SyncVar`, hooks in Netcode for GameObjects subscribe a function to the `OnValueChanged` callback of the `NetworkVariable`. A notable difference between UNet hooks and Netcode for GameObjects' `OnValueChanged` callback is that Netcode for GameObjects gives you both the old and the newly changed value, while UNet only provides you with the old value. With UNet, you also had to manually assign the value of the `SyncVar`.
+
+
+
+
+
+```csharp
+public class SpaceShip : NetworkBehaviour
+{
+ [SyncVar]
+ public string PlayerName;
+
+
+ [SyncVar(hook = "OnChangeHealth"))]
+ public int Health = 42;
+
+ void OnChangeHealth(int newHealth){
+ Health = newHealth; //This is no longer necessary in Netcode.
+ Debug.Log($"My new health is {newHealth}.");
+ }
+}
+```
+
+
+
+
+```csharp
+// Don't forget to initialize NetworkVariable with a value.
+public NetworkVariable PlayerName = new NetworkVariable();
+
+public NetworkVariable Health = new NetworkVariable(42);
+
+// This how you update the value of a NetworkVariable, you can also use .Value to access the current value of a NetworkVariable.
+void MyUpdate()
+{
+ Health.Value += 30;
+}
+
+
+void Awake()
+{
+ // Call this is in Awake or Start to subscribe to changes of the NetworkVariable.
+ Health.OnValueChanged += OnChangeHealth;
+}
+
+void OnChangeHealth(int oldHealth, int newHealth){
+ //There is no need anymore to manually assign the value of the variable here with Netcode. This is done automatically by Netcode for you.
+ Debug.Log($"My new health is {newHealth}. Before my health was {oldHealth}");
+}
+```
+
+
+
+
+Replace all postfix increment and decrement usages of SyncVar in your project. Netcode's `NetworkVariable.Value` exposes a value type that's why postfix increment/decrement isn't supported.
+
+
+
+
+
+```csharp
+
+public int Health = 42;
+
+public void Update(){
+ Health++;
+}
+
+
+```
+
+
+
+
+```csharp
+
+public NetworkVariable Health = new NetworkVariable(42);
+
+public void Update(){
+ Health.Value = Health.Value + 1;
+}
+```
+
+
+
+
+See [NetworkVariable](../basics/networkvariable.md) for more information.
+
+
+## Replace `SyncList` with `NetworkList`
+
+Replace `SyncList` with `NetworkList` everywhere in your project. `NetworkList` has an `OnListChanged` event which is similar to UNet's `Callback`.
+
+
+
+
+
+```csharp
+public SyncListInt m_ints = new SyncListInt();
+
+private void OnIntChanged(SyncListInt.Operation op, int index)
+{
+ Debug.Log("list changed " + op);
+}
+
+
+public override void OnStartClient()
+{
+ m_ints.Callback = OnIntChanged;
+}
+```
+
+
+
+```csharp
+NetworkList m_ints = new NetworkList();
+
+// Call this is in Awake or Start to subscribe to changes of the NetworkList.
+void ListenChanges()
+{
+ m_ints.OnListChanged += OnIntChanged;
+}
+
+// The NetworkListEvent has information about the operation and index of the change.
+void OnIntChanged(NetworkListEvent changeEvent)
+{
+
+}
+```
+
+
+
+
+
+## Replace Command/ClientRPC
+
+UNet's `Command/ClientRPC` is replaced with `Server/ClientRpc` in Netcode for GameObjects, which works in a similar way.
+
+
+
+
+
+```csharp
+ [Command]
+ public void CmdExample(float x)
+ {
+ Debug.Log(“Runs on server”);
+ }
+ [ClientRpc]
+ public void RpcExample(float x)
+ {
+ Debug.Log(“Runs on clients”);
+ }
+```
+
+
+
+
+```csharp
+ [Rpc(SendTo.Server)]
+ public void ExampleServerRpc(float x)
+ {
+ Debug.Log(“Runs on server”);
+ }
+ [Rpc(SendTo.ClientsAndHost)]
+ public void ExampleClientRpc(float x)
+ {
+ Debug.Log(“Runs on clients”);
+ }
+```
+
+
+
+:::note
+In Netcode for GameObjects, RPC function names must end with an `Rpc` suffix.
+:::
+
+See [Messaging System](../advanced-topics/messaging-system.md) for more information.
+
+## Replace `OnServerAddPlayer`
+
+Replace `OnServerAddPlayer` with `ConnectionApproval` everywhere in your project.
+
+
+
+
+
+```csharp
+using UnityEngine;
+using UnityEngine.Networking;
+using UnityEngine.Networking.NetworkSystem;
+
+class MyManager : NetworkManager
+{
+ public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader)
+ {
+ if (extraMessageReader != null)
+ {
+ var s = extraMessageReader.ReadMessage();
+ Debug.Log("my name is " + s.value);
+ }
+ OnServerAddPlayer(conn, playerControllerId, extraMessageReader);
+ }
+}
+```
+
+
+
+
+
+Server-only example:
+
+```csharp
+using Unity.Netcode;
+
+private void Setup()
+{
+ NetworkManager.Singleton.ConnectionApprovalCallback += ApprovalCheck;
+ NetworkManager.Singleton.StartHost();
+}
+
+private void ApprovalCheck(byte[] connectionData, ulong clientId, NetworkManager.ConnectionApprovedDelegate callback)
+{
+ //Your logic here
+ bool approve = true;
+ bool createPlayerObject = true;
+
+ // The Prefab hash. Use null to use the default player prefab
+ // If using this hash, replace "MyPrefabHashGenerator" with the name of a Prefab added to the NetworkPrefabs field of your NetworkManager object in the scene
+ ulong? prefabHash = NetworkpawnManager.GetPrefabHashFromGenerator("MyPrefabHashGenerator");
+
+ //If approve is true, the connection gets added. If it's false. The client gets disconnected
+ callback(createPlayerObject, prefabHash, approve, positionToSpawnAt, rotationToSpawnWith);
+}
+```
+
+
+
+
+See [Connection Approval](../basics/connection-approval.md) for more information.
+
+## Replace NetworkServer.Spawn with NetworkObject.Spawn
+
+Replace `NetworkServer.Spawn` with `NetworkObject.Spawn` everywhere in your project.
+
+
+
+
+
+```csharp
+
+using UnityEngine;
+using UnityEngine.Networking;
+
+public class Example : NetworkBehaviour
+{
+ //Assign the Prefab in the Inspector
+ public GameObject m_MyGameObject;
+ GameObject m_MyInstantiated;
+
+ void Start()
+ {
+ //Instantiate the prefab
+ m_MyInstantiated = Instantiate(m_MyGameObject);
+ //Spawn the GameObject you assign in the Inspector
+ NetworkServer.Spawn(m_MyInstantiated);
+ }
+}
+
+```
+
+
+
+
+```csharp
+GameObject go = Instantiate(myPrefab, Vector3.zero, Quaternion.identity);
+go.GetComponent().Spawn();
+```
+
+
+
+
+
+See [Object Spawning](../basics/object-spawning.md) for more information.
+
+## Custom Spawn Handlers
+
+Netcode has `Custom Spawn Handlers` to replace UNet's `Custom Spawn Functions`. See [Object Pooling](../advanced-topics/object-pooling) for more information.
+
+## Replace `NetworkContextProperties`
+
+Netcode has `IsLocalPlayer`, `IsClient`, `IsServer`, and `IsHost` to replace UNet's `isLocalPlayer`, `isClient`, and `isServer`. In Netcode for GameObjects, each object can be owned by a specific peer. This can be checked with `IsOwner`, which is similar to UNet's `hasAuthority`.
+
+## `NetworkProximityChecker`, `OnCheckObserver` and network visibility
+
+Netcode for GameObjects doesn't have direct equivalents for the following UNet components and functions:
+
+* `NetworkPromimityChecker` component. Network visibility for clients works similar as in UNet.
+* `ObjectHide` message. In Netcode for GameObjects, networked objects on the host are always visible.
+* `OnSetLocalVisibility` function. A manual network proximity implementation with the `OnCheckObserver` can be ported to Netcode for GameObjects by using `NetworkObject.CheckObjectVisibility`.
+* `OnRebuildObservers` isn't needed for the Netcode for GameObjects' visibility system.
+
+
+
+
+
+```csharp
+public override bool OnCheckObserver(NetworkConnection conn)
+{
+ return IsvisibleToPlayer(getComponent(), coon);
+}
+
+public bool IsVisibleToPlayer(NetworkIdentity identity, NetworkConnection conn){
+ // Any promimity function.
+ return true;
+}
+```
+
+
+
+
+
+
+```csharp
+public void Start(){
+ NetworkObject.CheckObjectVisibility = ((clientId) => {
+ return IsVisibleToPlayer(NetworkObject, NetworkManager.Singleton.ConnectedClients[clientId]);
+ });
+}
+
+public bool IsVisibleToPlayer(NetworkObject networkObject, NetworkClient client){
+ // Any promimity function.
+ return true;
+}
+```
+
+
+
+
+See [Object Visbility](../basics/object-visibility.md) to learn more about Netcodes network visiblity check.
+
+## Update scene management
+
+In Netcode for Gameobjects, scene management isn't done using the `NetworkManager` like in UNet. The `NetworkSceneManager` provides equivalent functionality for switching scenes.
+
+
+
+
+
+```csharp
+public void ChangeScene()
+{
+ MyNetworkManager.ServerChangeScene("MyNewScene");
+}
+```
+
+
+
+
+```csharp
+public void ChangeScene()
+{
+ NetworkSceneManager.LoadScene("MyNewScene", LoadSceneMode.Single);
+}
+```
+
+
+
+
+## Update `ClientAttribute/ClientCallbackAttribute` and `ServerAttribute/ServerCallbackAttribute`
+
+Netcode for GameObjects currently doesn't offer a replacement for marking a function with an attribute so that it only runs on the server or the client. You can manually return out of the function instead.
+
+
+
+
+
+```csharp
+[Client]
+public void MyClientOnlyFunction()
+{
+ Debug.Log("I'm a client!");
+}
+```
+
+
+
+
+
+
+```csharp
+public void MyClientOnlyFunction()
+{
+ if (!IsClient) { return; }
+
+ Debug.Log("I'm a client!");
+}
+```
+
+
+
+
+
+## Replace `SyncEvent` with an RPC event
+
+Netcode for GameObjects doesn't provide an equivalent for `SyncEvent`. To port `SyncEvent` code from UNet to Netcode for GameObjects, send an RPC to invoke the event on the other side.
+
+
+
+
+
+```csharp
+public class DamageClass : NetworkBehaviour
+{
+ public delegate void TakeDamageDelegate(int amount);
+
+ [SyncEvent]
+ public event TakeDamageDelegate EventTakeDamage;
+
+ [Command]
+ public void CmdTakeDamage(int val)
+ {
+ EventTakeDamage(val);
+ }
+}
+```
+
+
+
+
+
+```csharp
+public class DamageClass : NetworkBehaviour
+{
+ public delegate void TakeDamageDelegate(int amount);
+
+ public event TakeDamageDelegate EventTakeDamage;
+
+ [Rpc(SendTo.Server)]
+ public void TakeDamageServerRpc(int val)
+ {
+ EventTakeDamage(val);
+ OnTakeDamageClientRpc(val);
+ }
+
+ [Rpc(SendTo.ClientsAndHost)]
+ public void OnTakeDamageClientRpc(int val){
+ EventTakeDamage(val);
+ }
+}
+```
+
+
+
+
+## Network Discovery
+
+Netcode for GameObjects doesn't provide Network Discovery. The Contributions repository provides an example implementation for [NetworkDiscovery](https://github.com/Unity-Technologies/multiplayer-community-contributions/tree/main/com.community.netcode.extensions/Runtime/NetworkDiscovery).
+
+## Next steps
+
+After migrating to the Netcode for GameObjects package, you can review the following for what to do next:
+
+* Consider using the [Hello World](../tutorials/helloworld.md) and [Golden Path series](../tutorials/goldenpath_series/gp_intro.md) to learn some basics of Netcode for GameObjects.
+* Explore the educational samples content for a deeper exploration into Netcode for GameObjects:
+ * [Boss Room](../learn/bossroom/getting-started-boss-room.md)
+ * [2D Spaceshooter Bitesize sample](../learn/bitesize/bitesize-spaceshooter.md)
+ * [Invaders Bitesize sample](../learn/bitesize/bitesize-invaders.md)
+ * [Client-Driven Bitesize sample](../learn/bitesize/bitesize-clientdriven.md)
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+import Link from '@docusaurus/Link';
diff --git a/versioned_docs/version-2.0.0/installation/migratingfrommlapi.md b/versioned_docs/version-2.0.0/installation/migratingfrommlapi.md
new file mode 100644
index 000000000..f6efc695e
--- /dev/null
+++ b/versioned_docs/version-2.0.0/installation/migratingfrommlapi.md
@@ -0,0 +1,159 @@
+---
+id: upgrade_from_mlapi
+title: Migrate from MLAPI to Netcode for GameObjects
+description: How to upgrade your current MLAPI installation to the Netcode for GameObjects.
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+MLAPI is deprecated and no longer supported. Follow this guide to migrate from MLAPI to Netcode for GameObjects.
+
+## Back up your MLAPI project
+
+The transition from MLAPI to Netcode for GameObjects is significant and can cause issues with your current project. It's strongly recommended that you back up your existing MLAPI project before migration. You can do one or both of the following:
+
+* Create a copy of your entire project folder.
+* Use source control software, like Git.
+
+## Add the MLAPI Patcher to your MLAPI project
+
+Manually transitioning from MLAPI to Netcode for GameObjects will break all the component references in your project. You can use the MLAPI Patcher to automate the process and avoid breaking changes.
+
+1. Add the Netcode Patcher to your project. Open the **Package Manager** window in the Unity Editor and select **Add package from Git URL..**. Use the following URL: `https://github.com/Unity-Technologies/multiplayer-community-contributions/tree/release-0.1.0/com.unity.multiplayer.mlapi-patcher`
+
+## Install the Netcode for GameObjects package
+
+Follow the [installation guide](installation.md) to install Netcode for GameObjects. After installing the package, you'll see error messages in the console, which is expected because your project now has MLAPI and Netcode for GameObjects at the same time. Don't uninstall MLAPI yet - it's still required for the next step.
+
+Installing Netcode for GameObjects also installs some other packages such as [Unity Transport](https://docs.unity3d.com/Packages/com.unity.transport@latest/), [Unity Collections](https://docs.unity3d.com/Packages/com.unity.collections@latest/), and [Unity Burst](https://docs.unity3d.com/Packages/com.unity.burst@latest/).
+
+The Burst package requires an Editor restart. After restarting, the Editor will ask you to enter safe mode at the next boot, which is normal behavior since your network code isn't compiling anymore.
+
+## Update script references
+
+You can use the MLAPI Patcher to automate updating your script references. Open the MLAPI Patcher by selecting **Window** > **Netcode Patcher**.
+
+The Patcher will ask whether you're using the *Installer* version of MLAPI or the *Source* version. If you aren't sure which version of MLAPI you're using, you can check whether you have the `Assets/MLAPI/Lib/MLAPI.dll` file in your project. If you do, then you're using the *Installer* version of MLAPI. If you don't, then you're using the *Source* version of MLAPI.
+
+In the Patcher window, select **Installer** or **Source** button:
+
+
+
+
+
+1. Select **Installer**.
+1. Select **Update Script References**.
+
+
+
+
+1. Select **Source**.
+1. The window prompts you to link a MLAPI source directory.
+1. Take the directory in your project containing the MLAPI source and drop it into the field.
+1. Select **Update Script References**.
+
+
+
+
+After you complete the **Update Script References** process of the Patcher, the components in your project should have been updated to their new names.
+
+There is also a **Replace Type Names** button in the Patcher window. This step is optional. It automatically renames old type names in your scripts to the API changes made in Netcode for GameObjects, saving you some time to manually rename it. It performs a simple global replace of some of the type names. You may want to manually do this process instead if you want more control over changes.
+
+## Remove old MLAPI versions
+
+Remove all the folders containing the existing non-package version of MLAPI from your project. Usually this means removing the `Assets/MLAPI` and `Assets/Editor/MLAPI` folders from the project.
+
+## Migrate your code to the new Netcode for GameObjects APIs
+
+:::info
+Migrating your code is a long and manual process. If you run into difficulties, please join our [Discord](https://discord.gg/buMxnnPvTb) and we will support you.
+:::
+
+As few breaking changes as possible were introduced as part of the transition from MLAPI to Netcode for GameObjects. However, a successful compilation still requires some changes.
+
+### `NetworkVariable` changes
+
+The `NetworkVariable` type is now generic only and the type specified in the generic needs to be a value type.
+
+1. Change your `NetworkVariable*` types into their generic counterpart. For example, `NetworkVariableInt` becomes `NetworkVariable`, and `NetworkVariableFloat` becomes `NetworkVariable`.
+1. Some of your types won't match the new type requirements for `NetworkVariable`. If your type is a string, you can use `FixedString32Bytes` instead. Note that this type doesn't allow you to change the size of the string. For custom structs that only contain value types, you can implement `INetworkSerializable`, and it will work.
+1. For the other types, you'll need to create your own `NetworkVariable`. To achieve that, create a new class, inherit from `NetworkVariableBase`, and implement all the abstract members. If you already had custom `NetworkVariable`, read and write functions now use `FastBuffer` to read or write from and to the stream.
+
+### Scene management changes
+
+Scene management is now under the `NetworkManager` singleton. It can be accessed by:
+
+```csharp
+var sceneManager = NetworkManager.Singleton.SceneManager;
+```
+
+There is now only one scene event instead of many: `OnSceneEvent`. You can subscribe to it and get scene events information from the `SceneEvent` class. In this class, you'll find the `SceneEventType`, which will give you precisions on what type of event is coming from the SceneManager.
+
+Finally, the primary function to switch between scenes has changed to match the Unity SceneManager. Instead of `SwitchScene`, you now call `LoadScene` with two parameters: the scene name and the `LoadSceneMode`, which is the standard way to load a scene in Unity.
+
+### `NetworkBehavior` changes
+
+There are two main changes in `NetworkBehavior`:
+
+* `NetworkStart` method becomes `OnNetworkSpawn`, and `OnNetworkDespawn` was introduced to keep things symmetrical.
+* `OnDestroy` now needs to be overridden, since `NetworkBehavior` already uses it.
+
+## Changes in behavior
+
+Behavior changes are as minimal as possible, but there are two changes which are likely to cause errors in existing scripts:
+
+* `NetworkManager` now performs connection shut down when the application quits. If you were doing connection shutdown manually, you'll up with an error about disconnecting twice.
+* The library now fires all the `OnValueChanged` events from the `NetworkVariable` **after** the `OnNetworkSpawn` (previously known as `NetworkStart`) method has returned. You'll need to refactor any scripts depending on this order accordingly.
+
+### Upgrade RPCs
+
+The way RPCs are invoked has changed with this version of Netcode for GameObjects. Please read the [documentation about RPCs](../advanced-topics/messaging-system.md) and replace your existing RPCs with the new system.
+
+### Serialization
+
+The old `INetworkSerializable` interface has been replaced with a new `INetworkSerializable` interface. See [`INetworkSerializable`](../advanced-topics/serialization/inetworkserializable.md).
+
+The page also includes information on nested serial types.
+
+### SyncVars
+
+SyncVars have been removed in Netcode for GameObjects. Convert your existing SyncVars into [NetworkVariables](../basics/networkvariable).
+
+## Remove the Patcher package
+
+After you're done upgrading your project, you can remove the MLAPI Patcher package from your project in the Unity Package Manager.
+
+## Troubleshooting
+
+**Error: The type or namespace name 'MLAPI' can't be found**
+
+This error occurs if your project uses assembly definition (`.asmdef`) files. After switching to the package version, your assembly definition files need to reference `com.unity.multiplayer.mlapi.runtime`.
+
+**Error: The type or namespace name 'NetworkedBehaviour' can't be found**
+
+If you get an error message like this in the console, it's likely because your code has outdated APIs. Open the script indicated in the error message and update all APIs to the new names.
+
+**Error: SerializedObjectNotCreatableException: Object at index 0 is null**
+
+If this appears when you enter Play Mode or save a scene, close the Unity Editor and open it again and this should be gone.
+
+## Next steps
+
+After migrating to the Netcode for GameObjects package, you can review the following for what to do next:
+
+* Consider using the [Hello World](../tutorials/helloworld.md) and [Golden Path series](../tutorials/goldenpath_series/gp_intro.md) to learn some basics of Netcode for GameObjects.
+* Explore the educational samples content for a deeper exploration into Netcode for GameObjects:
+ * [Boss Room](../learn/bossroom/getting-started-boss-room.md)
+ * [2D Spaceshooter Bitesize sample](../learn/bitesize/bitesize-spaceshooter.md)
+ * [Invaders Bitesize sample](../learn/bitesize/bitesize-invaders.md)
+ * [Client-Driven Bitesize sample](../learn/bitesize/bitesize-clientdriven.md)
+
+import useBaseUrl from '@docusaurus/useBaseUrl';
+import Link from '@docusaurus/Link';
diff --git a/versioned_docs/version-2.0.0/learn/bitesize/bitesize-clientdriven.md b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-clientdriven.md
new file mode 100644
index 000000000..2c6af7826
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-clientdriven.md
@@ -0,0 +1,68 @@
+---
+id: bitesize-clientdriven
+title: ClientDriven sample
+description: Learn more about Client driven movements, networked physics, spawning vs statically placed objects, object reparenting
+---
+
+## Client Driven Movements
+Making movements feel responsive while staying consistent over multiple game executables, each with their own timelines, is a challenge for many networked games.
+
+## TLDR:
+
+- Use [ClientNetworkTransform](../../components/networktransform.md#clientnetworktransform) to sync client authoritative transform updates to the server and other clients.
+- Make sure ownership is set properly on that NetworkObject to be able to move it.
+- Since your clients live on different timelines (one per player), you have to be careful about who takes decisions and keep some of those decisions centralized on the server.
+- DON'T FORGET to test with latency, as your game will behave differently depending on whether client or server make decisions.
+
+## Sample:
+
+ClientDriven's aim is to create a quick sample to show responsive character movements that don't feel sluggish, even under bad network conditions.
+It uses the ClientNetworkTransform component and moves your own player's position client side, [client authoritatively](../dealing-with-latency.md#allow-low-impact-client-authority). Movement is leveraged through the use of Unity's Starter Assets, the [Third Person Character Controller](https://assetstore.unity.com/packages/essentials/starter-assets-third-person-character-controller-196526).
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/ClientDriven/Assets/StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs#L155-L162
+```
+
+### Client side object detection for pickup with server side pickup validation
+Ingredients in ClientDriven are owned by the server, since they're [shared objects](../dealing-with-latency.md#issue-world-consistency). This means if a player tries to grab an object while that object is moving, a server side range detection would sometimes fail, even though it should have succeeded (since ingredients are replicated with some lag, so the player would try to grab ingredients that are a few milliseconds behind).
+To make sure this doesn't happen, the object detection done to grab an ingredient is also done client side.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/ClientDriven/Assets/Scripts/ClientPlayerMove.cs#L64-L94
+```
+
+But the pickup itself is done server side.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/ClientDriven/Assets/Scripts/ServerPlayerMove.cs#L46-L82
+```
+
+Notice how we're checking whether that object can be picked up or not (since another player can have picked it up at the same time, creating a conflict).
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/ClientDriven/Assets/Scripts/ServerPlayerMove.cs#L50-L58
+```
+If the object is already picked up, we're not doing anything. Your client side animations should take this into account and cancel any animations "carrying" something.
+
+### Server side player spawn points
+In this sample, our spawn points list is server side (to have a single source of truth).
+ClientNetworkTransforms can be updated by owners only, which means the server can't update the player's position directly.
+This means OnNetworkSpawn, the server will need to assign a position to the player using a ClientRPC.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/ClientDriven/Assets/Scripts/ServerPlayerMove.cs#L24-L44
+```
+
+## Server physics with client driven movements (interactions on different timelines)
+All the ingredients can be bumped against by players. However, since ingredients are server driven, bumping against them with client driven movements can cause desync issues.
+This sample uses NetworkRigidbody for ingredients, which sets Kinematic = true, making them immovable client side. This way, only server side movements (from the replicated player movements) will move the ingredients. Two players bumping the same ingredient will still only have one single result, calculated server side, with no risk of desync.
+
+## Reparenting
+
+This sample uses Netcode's automatic reparenting synchronization. By setting a NetworkObject's parent to another NetworkObject, that reparenting will be synced to connected clients.
+Note that we're also setting InLocalSpace while reparenting, to make sure the client side ingredient will be tracked the same way as the server side one (else the ingredient would be carried with latency, making it appear "dragging along behind you").
+An ownership change can also have been used here, but the client would have needed to ask the server for that change first.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/ClientDriven/Assets/Scripts/ServerPlayerMove.cs#L46-L61
+```
diff --git a/versioned_docs/version-2.0.0/learn/bitesize/bitesize-dynamicprefabs.md b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-dynamicprefabs.md
new file mode 100644
index 000000000..df9768611
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-dynamicprefabs.md
@@ -0,0 +1,307 @@
+---
+id: bitesize-dynamicPrefabs
+title: Dynamic Prefabs sample
+description: Learn more about the dynamic Prefab system, which allows you to add new spawnable Prefabs at runtime.
+---
+
+# Dynamic Addressables Network Prefabs Sample
+
+The [DynamicAddressablesNetworkPrefabs Sample](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/tree/main/Basic/DynamicAddressablesNetworkPrefabs) showcases the available ways you can use dynamic Prefabs to dynamically load network Prefabs at runtime, either pre-connection or post-connection. Doing so allows you to add new spawnable NetworkObject Prefabs to Netcode for GameObjects.
+
+This sample covers a variety of possible ways you can use dynamically loaded network Prefabs:
+
+- **Pre-loading**: Add dynamic Prefabs to all peers before starting the connection.
+- **Connection approval**: Apply server-side validation to late-joining clients after loading dynamic Prefabs.
+- **Server-authoritative pre-load all Prefabs asynchronously**: Simplify server spawn management by having the server send a load request to all clients to load a set of network Prefabs.
+- **Server-authoritative try spawn synchronously**: Ensure all connected clients individually load a network Prefab before spawning it on the server.
+- **Server-authoritative network visibility spawning**: Spawn a network Prefab server-side as soon as it has loaded it locally, and only change the visibility of the spawned NetworkObject when each client loads the Prefab load.
+
+There's also the **APIPlayground**, which serves as an API playground that implements all post-connection uses together.
+
+:::note
+**Note**: This sample leverages [Addressables](https://docs.unity3d.com/Packages/com.unity.addressables@1.21/manual/index.html) to load dynamic Prefabs.
+:::
+
+### Scene 00_Preloading Dynamic Prefabs
+
+The `00_Preloading Dynamic Prefabs` scene is the simplest implementation of a dynamic Prefab. It instructs all game instances to load a network Prefab (it can be just one, it can also be a set of network Prefabs) and inject them to a NetworkManager's NetworkPrefabs list before starting the server. What's important is that it doesn't matter where the Prefab comes from. It can be a simple Prefab or it can be an Addressable - it's all the same.
+
+This is the lesser intrusive option for your development, as you don't have any extra spawning and Addressables management to perform later in your game.
+
+Here, the sample serializes the AssetReferenceGameObject to this class, but ideally you want to authenticate players when your game starts up and have them fetch network Prefabs from services such as UGS (see [Remote Config](https://docs.unity.com/remote-config)). You should also note that this is a technique that can serve to decrease the install size of your application, since you'd be streaming in networked game assets dynamically.
+
+The entirety of this use-case is performed pre-connection time, and all game instances would execute this bit of code inside the Preloading.cs `Start()` method:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/00_Preloading/Preloading.cs#L27-L31
+```
+
+The logic of this method invoked on `Start()` is defined below:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/00_Preloading/Preloading.cs#L33-L56
+```
+
+First, the sample waits for the dynamic Prefab asset to load from its address and into memory. After the Prefab is ready, the game instance adds it to NetworkManger's list of NetworkPrefabs, then it marks the NetworkObject as a NetworkManager's PlayerPrefab.
+
+Lastly, the sample forces the NetworkManager to check for matching [NetworkConfig](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/ngo/1.2.0/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkConfig.cs)s between a client and the server by setting ForceSamePrefabs to true. If the server detects a mismatch between the server's and client's NetworkManager's NetworkPrefabs list when a client is trying to connect, it denies the connection automatically.
+
+### Scene 01_Connection Approval Required For Late Joining
+
+The `01_Connection Approval Required For Late Joining` scene uses a class that walks through what a server needs to approve a client when dynamically loading network Prefabs. This is another simple example; it's just the implementation of the connection approval callback, which is an **optional** feature from Netcode for GameObjects. To enable it, enable the **Connection Approval** option on the NetworkManager in your scene. This example enables connection approval functionality to support late-joining clients, and it works best in combination with the techniques from the other example scenes. The other example scenes don't allow for reconciliation after the server loads a Prefab dynamically, except for scene `05_API Playground Showcasing All Post-Connection Uses`, where all post-connection use-cases are integrated in one scene.
+
+To begin, this section walks you through what the client sends to the server when trying to connect. This is done inside of [ClientConnectingState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/Shared/ConnectionStates/ClientConnectingState.cs)' StartClient() method:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/Shared/ConnectionStates/ClientConnectingState.cs#L25-L32
+```
+
+Before invoking `NetworkManager.StartClient()`, the client defines the `ConnectionData` to send along with the connection request, gathered from [DynamicPrefabLoadingUtilities.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/Shared/DynamicPrefabLoadingUtilities.cs):
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/Shared/DynamicPrefabLoadingUtilities.cs#L81-L89
+```
+
+For simplicity's sake, this method generates a hash that uniquely describes the dynamic Prefabs that a client has loaded. This hash is what the server uses as validation to decide whether a client has approval for a connection.
+
+Next, take a look at how the server handles incoming `ConnectionData`. The sample listens for the NetworkManager's ConnectionApprovalCallback and defines the behavior to invoke inside of [ConnectionApproval.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/tree/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/01_Connection%20Approval). This is done on `Start()`:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/01_Connection%20Approval/ConnectionApproval.cs#L30-L52
+```
+
+Unlike the earlier use-case, `ForceSamePrefab` is to false; this allows you to add NetworkObject Prefabs to a NetworkManager's NetworkPrefabs list after establishing a connection on both the server and clients. Before walking through what this class' connection approval callback looks like, it's worth noting here that the sample forces a mismatch of NetworkPrefabs between server and clients, because as soon as the server starts, it loads a dynamic Prefab and registers it to the server's NetworkPrefabs list:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/01_Connection%20Approval/ConnectionApproval.cs#L54-L69
+```
+
+This section walks you through the connection approval defined in this class in steps. First, its worth noting that the connection approval invokes on the host. As a result, you allow the host to establish a connection:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/01_Connection%20Approval/ConnectionApproval.cs#L85-L90
+```
+
+Next, a the sample introduces a few more validation steps. First, this sample only allows four connected clients. If the server detects any more connections past that limit, it denies the requesting client a connection. Secondly, if the `ConnectionData` is above a certain size threshold, it denies it outright.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/01_Connection%20Approval/ConnectionApproval.cs#L92-L105
+```
+
+A trivial approval for an incoming connection request occurs when the server hasn't yet loaded any dynamic Prefabs. Assuming the client hasn't injected any Prefabs outside of the `DynamicPrefabLoadingUtilities` system, the client is approved for a connection:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/01_Connection%20Approval/ConnectionApproval.cs#L107-L112
+```
+
+Another case for connection approval is when the requesting client's Prefab hash is identical to that of the server:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/01_Connection%20Approval/ConnectionApproval.cs#L114-L128
+```
+
+If the requesting client has a mismatching Prefab hash, it means that the client hasn't yet loaded the appropriate dynamic Prefabs. When this occurs, the sample leverages the NetworkManager's ConnectionApprovalResponse's `Reason` string field, and populates it with a payload containing the GUIDs of the dynamic Prefabs the client should load locally before re-attempting connection:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/01_Connection%20Approval/ConnectionApproval.cs#L140-L144
+```
+
+A client attempting to connect receives a callback from Netcode that it has been disconnected inside of `ClientConnectingState`:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/Shared/ConnectionStates/ClientConnectingState.cs#L39-L68
+```
+
+If the parsed DisconnectReason string is valid, and the parsed reason is of type `DisconnectReason.ClientNeedsToPreload`, the client will be instructed to load the Prefabs by their GUID. This is done inside of [ClientPreloadingState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/Shared/ConnectionStates/ClientPreloadingState.cs):
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/Shared/ConnectionStates/ClientPreloadingState.cs#L30-L37
+```
+
+After the client loads the necessary Prefabs, it once again transitions to the `ClientConnectingState`, and retries the connection to the server, sending along a new Prefab hash.
+
+:::note
+**Note**: This sample leveraged a state machine to handle connection management. A state machine isn't by any means necessary for connection approvals to work—it serves to compartmentalize connection logic per state, and to be a debug-friendly tool to step through connection steps.
+
+:::
+
+### Scene 02_Server Authoritative Load All Prefabs Asynchronously
+
+The `02_Server Authoritative Load All Prefabs Asynchronously` scene is a simple scenario where the server notifies all clients to pre-load a collection of network Prefabs. The server won't invoke a spawn in this scenario; instead, it incrementally loads each dynamic Prefab, one at a time.
+
+This technique might benefit a scenario where, after all clients connect, the host arrives at a point in the game where it expects that will need to load Prefabs soon. In such a case, the server instructs all clients to preemptively load those Prefabs. Later in the same game session, the server needs to perform a spawn, and can do so knowing all clients have loaded said dynamic Prefab (since it already did so preemptively). This allows for simple spawn management.
+
+This sample is different from the `00_Preloading Dynamic Prefabs` scene, in that it occurs after clients connect and join the game. It allows for more gameplay flexibility and loading different Prefabs based on where players are at in the game, for example.
+
+The logic that drives the behaviour for this use-case resides inside [ServerAuthoritativeLoadAllAsync.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/02_Server%20Authoritative%20Load%20All%20Async/ServerAuthoritativeLoadAllAsync.cs). Its Start() method is as follows:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/02_Server%20Authoritative%20Load%20All%20Async/ServerAuthoritativeLoadAllAsync.cs#L36-L59
+```
+
+Similarly to the last use-case, this use-case has `ConnectionApproval` set to `true` and `ForceSamePrefabs` set to `false`. The sample defines a trimmed-down `ConnectionApproval` callback inside of this class resembling that of the last use-case to allow for denying connections to clients that have mismatched NetworkPrefabs lists to that of the server. If `ConnectionApproval` is set to `false`, all incoming connection are automatically approved.
+
+The sample also binds a UI (user interface) button's pressed callback to a method inside this class. This method, shown below, iterates through the serialized list of `AssetReferenceGameObject`s, and generates a set of tasks to asynchronously load the Prefabs on every connected client (and the server).
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/02_Server%20Authoritative%20Load%20All%20Async/ServerAuthoritativeLoadAllAsync.cs#L136-L145
+```
+
+The task to load an Addressable individually is as follows:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/02_Server%20Authoritative%20Load%20All%20Async/ServerAuthoritativeLoadAllAsync.cs#L147-L189
+```
+
+First, the sample ensures this block of code only executes on the server. Next, a simple check verifies if the dynamic Prefab has already been loaded. If the dynamic Prefab is loaded, you can early return inside this method.
+
+Next, the server sends out a ClientRpc to every client, instructing them to load an Addressable and add it to their NetworkManager's NetworkPrefabs list. After sending out the ClientRpc, the server begins to asynchronously load the same Prefab. The ClientRpc looks like:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/02_Server%20Authoritative%20Load%20All%20Async/ServerAuthoritativeLoadAllAsync.cs#L191-L213
+```
+
+This operation should only run on clients. After the Prefab loads on the client, the client sends back an acknowledgement ServerRpc containing the hashcode of the loaded Prefab. The ServerRpc looks like:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/02_Server%20Authoritative%20Load%20All%20Async/ServerAuthoritativeLoadAllAsync.cs#L215-L242
+```
+
+The server records that the client has successfully loaded the dynamic Prefab. As hinted by the class name, this use-case only instructs clients to load a set of dynamic Prefabs and doesn't invoke a network spawn.
+
+### Scene 03_Server Authoritative Synchronous Dynamic Prefab Spawn
+
+The `03_Server Authoritative Synchronous Dynamic Prefab Spawn` scene is a dynamic Prefab loading scenario where the server instructs all clients to load a single network Prefab, and only invokes a spawn after all clients have finish loading the Prefab. The server initially sends a [ClientRpc](../../../docs/advanced-topics/message-system/clientrpc.md) to all clients, begins loading the Prefab on the server, awaits a acknowledgement of a load via a [ServerRpcs](../../../docs/advanced-topics/message-system/serverrpc.md) from each client, and only spawns the Prefab over the network after it receives an acknowledgement from every client, within a predetermined amount of time.
+
+This example implementation works best for scenarios where you want to guarantee the same world version across all connected clients. Because the server waits for all clients to finish loading the same dynamic Prefab, the spawn of said dynamic Prefab will be synchronous.
+
+The technique demonstrated in this sample works best for spawning game-changing gameplay elements, assuming you want all clients to be able to interact with said gameplay elements from the same point forward. For example, you don't want to have an enemy that's only visible (network-side or visually) to some clients and not others—you want to delay the spawning the enemy until all clients have dynamically loaded it and are able to see it before spawning it server-side.
+
+The logic for this use-case resides inside of [ServerAuthoritativeSynchronousSpawning.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/03_Server%20Authoritative%20Synchronous%20Spawning/ServerAuthoritativeSynchronousSpawning.cs). The Start() method of this class resembles that of the last use-case, however, the method invoked by the UI (user interface) is:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/03_Server%20Authoritative%20Synchronous%20Spawning/ServerAuthoritativeSynchronousSpawning.cs#L134-L149
+```
+
+The sample first validates that only the server executes this bit of code. Next, it grabs a `AssetReferenceGameObject` from the serialized list at random, and invokes an asynchronous task that tries to spawn this dynamic Prefab, positioned inside a random point of a circle:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/03_Server%20Authoritative%20Synchronous%20Spawning/ServerAuthoritativeSynchronousSpawning.cs#L151-L235
+```
+
+The sample checks if the dynamic Prefab is already loaded and if so, it can just spawn it directly:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/03_Server%20Authoritative%20Synchronous%20Spawning/ServerAuthoritativeSynchronousSpawning.cs#L166-L171
+```
+
+Next, the sample resets the variable to track the number of clients that have loaded a Prefab during this asynchronous operation, and the variable to track how long a spawn operation has taken. The server then instructs all clients to load the dynamic Prefab via a ClientRpc:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/03_Server%20Authoritative%20Synchronous%20Spawning/ServerAuthoritativeSynchronousSpawning.cs#L176-L177
+```
+
+The server now loads the dynamic Prefab. After successfully loading the dynamic Prefab, the server records the necessary number of acknowledgement ServerRpcs it needs to receive to guarantee that all clients have loaded the dynamic Prefab. The server then halts until that condition is met:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/03_Server%20Authoritative%20Synchronous%20Spawning/ServerAuthoritativeSynchronousSpawning.cs#L189-L203
+```
+
+If all clients have loaded the dynamic Prefab, and that condition is met within a predetermined amount of seconds, the server is free to instantiate and spawn a NetworkObject over the network. If this loading condition isn't met, the server doesn't instantiate nor spawn the loaded NetworkObject, and returns a failure for this task:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/03_Server%20Authoritative%20Synchronous%20Spawning/ServerAuthoritativeSynchronousSpawning.cs#L205-L208
+```
+
+The ClientRpc in this class is identical to that of the last use-case, but the ServerRpc is different since here is where the acknowledgement variable is incremented:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/03_Server%20Authoritative%20Synchronous%20Spawning/ServerAuthoritativeSynchronousSpawning.cs#L261-L290
+```
+
+### Scene 04_Server Authoritative Spawn Dynamic Prefab Using Network Visibility
+
+The `04_Server Authoritative Spawn Dynamic Prefab Using Network Visibility` scene is a dynamic Prefab loading scenario where the server instructs all clients to load a single network Prefab via a [ClientRpc](../../../docs/advanced-topics/message-system/clientrpc.md), spawns the Prefab as soon as it's loaded on the server, and marks the Prefab as network-visible only to clients that have already loaded that same Prefab. As soon as a client loads the Prefab locally, it sends an acknowledgement [ServerRpcs](../../../docs/advanced-topics/message-system/serverrpc.md), and the server marks that spawned NetworkObject as network-visible for that client.
+
+An important implementation detail to note about this technique is that the server won't wait until all clients load a dynamic Prefab before spawning the corresponding NetworkObject. As a result, a NetworkObject becomes network-visible for a connected client as soon as the client loads it—a client isn't blocked by the loading operation of another client (which might take longer to load the asset or fail to load it at all). A consequence of this asynchronous loading technique is that clients might experience differing world versions momentarily. As a result, it's not recommend to use this technique for spawning game-changing gameplay elements (like a boss fight, for example) if you want all clients to interact with the spawned NetworkObject as soon as the server spawns it.
+
+Take a look at the implementation, observed inside [ServerAuthoritativeNetworkVisibilitySpawning](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs). As was the case with the last use-case, the `Start()` method defines the callback to subscribe to from the UI (user interface). The method invoked on the server looks like:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L134-L149
+```
+
+A dynamic Prefab reference is selected at random, and will be spawned by the following method:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L151-L225
+```
+
+Similar to the last use-case, this section of code should only run on the server:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L161-L169
+```
+
+This method here will first load the dynamic Prefab on the server, and immediately spawn it on the server:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L178-L179
+```
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L185
+```
+
+After instantiating the NetworkObject, the sample keeps track of the instantiated NetworkObject in a dictionary, keyed by its asset GUID:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L187-L194
+```
+
+`NetworkObject.CheckObjectVisibility` is the callback that Netcode uses to decide whether to mark a NetworkObject as network-visible to a client. Here the sample explicitly defines a new callback. In this case, network-visibility is determined by whether the server has received an acknowledgement ServerRpc from a client for having loaded the dynamic Prefab.
+
+It's worth noting that this callback also runs on the host, so a quick server check returns a success:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L201-L205
+```
+
+If a client has loaded the dynamic Prefab in question, mark the NetworkObject network-visible to them:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L207-L211
+```
+
+If a client hasn't loaded the dynamic Prefab, send the client a ClientRpc instructing them to load the dynamic Prefab:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L216-L218
+```
+
+After the server defines this callback, it spawns the NetworkObject:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L221
+```
+
+The ClientRpc is identical to that of the last use-case, but this use-case takes a look at the ServerRpc in this class, and makes a distinction unique to this use-case:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L272-L280
+```
+
+This marks the NetworkObject network-visible to the non-hosting clients. The specific API used here is:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/DynamicAddressablesNetworkPrefabs/Assets/Scripts/04_Server%20Authoritative%20Network-Visibility%20Spawning/ServerAuthoritativeNetworkVisibilitySpawning.cs#L227-L239
+```
+
+### Scene 05_API Playground Showcasing All Post-Connection Uses
+
+The `05_API Playground Showcasing All Post-Connection Uses` scene uses a class that serves as the playground of the dynamic Prefab loading uses. It integrates APIs from this sample to use at post-connection time, such as:
+
+- Connection approval for syncing late-joining clients.
+- Dynamically loading a collection of network Prefabs on the host and all connected clients.
+- Synchronously spawning a dynamically loaded network Prefab across connected clients.
+- Spawning a dynamically loaded network Prefab as network-invisible for all clients until they load the Prefab locally (in which case it becomes network-visible to the client).
diff --git a/versioned_docs/version-2.0.0/learn/bitesize/bitesize-introduction.md b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-introduction.md
new file mode 100644
index 000000000..f4acedded
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-introduction.md
@@ -0,0 +1,44 @@
+---
+id: bitesize-introduction
+title: About Bitesize samples
+---
+
+The Bitesize Samples repository provides a series of sample code as modules to use in your games and better understand Netcode for GameObjects (Netcode).
+
+* [Multiplayer Use Cases](bitesize-usecases.md) - Learn more about core Netcode For GameObjects (Netcode) features through practical examples and In-Editor tutorials.
+* [2D Space Shooter Sample](bitesize-spaceshooter.md) - Learn more about physics movement and status effects using Netcode `NetworkVariables` and `ObjectPooling`.
+* [Invaders Sample](bitesize-invaders.md) - Learn more about game flow, modes, unconventional movement networked, and a shared timer.
+* [Client Driven Sample](bitesize-clientdriven.md) - Learn more about Client driven movements, networked physics, spawning vs statically placed objects, object reparenting.
+* [Dynamic Addressables Network Prefabs](bitesize-dynamicprefabs.md) - Learn more about the dynamic prefab system, which allows us to add new spawnable prefabs at runtime.
+
+## Requirements
+
+You need Unity and Netcode for GameObjects installed to work with these samples. See [Install Netcode for GameObjects ](../../installation/installation.md) for details.
+
+## Get the samples
+
+### Get the project files
+
+Download the project files from the [Bitesize Samples Repository](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize)
+
+![how to download](/img/bitesize/bitesize-download.png)
+
+After download, unzip the archive file. You are now ready to add the project to Unity Hub.
+
+### Add a sample to the Unity Hub
+
+1. Open Unity Hub.
+1. Click **Add**.
+1. Navigate to the unzipped folder. select the one of the projects in the `Basic` folder to add the respective project.
+
+:::important Compatibility
+The Bitesize Samples have been built for a specific Unity version. You can see the version after adding a sample to the Unity Hub or in the description of the [repository](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize). We recommend using the same Unity version to avoid potential issues.
+:::
+
+## Troubleshooting
+
+**Error building**
+
+*Error:* Error building Player: Currently selected scripting backend (IL2CPP) isn't installed.
+
+Currently, you may need to have [Unity IL2CPP](https://docs.unity3d.com/Manual/IL2CPP.html) installed. Bitesize Samples should not require IL2CPP, and may have updates to resolve this error.
diff --git a/versioned_docs/version-2.0.0/learn/bitesize/bitesize-invaders.md b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-invaders.md
new file mode 100644
index 000000000..e539be95b
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-invaders.md
@@ -0,0 +1,129 @@
+---
+id: bitesize-invaders
+title: Invaders sample
+description: Learn more about game flow, modes, unconventional movement networked, and a shared timer using Netcode for GameObjects.
+---
+
+The [Invaders Sample Project](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/main/Basic/Invaders) to understand the game flow and modes with Netcode for GameObjects (Netcode) using Scene Management, Unconventional Movement Networked, and a Shared Timer between clients updated client-side with server side seeding.
+
+## Game Flows
+
+Most Multiplayer games have multiple Networked Scenes, where players can join, communicate, and progress through scenes and maps together. This is a game flow: players join and establish communication together, the server determines the next scene or map, and transitions all clients to the new scene and loads the required map. This ensures players can play together.
+
+The logic and transitions are a specified game flow. To transition in a smooth manner, you need to create game flows and back-end systems that support those flows.
+
+Invaders implements this game-flow by creating different controller classes that handle each Game Mode such as MainMenu, a simple Networked Lobby and InGame modes, and other support classes that help with the transition from one Game Mode to another.
+
+The backbones of the flow/system mentioned above is consisting of two main components:
+
+* `SceneTransitionHandler`
+* `SceneState`
+* `Lobby Controller`
+
+### SceneTransitionHandler
+
+A `SceneTransitionHandler` with a lightweight state machine allows you to track clients' progress in regards to Scene Loading. It notifies the server when clients finish loading so that the other listeners are informed, by subscribing to the `NetworkedSceneManager` load events and creating a wrapper around it that others can subscribe to.
+
+Those events are invoked by `NetworkSceneManager` during the loading process. Invaders subscribe to these events when strating the server in the [MenuControl](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/MenuControl.cs) via the [SceneTransitionHandler.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/SceneTransitionHandler.cs):
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/MenuControl.cs#L16-L30
+```
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/SceneTransitionHandler.cs#L90-L97
+```
+
+### SceneState
+
+At the same time, we have implemented a light State Machine to keep track of the current `SceneState`. For example, the `SceneState` can indicate if players are in the Init or Bootstrap scene, Start or Lobby, or InGame. You can run a different Behavior or in this case a different `UpdateLoop` function, for each state.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/SceneTransitionHandler.cs#L25-L34
+```
+
+One example of how to update the current `SceneState` is in *[InvadersGame.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/InvadersGame.cs)*, in the `OnNetworkSpawn` function.
+
+:::note
+This class has the same role as the Lobby Controller, it acts as a Manager, for a specific part of the game.
+:::
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/InvadersGame.cs#L156-L194
+```
+
+### Lobby Controller
+
+A Lobby Controller is a Manager for the lobby. This is where we applied a simple Mediator Design Pattern that restricts direct communications between the objects and forces them to collaborate only using a moderator object. In this case, the *[LobbyControl.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/LobbyControl.cs)* handles Lobby interactions and state. This works hand-in-hand with the `SceneTransitionHandler`, by subscribing to the `OnClientLoadedScene` of that class in `OnNetworkSpawn`.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/LobbyControl.cs#L23-L45
+```
+
+Whenever the `OnClientLoadedScene` callback is called, the custom `ClientLoadedScene` function is also called. And that is the location where you add the new Player to a container that just loaded the Lobby Scene, generates user stats for it (which is just a random name), and then later sends an update to the rest of the users notifying them that someone new has joined the Lobby.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/LobbyControl.cs#L90-L107
+```
+
+When the players join this Lobby, they all need to click **Ready** before the game can progress to the next scene (before the Host can start the game). After players click Ready, you send a `ServerRPC` called `OnClientIsReadyServerRpc` (inside the `PlayerIsReady` function). When it arrives server-side, it marks the client state as ready based on its `ClientId`. You keep track of if a client is ready in the `m_ClientsInLobby` `Dictionary`.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/LobbyControl.cs#L195-L209
+```
+
+At the same time, to sync up with the rest of the clients and update their UI, we send a ClientRpc. The update is handled by the ClientRpc called `SendClientReadyStatusUpdatesClientRpc` in `UpdateAndCheckPlayersInLobby`.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/LobbyControl.cs#L126-L144
+```
+
+When all the players have joined the lobby and are ready, `UpdateAndCheckPlayersInLobby` calls `CheckForAllPlayersReady` to transition to the next scene.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/LobbyControl.cs#L146-L174
+```
+
+## Unconventional Networked Movement
+
+Invaders has an easy movement type - moving only on one (horizontal) axis - which allows you to only modify the transform client-side without waiting for server-side validation. You can find where we perform the move logic in *[PlayerControl.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/PlayerControl.cs)* in the `InGameUpdate` function . With the help of a [`NetworkTransform`](../../components/networktransform.md) that is attached directly to the Player Game Object, it will automatically sync up the Transform with the other clients. At the same time, it will smooth out the movement by interpolating or extrapolating for all of them.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/PlayerControl.cs#L176-L193
+```
+
+## Shared Start/Round Timer updated Client-Side
+
+Games commonly have timers to display in the UI such as Start Timer, Round Timer, and Cooldowns. The Invaders sample also has a shared timer to ensure all players start the game at the same time. Otherwise, players with higher-end devices and better network access may have an unfair advantage by loading scenes and maps faster.
+
+When you implement this kind of timer, usually you would use a `NetworkVariable` to replicate and display the exact time value across all clients. To improve performance, you don't need to replicate that float every Network Tick to the Clients, which would only waste network bandwidth and some minimal CPU resources.
+
+An alternative solution is to sync only the start of the timer to the clients, and afterwards only sync the remaining value of the timer when a new client joins. For the remaining time, clients can update the timer locally. This method ensures the server does not need to send the value of that timer every Network Update tick since you know what the approximated value will be.
+
+In Invaders we chose the second solution instead, and simply start the timer for clients via an RPC.
+
+### Start the game timer
+
+First, use `ShouldStartCountDown` to start the timer and send the time remaining value to the client-side. This initiates and sends the value only once, indicating the game has started and how much time remains. The game then counts down locally using these values. See [Update game timer Client-Side](#update-game-timer-client-side).
+
+Example code to start the countdown:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/InvadersGame.cs#L205-L229
+```
+
+In the case of a late-joining client, if the timer is already started, we send them an RPC to tell them the amount of time remaining.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/InvadersGame.cs#L196-L203
+```
+
+### Update game timer Client-Side
+
+On the client-side, use the `UpdateGameTimer` to locally calculate and update the `gameTimer`. The server only needs to be contacted once to check if the game has started (`m_HasGameStared` is true) and the `m_TimeRemaining` amount, recieved by `ShouldStartCountDown`. When met, it locally calculates and updates the `gameTimer` reducing the remaining time on the client-side for all players. When `m_TimeRemaining` reaches 0.0, the timer is up.
+
+Example code to update the game timer:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/Invaders/Assets/Scripts/InvadersGame.cs#L276-L299
+```
diff --git a/versioned_docs/version-2.0.0/learn/bitesize/bitesize-spaceshooter.md b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-spaceshooter.md
new file mode 100644
index 000000000..8cbb507ef
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-spaceshooter.md
@@ -0,0 +1,69 @@
+---
+id: bitesize-spaceshooter
+title: 2D Space Shooter sample
+description: Learn more about physics movement and status effects using Netcode for GameObjects (Netcode) NetworkVariables and ObjectPooling .
+---
+
+The [2D Space Shooter Project](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/tree/master/Basic/2DSpaceShooter) provides examples of physics, player health, and status effects using Netcode for GameObjects (Netcode). Technical features include[NetworkVariable](../../basics/networkvariable.md) and [ObjectPooling](../../advanced-topics/object-pooling.md).
+
+## Server Authoritative Physics Movement
+
+The movement in 2DSpaceShooter is physics based. The player object is a dynamic rigidbody and can collide with other players or asteroids. Physics in multiplayer games can be hard to get right. For simplicity, 2DSpaceShooter runs all movement and physics just on the server-side.
+
+The client sends inputs in the form of RPCs to the server. The server then uses those inputs to adjust the throttle and turn values of the player.
+
+This method of running physics makes sure that there are no desyncs or other physics issues between the client and server, but it introduces more latency.
+
+## Player Health
+
+2DSpaceShooter uses `NetworkVariable`s to track the players health and energy. Both variables are server authoritative, only the host or server can make changes to them. The client draws the player's health bar simply by accessing the value of the `NetworkVariable`.
+
+For example:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/2DSpaceShooter/Assets/Scripts/ShipControl.cs#L172-L175
+```
+
+## Power-ups and Status Effects
+
+The 2DSpaceShooter sample has power-ups which apply different status effects to a player on collection. The core implementation of the power up effects in `ShipControl.cs` is simplistic.
+
+The power-ups themselves are server authorative. On the server they check if a player has entered their trigger and then apply a timed status effect to that player and disappear.
+
+The `ShipControl.cs` of the player object tracks each status effect. `NetworkVariable`s are used as duration timers to control the beginning and end of status effects. You can also use regular floats for timers. By using `NetworkVariable`s, the client can use this information to display different graphics based on active buffs to players.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/2DSpaceShooter/Assets/Scripts/ShipControl.cs#L431-L486
+```
+
+## NetworkObject Pooling
+
+The `2DSpaceShooter` object creates many objects dynamically at runtime including bullets, asteroids, and pickups. 2DSpaceShooter uses object pooling to avoid performance issues of instantiating and destroying Unity Objects all the time and creating allocations in the process.
+
+2DSpaceShooter uses the NetworkObjectPool script, which can be found in the Community Contributions Repository.
+
+![pool img](/img/bitesize/invader-networkobjectpool.png)
+
+All of the runtime spawnable objects have been registered to the pool. On the client-side, this will cause Netcode to use an object from the pool instead of instantiating a new Object. When the NetworkObject is despawned, it will be automatically returned to the pool instead of getting destroyed.
+
+Adding the `NetworkObjectPool` to the scene won't yet pool server objects because these must be manually created and then spawned by the user. Instead of instantiating objects, your code should take them from the pool.
+
+Regular Netcode Spawn Code example:
+
+```csharp
+GameObject powerUp = Instantiate(m_PowerupPrefab);
+powerUp.GetComponent().Spawn(null, true);
+```
+
+Pooled Netcode Spawn Code example:
+
+```csharp
+GameObject powerUp = m_ObjectPool.GetNetworkObject(m_PowerupPrefab);
+powerUp.GetComponent().Spawn(null, true);
+```
+
+
+
+:::tip
+If you are using Unity 2021, you can use the built-in [Object Pooling API](https://docs.unity3d.com/2021.1/Documentation/ScriptReference/Pool.ObjectPool_1.html) instead to build your own object pools.
+:::
diff --git a/versioned_docs/version-2.0.0/learn/bitesize/bitesize-usecases.md b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-usecases.md
new file mode 100644
index 000000000..a349c36d7
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bitesize/bitesize-usecases.md
@@ -0,0 +1,43 @@
+---
+id: bitesize-usecases
+title: Multiplayer Use Cases sample
+description: Learn about the scenes in the Multiplayer Use Cases sample.
+---
+
+The [Multiplayer Use Cases Sample](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/tree/main/Basic/MultiplayerUseCases) provides multiple scenes that explain some APIs, systems, and concepts that you can use with Netcode for GameObjects:
+
+- Server-side manipulation of data sent by Clients.
+- State synchronization through NetworkVariables.
+- Proximity interactions that are only visible only to the local player.
+- Client-server communication through Remote Procedure Calls (RPCs).
+
+### Tutorials
+
+Each scene includes a tutorial to help you locate the scripts and GameObjects it uses. Follow the tutorial included in each sample scene to learn how to use it.
+
+The tutorials that open with each scene use the [Tutorial Framework package](https://docs.unity3d.com/Packages/com.unity.learn.iet-framework@4.0/manual/index.html). You can open each tutorial at any time from the **Tutorials** menu.
+
+## The NetvarVsRpc scene
+
+The NetvarVsRpc scene explains why to use NetworkVariables instead of Remote Procedure Calls (RPCs) to perform state synchronization.
+
+## The NetworkVariables scene
+
+The NetworkVariables scene shows you how to use NetworkVariables to perform state synchronization in a way that also sends the most recent information to late joining or reconnecting clients.
+
+## The ProximityChecks scene
+
+The ProximityChecks scene shows you how to detect the local user and enable or disable in-game actions based on the player character's distance from a GameObject.
+
+## The RPCs scene
+
+The RPCs scene demonstrates the following Remote Procedure Call (RPC) processes:
+ * Use RPCs to send information from clients to the server.
+ * Perform server-side manipulation of the data sent.
+ * Use connection approval to determine the spawn position of the player.
+
+## Additional resources
+
+- Get help and ask questions on [Multiplayer Discussions](https://discussions.unity.com/lists/multiplayer).
+- Join the community of Multiplayer creators on the [Multiplayer Networking Discord](https://discord.gg/unity-multiplayer-network).
+- [Request a feature or report a bug](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/issues/new/choose).
diff --git a/versioned_docs/version-2.0.0/learn/bossroom/architecture.md b/versioned_docs/version-2.0.0/learn/bossroom/architecture.md
new file mode 100644
index 000000000..d07e0cdd5
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bossroom/architecture.md
@@ -0,0 +1,270 @@
+---
+id: bossroom-architecture
+title: Boss Room architecture
+---
+Boss Room is a fully functional co-op multiplayer RPG made with Unity Netcode. It's an educational sample designed to showcase typical Netcode patterns often featured in similar multiplayer games. Players work together to fight Imps and a boss using a click-to-move control model.
+
+This article describes the high-level architecture of the Boss Room codebase and dives into some reasoning behind architectural decisions.
+
+## Assembly structure
+
+Boss Room's code is organized into multiple domain-based assemblies, each with a relatively self-contained purpose.
+
+An exception to this organization structure is the Gameplay assembly, which houses most of the networked gameplay logic and other functionality tightly coupled with the gameplay logic.
+
+This assembly separation style enforces better separation of concerns and helps keep the codebase organized. It also uses more granular recompilation during iterations to save time.
+
+![Assembly structure](/img/arch-2.png)
+
+## Application flow
+
+The application flow of Boss Room starts with the `Startup` scene (which should always load first).
+
+:::tip
+The Boss Room sample has an editor tool that enforces starting from the `Startup` scene even if you're working in another scene. You can disable this tool through the Unity Editor by selecting **Menu** > **Boss Room** > **Don't Load Bootsrap Scene On Play**. Select **Load Bootsrap Scene On Play** to re-enable it.
+:::
+
+The `ApplicationController` component lives on a GameObject in the Startup scene and serves as the application's entry point (and composition root). It binds dependencies throughout the application's lifetime (the core dependency injection managed “singletons”). See the [Dependency Injection](#dependency-injection) section for more information.
+
+## Game state and scene flow
+
+Each scene in Boss Room has an entry point component sitting on a root-level GameObject that serves as a scene-specific composition root.
+
+After Boss Room starts and the initial bootstrap logic completes, the `ApplicationController` class loads the `MainMenu` scene.
+
+The MainMenu scene only has the `MainMenuClientState`, whereas scenes that contain networked logic also have the server counterparts to the client state components. In the latter case, both the server and client components exist on the same GameObject.
+
+The `NetworkManager` starts when the `CharSelect` scene loads, which happens when a player joins or hosts a game. The host drives game state transitions and controls the set of loaded scenes. Having the host manage the state transitions and scenes indirectly forces all clients to load the same scenes as the server they're connected to (via Netcode's networked scene management).
+
+### Application Flow Diagram
+
+![Application Flow Diagram](/img/arch-1.png)
+
+:::note
+Boss Room's main room has four scenes. The primary scene (Boss Room's root scene) has the state components, game logic, level `navmesh`, and trigger areas that let the server know to load a given sub-scene. Boss Room loads each sub-scene additively using those triggers.
+:::tip
+
+Sub-scenes contain spawn points for the enemies and visual assets for their respective level segments. The server unloads sub-scenes that don't have active players and loads the required sub-scenes based on the players' position. If at least one player overlaps with the sub-scene's trigger area, the server loads the sub-scene.
+
+## Transports
+
+Boss Room supports two network transport mechanisms:
+
+* IP
+* Unity Relay
+
+Clients connect directly to a host via an IP address when using IP. However, the IP network transport only works if the client and host are in the same local area network (or if the host uses port forwarding).
+
+With the Unity Relay network transport, clients don't need to worry about sharing a local area network or port forwarding. However, you must first [set up the Relay service](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Documentation/Unity-Relay/README.md).
+
+See the [Multiplayer over the internet](getting-started-boss-room.md) section of the Boss Room README for more information about using the two network transport mechanisms.
+
+Boss Room uses the Unity Transport package. Boss Room's assigns its instance of Unity Transport to the `transport` field of the `NetworkManager`.
+
+The Unity Transport Package is a network transport layer with network simulation tools that help spot networking issues early during development. Boss Room has both buttons to start a game in the two modes and will setup Unity Transport automatically to use either one of them at runtime.
+
+Unity Transport supports Unity Relay (provided by Unity Gaming Services). See the documentation on [Unity Transport package](../../../transport/about.md) and [Unity Relay](https://docs-multiplayer.unity3d.com/docs/relay/relay) for more information.
+
+## Connection flow state machine
+
+The `ConnectionManager`, a simple state machine, owns Boss Room's network connection flow. It receives inputs from Netcode for GameObjects (or the user) and handles the inputs according to its current state. Each state inherits from the `ConnectionState` abstract class. If you add a new transport, you must extend the `StartingHostState` and `ClientConnectingState` states. Both of these classes assume you're using the Unity Transport transport.
+
+![Connection flow state machine](/img/arch-3.png)
+
+## Session management and reconnection
+
+To allow users to reconnect to the game and restore their game state, Boss Room stores a map of the GUIDs for their respective data. This way, it ensures that when a player disconnects, Boss Room accurately reassigns data to that player when they reconnect.
+
+For more information, see [Session Management](../../advanced-topics/session-management.md).
+
+## Unity Gaming Services integration
+
+Boss Room is a multiplayer experience designed to be playable over the internet. To effectively support this, it integrates several [Unity Gaming Services](https://unity.com/solutions/gaming-services) (UGS):
+
+* Authentication
+* Lobby
+* Relay
+
+These three UGS services allow players to host and join games without needing port forwarding or out-of-game coordination.
+
+To keep a single source of truth for service access (and avoid scattering of service access logic), Boss Room wraps UGS SDK access into `Facades` and uses UI mediators to contain the service logic triggered by user interfaces (UIs).
+
+* [`AuthenticationServiceFacade.cs`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs)
+* [`LobbyServiceFacade.cs`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/UnityServices/Lobby/LobbyServiceFacade.cs)
+* Lobby and Relay - client join - `JoinLobbyRequest()` in [Assets/Scripts/Gameplay/UI/Lobby/LobbyUIMediator.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/UI/Lobby/LobbyUIMediator.cs)
+* Relay Join - `StartClientLobby()` in [Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs)
+* Relay Create - `StartHostLobby()` in [Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs)
+* Lobby and Relay - host creation - `CreateLobbyRequest()` in [Assets/Scripts/Gameplay/UI/Lobby/LobbyUIMediator.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/UI/Lobby/LobbyUIMediator.cs)
+
+## Core gameplay structure
+
+:::note
+An `Avatar` is at the same level as an `Imp` and lives in a scene. A `Persistent Player` lives across scenes.
+:::
+
+A `Persistent Player` Prefab goes into the `Player` Prefab slot in the `NetworkManager` of Boss Room. As a result, Boss Room spawns a single `Persistent Player` Prefab per client, and each client owns their respective `Persistent Player` instances.
+
+:::note
+There is no need to mark `Persistent Player` instances as `DontDestroyOnLoad`. Netcode for GameObjects automatically keeps these prefabs alive between scene loads while the connections are live.
+:::
+
+The `Persistent Player` Prefab stores synchronized data about a player, such as their name and selected `PlayerAvatar` GUID.
+
+Each connected client owns their respective instance of the PlayerAvatar prefab. Netcode for GameObjects destroys the `PlayerAvatar` instance when a scene load occurs (either to the `PostGame` or `MainMenu` scenes) or if the client disconnects.
+
+In the `CharSelect` scene, clients select from eight possible avatar classes. Boss Room stores each player's selection inside the `PersistentPlayer`'s `NetworkAvatarGuidState`.
+
+Inside the Boss Room scene, `ServerBossRoomState` spawns a `PlayerAvatar` per `PersistentPlayer` present.
+
+The following example of a selected “Archer Boy” class shows the `PlayerAvatar` GameObject hierarchy:
+
+* `PlayerAvatar` is a NetworkObject that Boss Room destroys when the scene unloads.
+* `PlayerGraphics` is a child `GameObject` containing a `NetworkAnimator` component responsible for replicating animations invoked on the server.
+* `PlayerGraphics_Archer_Boy` is a purely graphical representation of the selected avatar class.
+
+`ClientAvatarGuidHandler`, a `NetworkBehaviour` component residing on the `PlayerAvatar` Prefab instance, fetches the validated avatar GUID from `NetworkAvatarGuidState` and spawns a local, non-networked graphics GameObject corresponding to the avatar GUID.
+
+### Characters
+
+`ServerCharacter` exists on a `PlayerAvatar` (or another NPC character) and has server RPCs and `NetworkVariables` that store the state of a given character. It's responsible for executing the server-side logic for the characters. This server-side logic includes the following:
+
+* Movement and pathfinding via `ServerCharacterMovement` use `NavMeshAgent,` which exists on the server to translate the character's transform (synchronized using the `NetworkTransform` component);
+* Player action queueing and execution via `ServerActionPlayer`;
+* AI logic via `AIBrain` (applies to NPCs);
+* Character animations via `ServerAnimationHandler`, which uses `NetworkAnimator` to synchronize;
+* `ClientCharacter` is primarily a host for the `ClientActionPlayer` class and has the client RPCs for the character gameplay logic.
+
+### Game config setup
+
+We defined Boss Room's game configuration using ScriptableObjects.
+
+The [`GameDataSource.cs`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/GameDataSource.cs) singleton class stores all actions and character classes in the game.
+
+[`CharacterClass`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Configuration/CharacterClass.cs) is the data representation of a Character and has elements such as starting stats and a list of Actions the character can perform. It covers both player characters and non-player characters (NPCs) alike.
+
+The [`Action`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Configuration/Action.cs) subclasses are data-driven and represent discrete verbs, such as swinging a weapon or reviving a player.
+
+### Action System
+
+:::note
+Boss Room's action system was created specifically for Boss Room's educational purpose. You'll need to implement a more user friendly custom action system to allow for better game design emergence from your game designers.
+:::
+
+Boss Room's Action System is a generalized mechanism for `Characters` to "do stuff" in a networked way. `ScriptableObject`-derived `Actions` implement the client and server logic of any given thing the characters can do in the game.
+
+There are a variety of actions that serve different purposes. Some actions are generic and reused by multiple character classes, while others are specific to a single class.
+
+Each character can have multiple actions that exist simultaneously but only one active `Action` (also called the "blocking" action). If a character triggers a later action, Boss Room queues it behind the current action. Non-blocking actions can run in the background without interfering with the current action.
+
+Boss Room synchronizes actions by calling a `ServerCharacter.RecvDoActionServerRPC` and passing the `ActionRequestData`, a struct that implements the `INetworkSerializable` interface.
+
+:::note
+`ActionRequestData` has an `ActionID` field, a simple struct that wraps an integer containing the index of a given `ScriptableObject` `Action` in the registry of abilities available to characters. The registry of available character abilities is stored in `GameDataSource`.
+:::
+
+Boss Room uses the `ActionID` struct to reconstruct the requested action and play it on the server by creating a pooled clone of the `ScriptableObject` `Action` that corresponds to the action. Clients then play out the visual part of the ability (including particle effects and projectiles).
+
+It's also possible to play an anticipatory animation on the client requesting an ability. For instance, you might want to play a small jump animation when the character receives movement input but hasn't yet moved (because it hasn't synchronized the data from the server).
+
+[`ServerActionPlayer`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ActionPlayers/ServerActionPlayer.cs) and [`ClientActionPlayer`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ActionPlayers/ClientActionPlayer.cs) are companion classes to actions Boss Room uses to play out the actions on both the client and server.
+
+#### Movement action flow
+
+The following list describes the movement flow of a player character.
+
+1. The client uses a mouse to click on the target destination.
+2. The client sends an RPC (containing the target destination) to the server.
+3. Anticipatory animation plays immediately on the client.
+4. There's network latency before the server receives the RPC.
+5. The server receives the RPC (containing the target destination).
+6. The server performs pathfinding calculations.
+7. The server completes the pathfinding, and the server representation of the entity starts updating its `NetworkTransform` at the same cadence as `FixedUpdate`.
+8. There's network latency before clients receive replication data.
+9. The client representation of the entity updates its NetworkVariables.
+
+:::note
+The Visuals GameObject never outpaces the simulation GameObject and is always slightly behind the networked position and rotation.
+:::
+
+### Navigation system
+
+Each scene with navigation (or dynamic navigation objects) should have a `NavigationSystem` component on a scene GameObject. The `GameObject` containing the `NavigationSystem` component must have the `NavigationSystem` tag.
+
+#### Building a navigation mesh
+
+Boss Room uses `NavMeshComponents`, meaning building directly from the `Navigation` window fails to deliver the desired results.
+
+Instead, find a `NavMeshComponent` in the given scene (for example, a `NavMeshSurface`) and use the **Bake** button on that script.
+
+You should also ensure each scene has exactly one `navmesh` file. You can find `navmesh` files stored in a folder with the same name as the corresponding scene (prefixed by “`NavMesh-`”).
+
+## Architectural patterns and decisions
+
+### Dependency injection
+
+Boss Room implements the [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) (DI) pattern using the [`VContainer`](https://vcontainer.hadashikick.jp/) library. DI allows Boss Room to clearly define its dependencies in code instead of using static access, pervasive singletons, or scriptable object references (Scriptable Object Architecture). Code is easy to version-control and comparatively easy to understand for a programmer, unlike Unity YAML-based objects, such as scenes, scriptable object instances, and prefabs.
+
+DI also allows Boss Room to circumvent the problem of cross-scene references to common dependencies, even though it still has to manage the lifecycle of `MonoBehaviour`-based dependencies by marking them with `DontDestroyOnLoad` and destroying them manually when appropriate.
+
+:::note
+`ApplicationController` inherits from the `VContainer`'s `LifetimeScope`, a class that serves as a dependency injection scope and bootstrapper that facilitates binding dependencies. Scene-specific State classes inherit from `LifetimeScope`, too.
+:::
+
+In the Unity Editor Inspector, you can choose a parent scope for any `LifetimeScope`. When doing so, it's helpful to set a cross-scene reference to some parent scopes, most commonly the `ApplicationController`. Setting a cross-scene reference allows you to bind scene-specific dependencies while maintaining easy access to the global dependencies of the `ApplicationController` in the State-specific version of a `LifetimeScope` object.
+
+### `Client`/`Server` code separation
+
+A challenge the Boss Room development team encountered when developing Boss Room was that code would often run in a single context, either client or server. Reading mixed client and server code adds a layer of complexity, making mistakes more likely.
+
+To solve this challenge, they explored different client-server code separation approaches. The team eventually decided to revert the initial client/server/shared assemblies to a more classic domain-driven assembly architecture while keeping more complex classes separated by client/server.
+
+The initial thought was that separating assemblies by client and server would allow for easier porting to a dedicated game server (DGS) model afterward; the team would only need to strip a single assembly to ensure code only runs when necessary.
+
+However, this approach had two primary issues:
+
+* It introduced callback hell, which made code (that should be trivial) too complex. You can look at the different action implementations in Boss Room 1.3.1 to see this.
+* Many components were better suited as single simple classes instead of three-class horrors.
+
+After investigation, the Boss Room development team determined that client/server separation was unnecessary for the following reasons:
+
+* There's no need for [asmdef (assembly definition)](https://docs.unity3d.com/Manual/cus-asmdef.html) stripping because you can ifdef out single classes instead.
+* It's not completely necessary to ifdef classes because it's only compile-time insurance that certain parts of client-side code never run. You can still disable the component on Awake at runtime if it's not mean to run on the server or client.
+* The added complexity outweighed the pros that'd help with stripping whole assemblies.
+* Most `Client`/`Server` class pairs are tightly coupled and call one another; they have split implementations of the same logical object. Separating them into different assemblies forces you to create “bridge classes” to avoid circular dependencies between your client and server assemblies. By putting your client and server classes in the same assemblies, you allow those circular dependencies in those tightly coupled classes and remove unnecessary bridging and abstractions.
+* Whole assembly stripping is incompatible with Netcode for GameObjects because Netcode for GameObjects doesn't support NetworkBehaviour stripping. Components related to a NetworkObject must match on the client and server sides. If these components aren't identical, it creates undefined runtime errors (the errors will change from one use to another; they range from no issue, to silent errors, to buffer exceptions) with Netcode for GameObjects' `NetworkBehaviour` indexing.
+
+After those experiments, the Boss Room development team established new rules for the codebase:
+
+* Use domain-based assemblies
+* Use single classes for small components (for example, the Boss Room door with a simple on/off state).
+ * If a class never grows too big, use a single NetworkBehaviour (because it's easy to maintain).
+* Use client and server classes (with each pointing to the other) for client/server separation.
+* Place client/server pairs in the same assembly.
+* If you start the game as a client, the server components disable themselves, leaving you with only client components executing. Ensure you don't destroy the server components. Netcode for GameObjects still requires the server component for network message sending.
+* The clients have a `m_Server`, and servers have a `m_Client` property.
+* The `Server` class owns server-driven `NetworkVariables`. Similarly, the `Client` class owns owner-driven `NetworkVariables`. This ownership separation helps make larger classes more readable and maintainable.
+* Use partial classes when separating by context isn't possible.
+* Continue using the `Client`/`Server` prefix to make contexts more obvious. Note: You can't use prefixes for `ScriptableObjects` that have file name requirements.
+* Use `Client`/`Server`/`Shared` separation when you have a one-to-many relationship where your server class needs to send information to many client classes. You can also achieve this with the [`NetworkedMessageChannel`](#networkedmessagechannel).
+
+You still need to take care of code executing in `Start` and `Awake`. If the code in `Start` and `Awake` runs simultaneously with the NetworkManager's initialization, it might not know whether the player is a host or client.
+
+### Publisher-Subscriber Messaging
+
+Boss Room implements a dependency injection-friendly Publisher-Subscriber pattern that allows Boss Room to send and receive strongly-typed messages in a loosely coupled manner, where communicating systems only know about the `IPublisher`/`ISubscriber` of a given message type.
+
+Because publishers and subscribers are classes, Boss Room can have more interesting behavior for message transfer, such as buffered and networked messaging. See the [`NetworkedMessageChannel`](#networkedmessagechannel) section.
+
+These mechanisms allow Boss Room to avoid circular references and limit the dependency surface between assemblies. Cross-communicating systems rely on common messages but don't necessarily need to know about each other. Because messages don't need to know about each other, Boss Room can more easily separate them into smaller assemblies.
+
+These mechanisms allow for strong separation of concerns and coupling reduction using PubSub and dependency injection (DI). Boss Room uses DI to pass the handles to the `IPublisher` or `ISubscriber` of any given event type. As a result, message publishers and consumers are unaware of each other.
+
+`MessageChannel` classes implement the `IPublisher` and `ISubscriber` interfaces and have the actual messaging logic.
+
+:::note
+The Boss Room development team considered using a third party library for messaging (like `MessagePipe`). However, since Boss Room needed custom networked channels and the use cases were quite simple, the team decided to go with an in-house light implementation. If Boss Room was a full game with more gameplay, it'd benefit more from a library that with more features.
+:::
+
+#### `NetworkedMessageChannel`
+
+With in-process messaging, Boss Room implements the `NetworkedMessageChannel`, which uses the same API, but allows for sending data between peers. Boss Room implements the Netcode synchronization for these using custom Netcode for GameObjects messaging, which serves as a useful synchronization primitive in the codebase arsenal.
diff --git a/versioned_docs/version-2.0.0/learn/bossroom/bossroom-actions.md b/versioned_docs/version-2.0.0/learn/bossroom/bossroom-actions.md
new file mode 100644
index 000000000..8caaf9dfb
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bossroom/bossroom-actions.md
@@ -0,0 +1,52 @@
+---
+id: bossroom-actions
+title: Boss Room actions walkthrough
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+Boss Room's actions each use a different pattern for good multiplayer quality. This doc walks you through each of them and goes into details about how we implemented each and what lessons you can learn from each. You can get their implementations [here](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/tree/v2.1.0/Assets/Scripts/Gameplay/Action).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/versioned_docs/version-2.0.0/learn/bossroom/getting-started-boss-room.md b/versioned_docs/version-2.0.0/learn/bossroom/getting-started-boss-room.md
new file mode 100644
index 000000000..6266f5d30
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bossroom/getting-started-boss-room.md
@@ -0,0 +1,286 @@
+---
+id: bossroom
+title: Getting started with Boss Room
+description: Learn more about installing and running the Boss Room game sample.
+---
+
+![Boss Room banner](/img/banner.png)
+
+Boss Room is a fully functional co-op multiplayer RPG made with Unity Netcode. it's an educational sample designed to showcase typical netcode [patterns](https://docs-multiplayer.unity3d.com/netcode/current/learn/bossroom/bossroom-actions/index.html) often featured in similar multiplayer games.
+
+:::note
+**Note**: Boss Room is compatible with the latest Unity Long Term Support (LTS) Editor version (currently [2022 LTS](https://unity.com/releases/lts)). Make sure to include standalone support for Windows/Mac in your installation.
+:::
+
+Boss Room has been developed and tested on the following platforms:
+
+* Windows
+* Mac
+* iOS
+* Android
+
+The minimum device specifications for Boss Room are:
+
+* iPhone 6S
+* Samsung Galaxy J2 Core
+
+Join the multiplayer community on the Unity [Discord](https://discord.gg/mNgM2XRDpb) and [Forum](https://forum.unity.com/forums/multiplayer.26/) to connect and find support. Got feedback? Tell us what you think using our new [Feedback Form](#feedback-form).
+
+### Contents and quick links
+
+- [Contents and quick links](#contents-and-quick-links)
+- [Boss Room Overview](#boss-room-overview)
+- [Getting the project](#getting-the-project)
+ - [Installing Git LFS to clone locally](#installing-git-lfs-to-clone-locally)
+ - [Direct download](#direct-download)
+- [Registering the project with Unity Gaming Services (UGS)](#registering-the-project-with-unity-gaming-services-ugs)
+- [Opening the project for the first time](#opening-the-project-for-the-first-time)
+- [Exploring the project](#exploring-the-project)
+- [Testing multiplayer](#testing-multiplayer)
+ - [Local multiplayer setup](#local-multiplayer-setup)
+ - [Multiplayer over Internet](#multiplayer-over-internet)
+- [Index of resources](#index-of-resources)
+ - [Gameplay](#gameplay)
+ - [Game flow](#game-flow)
+ - [Connectivity](#connectivity)
+ - [Services](#services)
+ - [Tools and utilities](#tools-and-utilities)
+- [Troubleshooting](#troubleshooting)
+ - [Bugs](#bugs)
+- [Licence](#licence)
+- [Other samples](#other-samples)
+- [Contributing](#contributing)
+- [Feedback form](#feedback-form)
+
+### Boss Room Overview
+
+Boss Room is designed to be used in its entirety to help you explore the concepts and patterns behind a multiplayer game flow; such as character abilities, casting animations to hide latency, replicated objects, RPCs, and integration with the [Relay](https://unity.com/products/relay), [Lobby](https://unity.com/products/lobby), and [Authentication](https://unity.com/products/authentication) services.
+
+You can use the project as a reference starting point for your own Unity game or use elements individually.
+
+This repository also has a [Utilities](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop) package containing reusable sample scripts. You can install it using the following manifest file entry:
+
+```json
+"com.unity.multiplayer.samples.coop": "https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop"
+```
+
+For more information on the art in Boss Room, see [ART_NOTES.md](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Documentation/ART_NOTES.md).
+
+### Getting the project
+
+You can get the project by downloading it directly or cloning locally. However, if you use git, you must install Git LFS.
+
+#### Installing Git LFS to clone locally
+
+Boss Room uses Git Large Files Support (LFS) to handle all large assets required locally. See [Git LFS installation options](https://github.com/git-lfs/git-lfs/wiki/Installation) for Windows and Mac instructions. This step is only needed if cloning locally. You can also just download the project which will already include large files.
+
+#### Direct download
+
+You can download the latest version of Boss Room from our [Releases](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases) page. Doing so doesn't require you to use Git LFS.
+
+Alternatively, you can click the green **Code** button, then select **Download Zip**. This downloadd the branch that you are currently viewing on Github.
+
+:::note
+**Note for Windows users**: Using Windows' built-in extraction tool may generate an `Error 0x80010135: Path too long` error window which can invalidate the extraction process. A workaround for this is to shorten the zip file to a single character (for example, "`c.zip`") and move it to the shortest path on your computer (most often right at `C:\`) and retry. If that solution fails, another workaround is to extract the downloaded zip file using [7zip](https://www.7-zip.org/).
+:::
+
+### Registering the project with Unity Gaming Services (UGS)
+
+Boss Room leverages several services from UGS to ease connectivity between players. To use these services inside your project, you need to [create an organization](https://support.unity.com/hc/en-us/articles/208592876-How-do-I-create-a-new-Organization-) inside the Unity Dashboard, which will provide you with access to the [Relay](https://docs.unity.com/relay/get-started.html) and [Lobby](https://docs.unity.com/lobby/game-lobby-sample.html) services.
+
+### Opening the project for the first time
+
+Once you have downloaded the project, follow the steps below to get up and running:
+
+1. Check that you have installed the most recent [LTS editor version](https://unity.com/releases/lts).
+ 1. Include standalone support for **Windows/Mac** in your Unity Editor installation.
+2. Add the project to the Unity Hub by selecting the **Add** button and pointing it to the root folder of the downloaded project.
+ 1. Unity imports all the project assets the first time you open the project, which takes longer than usual.
+3. Select the **Play** button. You can then host a new game or join an existing one using the in-game UI.
+
+### Exploring the project
+
+Boss Room is an eight-player co-op RPG game experience, where players collaborate to fight imps, and then a boss. Players can select between character classes that were designed to provide educational oriented implementations of characteristics commonly found in similar small-scale netcode games. Control model is click-to-move, with skills triggered by a mouse button or hotkey.
+
+One of the eight clients acts as the host/server. That client will use a compositional approach so that its entities have both server and client components.
+
+* The game is server-authoritative, with latency-masking animations.
+* Position updates are carried out through NetworkTransform that sync position and rotation.
+* Code is organized in domain-based assemblies.
+
+### Testing multiplayer
+
+To see the multiplayer functionality in action, you can:
+
+* Connect with a friend over your local area network
+* Connect with a friend over the internet
+ * You can use UGS which helps remove the complexities of handling port forwarding
+ * Otherwise, the host will need to setup port forwarding on their router
+
+See [Testing multiplayer games locally](../../tutorials/testing/testing_locally.md) for more information.
+
+#### Local multiplayer setup
+
+First, build an executable by selecting **File** > **Build Settings** > **Build**.
+
+After you have the build, you can launch several instances of the build executable to host or join a game.
+
+If you run several instances locally, you must use the **Change Profile** button to set different profiles for each instance for authentication purposes.
+
+:::note
+**Note**: If you're using Mac to run multiple instances of the same app, you need to use the command line. Run `open -n BossRoom.app`.
+:::
+
+#### Multiplayer over Internet
+
+Use the following instructions to test Boss Room with multiple players over the Internet.
+
+First, build an executable and distribute it to all players.
+
+:::tip
+**Tip**: it's possible to connect between multiple instances of the same executable OR between executables and the Unity Editor that you used to create the executable.
+:::
+
+Next, you need to set up a relay. Running the Boss Room over the internet currently requires setting up a relay:
+
+* Boss Room provides an integration with [Unity Relay](../../relay/relay.md). You can find our Unity Relay setup guide [here](../../relay/relay.md).
+* Alternatively you can use Port Forwarding. The [https://portforward.com/](https://portforward.com/) site has guides on how to enable port forwarding on a huge number of routers.
+* Boss Room uses `UDP` and needs a `9998` external port to be open.
+* Make sure your host's address listens on 0.0.0.0 (127.0.0.1 is for local development only).
+
+### Index of resources
+
+The Boss Room sample includes resources for gameplay, game flow, connectivity, Unity services, and other tools and utilities.
+
+#### Gameplay
+
+Boss Room includes the following gameplay resources:
+
+* Action anticipation - AnticipateActionClient() in [Assets/Scripts/Gameplay/Action/Action.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/Action.cs)
+* Object spawning for long actions (archer arrow) - LaunchProjectile() in [Assets/Scripts/Gameplay/Action/ConcreteActions/LaunchProjectileAction.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/LaunchProjectileAction.cs)
+* Quick actions with RPCs (ex: mage bolt) - [Assets/Scripts/Gameplay/Action/ConcreteActions/FXProjectileTargetedAction.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/FXProjectileTargetedAction.cs)
+* Teleport - [Assets/Scripts/Gameplay/Action/ConcreteActions/DashAttackAction.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/DashAttackAction.cs)
+* Client side input tracking before an action (archer AOE) - OnStartClient() in [Assets/Scripts/Gameplay/Action/ConcreteActions/AOEAction.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/AOEAction.cs)
+* Time based action (charged shot) - [Assets/Scripts/Gameplay/Action/ConcreteActions/ChargedLaunchProjectileAction.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/ChargedLaunchProjectileAction.cs)
+* Object parenting to animation - [Assets/Scripts/Gameplay/Action/ConcreteActions/PickUpAction.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/PickUpAction.cs)
+* Physics object throwing (using NetworkRigidbody) - [Assets/Scripts/Gameplay/Action/ConcreteActions/TossAction.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/TossAction.cs)
+* NetworkAnimator usage - All actions, in particular [Assets/Scripts/Gameplay/Action/ConcreteActions/ChargedShieldAction.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/ChargedShieldAction.cs)
+* NetworkTransform local space - [Assets/Scripts/Gameplay/GameplayObjects/ServerDisplacerOnParentChange.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/ServerDisplacerOnParentChange.cs)
+* Dynamic imp spawning with portals - [Assets/Scripts/Gameplay/GameplayObjects/ServerWaveSpawner.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/ServerWaveSpawner.cs)
+* In scene placed dynamic objects (imps) - [Packages/com.unity.multiplayer.samples.coop/Utilities/Net/NetworkObjectSpawner.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/NetworkObjectSpawner.cs)
+* Static objects (non-destroyables like doors, switches, etc) - [Assets/Scripts/Gameplay/GameplayObjects/SwitchedDoor.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/SwitchedDoor.cs)
+* State tracking with breakables, switch, doors
+ * [Assets/Scripts/Gameplay/GameplayObjects/Breakable.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/Breakable.cs)
+ * [Assets/Scripts/Gameplay/GameplayObjects/FloorSwitch.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/FloorSwitch.cs)
+ * [Assets/Scripts/Gameplay/GameplayObjects/SwitchedDoor.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/SwitchedDoor.cs)
+* NetworkVariable with Enum - [Assets/Scripts/Gameplay/GameState/NetworkPostGame.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameState/NetworkPostGame.cs)
+* NetworkVariable with custom serialization (GUID) - [Assets/Scripts/Infrastructure/NetworkGuid.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkGuid.cs)
+* NetworkVariable with fixed string - [Assets/Scripts/Utils/NetworkNameState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Utils/NetworkNameState.cs)
+* NetworkList with custom serialization (LobbyPlayerState) - [Assets/Scripts/Gameplay/GameState/NetworkCharSelection.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameState/NetworkCharSelection.cs)
+* Persistent player (over multiple scenes) - [Assets/Scripts/Gameplay/GameplayObjects/PersistentPlayer.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/PersistentPlayer.cs)
+* Character logic (including player's avatar) - [Assets/Scripts/Gameplay/GameplayObjects/Character/ \
+Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/Character)
+* Character movements - [Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacterMovement.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacterMovement.cs)
+* Client driven movements - Boss Room is server driven with anticipation animation. See [Client Driven bitesize](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/tree/v2.1.0/Basic/ClientDriven) for client driven gameplay
+* Player spawn - SpawnPlayer() in [Assets/Scripts/Gameplay/GameState/ServerBossRoomState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameState/ServerBossRoomState.cs)
+
+#### Game flow
+
+Boss Room includes the following game flow resources:
+
+* Application Controller - [Assets/Scripts/ApplicationLifecycle/ApplicationController.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ApplicationLifecycle/ApplicationController.cs)
+* Game flow state machine - All child classes in [Assets/Scripts/Gameplay/GameState/GameStateBehaviour.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameState/GameStateBehaviour.cs)
+* Scene loading and progress sharing - [ackages/com.unity.multiplayer.samples.coop/Utilities/SceneManagement/](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/SceneManagement)
+* Synced UI with character select - [Assets/Scripts/Gameplay/GameState/ClientCharSelectState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameState/ClientCharSelectState.cs)
+* In-game lobby (character selection) - [Assets/Scripts/Gameplay/GameState/NetworkCharSelection.cs \
+Assets/Scripts/Gameplay/GameState/ServerCharSelectState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameState/NetworkCharSelection.cs)
+* Win state - [Assets/Scripts/Gameplay/GameState/PersistentGameState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameState/PersistentGameState.cs)
+
+#### Connectivity
+
+Boss Room includes the following connectivity resources:
+
+* Connection approval return value with custom messaging - WaitToDenyApproval() in [Assets/Scripts/ConnectionManagement/ConnectionState/HostingState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ConnectionManagement/ConnectionState/HostingState.cs)
+* Connection state machine - [Assets/Scripts/ConnectionManagement/ConnectionManager.cs \
+Assets/Scripts/ConnectionManagement/ConnectionState/](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ConnectionManagement/ConnectionManager.cs)
+* Session manager - [Packages/com.unity.multiplayer.samples.coop/Utilities/Net/SessionManager.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/SessionManager.cs)
+* RTT stats - [Assets/Scripts/Utils/NetworkOverlay/NetworkStats.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Utils/NetworkOverlay/NetworkStats.cs)
+
+#### Services
+
+Boss Room supports integration with Lobby, Relay, and Authentication (UAS). Boss Room includes the following service resources:
+
+* Lobby and relay - host creation - CreateLobbyRequest() in [Assets/Scripts/Gameplay/UI/Lobby/LobbyUIMediator.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/UI/Lobby/LobbyUIMediator.cs)
+* Lobby and relay - client join - JoinLobbyRequest() in [Assets/Scripts/Gameplay/UI/Lobby/LobbyUIMediator.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/UI/Lobby/LobbyUIMediator.cs)
+* Relay Join - StartClientLobby() in [Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs)
+* Relay Create - StartHostLobby() in [Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs)
+* Authentication - EnsurePlayerIsAuthorized() in [Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/UnityServices/Auth/AuthenticationServiceFacade.cs)
+
+#### Tools and utilities
+
+Boss Room includes the following tools and utilities:
+
+* Networked message channel (inter-class and networked messaging) - [Assets/Scripts/Infrastructure/PubSub/NetworkedMessageChannel.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/PubSub/NetworkedMessageChannel.cs)
+* Simple interpolation - [Assets/Scripts/Utils/PositionLerper.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Utils/PositionLerper.cs)
+* Network Object Pooling - [Assets/Scripts/Infrastructure/NetworkObjectPool.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkObjectPool.cs)
+* NetworkGuid - [Assets/Scripts/Infrastructure/NetworkGuid.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Infrastructure/NetworkGuid.cs)
+* Netcode hooks - [Packages/com.unity.multiplayer.samples.coop/Utilities/Net/NetcodeHooks.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/NetcodeHooks.cs)
+* Spawner for in-scene objects - [Packages/com.unity.multiplayer.samples.coop/Utilities/Net/NetworkObjectSpawner.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/NetworkObjectSpawner.cs)
+* Session manager for reconnection - [Packages/com.unity.multiplayer.samples.coop/Utilities/Net/SessionManager.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/SessionManager.cs)
+* Relay utils - [Packages/com.unity.multiplayer.samples.coop/Utilities/Net/UnityRelayUtilities.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/UnityRelayUtilities.cs)
+* Client authority - [Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs)
+* Scene utils with synced loading screens - [Packages/com.unity.multiplayer.samples.coop/Utilities/SceneManagement/](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/SceneManagement)
+* RNSM custom config - [Packages/com.unity.multiplayer.samples.coop/Utilities/Net/RNSM/CustomNetStatsMonitorConfiguration.asset](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/RNSM/CustomNetStatsMonitorConfiguration.asset)
+* NetworkSimulator usage through UI - [Assets/Scripts/Utils/NetworkSimulatorUIMediator.cs ](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Utils/NetworkSimulatorUIMediator.cs)
+* ParrelSync - [Packages/manifest.json](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/manifest.json)
+
+### Troubleshooting
+
+#### Bugs
+
+- Report bugs in Boss Room using Github [issues](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/issues)
+- Report Netcode for GameObjects bugs using Netcode for GameObjects Github [issues](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/issues)
+- Report Unity bugs using the [Unity bug submission process](https://unity3d.com/unity/qa/bug-reporting).
+
+### Licence
+
+Boss Room is licenced under the Unity Companion Licence. See [LICENSE.md](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/LICENSE.md) for more legal information.
+
+Visit the following links to learn more about Unity Netcode and Boss Room.
+
+* [About Netcode for GameObjects](../../about.md)
+* [Boss Room Actions Walkthrough](bossroom-actions.md)
+* [NetworkObject Parenting inside Boss Room](networkobject-parenting.md)
+* [NetworkRigidbody inside Boss Room](networkrigidbody.md)
+* [Dynamically spawning NetworkObject in Boss Room](spawn-networkobjects.md)
+
+### Other samples
+
+The [Bitesize Samples](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize) repository is currently being expanded and has a collection of smaller samples and games showcasing sub-features of Netcode for GameObjects. You can review these samples with documentation to better understand our APIs and features.
+
+### Contributing
+
+Please check out [CONTRIBUTING.md](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0p/CONTRIBUTING.md) for full guidelines on submitting issues and PRs to Boss Room.
+
+Our projects use the `git-flow` branching strategy:
+
+* The `develop` branch has all active development.
+* The `main` branch has release versions.
+
+To get the project on your machine, you need to clone the repository from GitHub using the following command-line command:
+
+```bash
+git clone https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git
+```
+
+:::danger
+**Important**: You should have [Git LFS](https://git-lfs.github.com/) installed on your local machine.
+:::
+
+Please check out [CONTRIBUTING.md](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/CONTRIBUTING.md) for guidelines on submitting issues and PRs to Boss Room!
+
+### Feedback form
+
+Thank you for cloning Boss Room and taking a look at the project. To help us improve and build better samples in the future, please consider submitting feedback about your experiences with Boss Room. It'll only take a couple of minutes. Thanks!
+
+[Enter the Boss Room Feedback Form](https://unitytech.typeform.com/bossroom)
diff --git a/versioned_docs/version-2.0.0/learn/bossroom/networkobject-parenting.md b/versioned_docs/version-2.0.0/learn/bossroom/networkobject-parenting.md
new file mode 100644
index 000000000..687a19aec
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bossroom/networkobject-parenting.md
@@ -0,0 +1,23 @@
+---
+id: networkobject-parenting
+title: NetworkObject parenting inside Boss Room
+description: Learn about Boss Room's approach to NetworkObject parenting.
+---
+:::note
+Required reading: [NetworkObject Parenting](../../advanced-topics/networkobject-parenting.md)
+:::
+
+Before detailing Boss Room's approach to NetworkObject parenting, it's important to highlight a limitation of Netcode: A dynamically-spawned NetworkObject **can't** contain another NetworkObject in its hierarchy. If you spawn such a NetworkObject, you can't spawn children `NetworkObjects`. You can only add children NetworkObject components to a NetworkObject that is part of a scene.
+
+Boss Room leverages NetworkObject parenting through the server-driven `PickUp` action (see [`PickUpAction.cs`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/PickUpAction.cs)), where a character has the ability to pick up a specially-tagged, in-scene placed NetworkObject (see [`PickUpPot` prefab](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Prefabs/Game/PickUpPot.prefab)].
+
+At its root, `PickUpPot` has a NetworkObject, a `NetworkTransform`, and a `PositionConstraint` component. `AutoObjectParentSync` is enabled on its `NetworkTransform` (as is by default) so that:
+
+1. The NetworkObject can verify server-side if parenting a Heavy object to another NetworkObject is allowed.
+2. The NetworkObject can notify us when the parent has successfully been modified server-side.
+
+To accommodate the limitation highlighted at the beginning of this document, Boss Room leverages the `PositionConstraint` component to simulate an object following a character's position.
+
+A special hand bone has been added to our Character's avatar. Upon a character's successful parenting attempt, this special bone is set as the `PickUpPot`'s `PositonConstraint` target. So while the `PickUpPot` is technically parented to a player, the `PositionConstraint` component allows the `PickUpPot` to follow a bone's position, presenting the **illusion** that the `PickUpPot` is parented to the player's hand bone itself.
+
+Once the `PickUpPot` is parented, local space simulation is enabled on its [`NetworkTransform` component](../../components/networktransform.md).
diff --git a/versioned_docs/version-2.0.0/learn/bossroom/networkrigidbody.md b/versioned_docs/version-2.0.0/learn/bossroom/networkrigidbody.md
new file mode 100644
index 000000000..7c179052c
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bossroom/networkrigidbody.md
@@ -0,0 +1,12 @@
+---
+id: networkrigidbody
+title: NetworkRigidbody inside Boss Room
+description: Learn how Boss Room leverages NetworkRigidbody.
+---
+:::note
+Required reading: [Physics](../..//advanced-topics/physics.md)
+:::
+
+Boss Room leverages `NetworkRigidbody` to simulate physics-based projectiles. See the Vandal Imp's tossed projectile, the [`ImpTossedItem` prefab](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Prefabs/Game/ImpTossedItem.prefab). At its root, this Prefab has a NetworkObject, a `NetworkTransform`, a `Rigidbody`, and a `NetworkRigidbody` component. Refer to [`TossAction.cs`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/TossAction.cs) for more implementation details.
+
+An important note: You must do any modifications to a `Rigidbody` that involve Physics (modifying velocity, applying forces, applying torque, and the like) **after** the NetworkObject spawns since `NetworkRigidbody` forces the `Rigidbody`'s `isKinematic` flag to be true on `Awake()`. Once spawned, this flag is modified depending on the ownership status of the NetworkObject.
diff --git a/versioned_docs/version-2.0.0/learn/bossroom/optimizing-bossroom.md b/versioned_docs/version-2.0.0/learn/bossroom/optimizing-bossroom.md
new file mode 100644
index 000000000..695fd9771
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bossroom/optimizing-bossroom.md
@@ -0,0 +1,189 @@
+---
+id: optimizing-bossroom
+title: Optimizing Boss Room performance
+description: Learn how Boss Room optimizes performance.
+---
+
+Optimization is critical for networked and non-networked games. However, you have more limitations and constraints to consider when building a networked game. For example, networked games must account for latency, packet loss, reliability, and bandwidth limitations.
+
+One of the more critical optimizations of a networked game is how much bandwidth it consumes. The following issues can occur with networked games that have high bandwidth usage:
+
+* The game instance drops packets, which can occur at the transport or NIC (network interface card) layers
+* Latency induced discrepancies between players depend upon their network capabilities.
+ * A player with a latent and/or lower bandwidth capable connection can often lead to a less than nominal experience than players with a low latency and/or higher bandwidth capable connections.
+
+As such, a good optimization goal for a netcode enabled game is to keep the bandwidth consumption reduced where possible. Netcode enabled games that have been optimized for bandwidth usage can help deliver a smoother player experience and reduce the overall network requirements for both servers and clients.
+
+The following sections cover a handful of the most impactful optimization techniques used in the Boss Room sample, including
+
+* [RPCs vs. NetworkVariables](#rpcs-vs-networkvariables)
+* [NetworkTransform configuration](#networktransform-configuration)
+* [Pooling](#pooling)
+* [Unity Transport properties configuration](#utp-properties-configuration)
+* [NetworkManager tick rate tweaking](#utp-properties-configuration)
+
+## RPCs vs. NetworkVariables {#rpcs-vs-networkvariables}
+
+Remote procedure calls (RPCs) and networked variables are the two primary ways to synchronize data between the server and clients. See [RPCs vs. NetworkVariable](../../learn/rpcvnetvar.md) to learn more about the differences between these two approaches.
+
+You can optimize bandwidth usage by carefully deciding when to use RPCs versus NetworkVariables. As a general rule, you should:
+
+* Use RPCs for temporary events with information that's only useful for a moment (when it's first received).
+* Use NetworkVariables for persistent states with information that's useful for more extended periods (for example, long-term state syncing).
+
+RPCs require less bandwidth than NetworkVariables, so using RPCs for temporary events for which the client doesn't need to subscribe to updates saves bandwidth.
+
+For example, consider the Archer's and the Mage's attacks. The Archer's projectile is a slow, aimed attack that takes time to reach its target and only registers a hit when colliding with another character or object. In this case, creating a NetworkObject for the Archer's projectile and replicating its position with a NetworkTransform component (which uses NetworkVariables internally) makes sense to ensure the arrow stays in sync over multiple seconds.
+
+However, the Mage's projectile is much faster and always seeks its target to hit it. In the case of the Mage's projectile, it does not matter if all clients see the projectile in the same place simultaneously; they only need to see it launch and hit its target. As a result, you can save bandwidth by using an RPC to trigger the creation of the visual effect on the clients and have each client interpret that event without data from the server. In this case, the server only needs to send data when the Mage triggers the ability instead of spawning a new NetworkObject that has the visual effects (VFX) and synchronizing the motion of the VFX as it heads towards its target over each network tick.
+
+For more examples, see [RPCs vs. NetworkVariables Examples](../../learn/rpcnetvarexamples.md).
+
+## NetworkTransform configuration {#networktransform-configuration}
+
+The NetworkTransform component handles the synchronization of a NetworkObject's Transform. By default, the NetworkTransform component synchronizes every part of the transform at every tick if a change bigger than the specified [threshold](../../components/networktransform.md) occurs. However, you can configure it to only synchronize the necessary data by omitting particular axeis of the position, rotation, or scale vectors. See [Restricting synchronization](../../components/networktransform.md).
+
+You can also increase the thresholds to reduce the frequency of updates if you don't mind reducing the accuracy and responsiveness of the replicated Transform.
+
+Before optimization, the Boss Room sample contained a lot of unnecessary data. This is due to NetworkTransform synchronizing every axis' position, rotation, and scale information by default. So, we restricted every NetworkTransform only to synchronize the required data to reduce bandwidth usage.
+
+Since the characters evolve on a plane, we only synchronize their position's x and z components and their rotation about the y-axis.
+
+Additionally, with the changes introduced in [Netcode for GameObjects v1.4.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.4.0), we were able to further reduce the bandwidth cost associated for some prefabs that utilized NetworkTransform. The synchronization payload was reduced by 5 bytes for the Character and the Arrow prefab inside Boss Room, for example, by enabling "Use Half Float Precision" on their respective NetworkTransforms.
+
+See [NetworkTransform](../../components/networktransform.md) for more information on the NetworkTransform component.
+
+## Pooling {#pooling}
+
+Object pooling is a creational design pattern that pre-instantiates all required objects before gameplay. It removes the need to create new objects or destroy old ones while the game runs. It creates a set amount of GameObjects before the game's runtime and inactivates or activates the required GameObjects, effectively recycling the GameObject and never destroying it.
+
+You can use object pooling to optimize both networked and non-networked games by lowering the burden placed on the CPU and reudcing expensive memory allocations by pooling GameObjects before gameplay starts instead of having to rapidly create and destroy them.
+
+See [Object pooling](../../advanced-topics/object-pooling.md).
+
+## Unity Transport properties configuration {#utp-properties-configuration}
+
+The [Unity Transport package](../../../transport/about.md) has properties you can configure to meet a game's needs. You can find these properties in the Inspector of the UnityTransport script.
+
+The Boss Room sample shows how to adapt some Unity Transport properties to fit its specific requirements. Most of the Unity Transport property configuration remains unchanged. However, we changed the following property values:
+
+* [Disconnect Timeout](#disconnect-timeout)
+* [Max Connect Attempts](#max-connect-attempts)
+* [Connect Timeout](#connect-timeout)
+* [Max Packet Queue Size](#max-packet-queue-size)
+
+### Disconnect Timeout {#disconnect-timeout}
+
+The [Disconnect Timeout property](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.Transports.UTP.UnityTransport.html#Unity_Netcode_Transports_UTP_UnityTransport_DisconnectTimeoutMS) controls how long the server (and the clients) wait before disconnecting. The Boss Room sample uses a Disconnect Timeout value of 10 seconds to prevent the server and the clients from hanging onto a connection for too long.
+
+### Max Connect Attempts {#max-connect-attempts}
+
+The [Max Connect Attempts property](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.Transports.UTP.UnityTransport.html#Unity_Netcode_Transports_UTP_UnityTransport_MaxConnectAttempts) controls the times a client tries to connect before declaring a connection failure. The Boss Room sample uses a Max Connect Attempts value of 10 to prevent clients from waiting too long before declaring a connection failure.
+
+### Connect Timeout {#connect-timeout}
+
+The [Connect Timeout property](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.Transports.UTP.UnityTransport.html#Unity_Netcode_Transports_UTP_UnityTransport_ConnectTimeoutMS) controls the number of times clients attempt to connect per second. The Boss Room sample uses a Connect Timeout value of 1 second, meaning that clients try to connect once per second. Having the Connect Timeout set to 1 second and the Max Connect Attempts set to 10 means that clients fail to connect after 10 seconds of waiting.
+
+### Max Packet Queue Size {#max-packet-queue-size}
+
+The [Max Packet Queue Size property](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.Transports.UTP.UnityTransport.html#Unity_Netcode_Transports_UTP_UnityTransport_MaxPacketQueueSize) defines the maximum number of packets that can be sent and received during a single frame.
+
+The impact of surpassing the Max Packet Queue Size threshold varies depending on the packet direction (sending or receiving).
+
+* If a client or the server tries to **send** more packets than the Max Packet Queue Size value during a single frame, Unity Transport buffers the extra packets inside a send queue until the next frame update.
+* If a client or the server **receives** more packets than the Max Packet Queue Size value during a single frame, the operating system buffers the extra packets.
+
+Setting the Max Packet Queue Size parameter too low can introduce some [jitter](../../learn/lagandpacketloss.md) during frames where the number of packets sent or received is too high. On the other hand, setting the Max Packet Queue Size parameter too high would use more memory than necessary.
+
+:::note
+**Note**: Each unit in the Max Packet Queue Size parameter uses roughly 4 KB of memory. This value is based on twice the maximum size of a packet, which Unity Transport defines internally (it isn't exposed to Netcode users since this parameter governs the sizes of both the send and receive queues).
+:::
+
+The Boss Room sample uses a Max Packet Queue Size property value of 256. The reasoning behind choosing 256 is specific to how Boss Room uses Unity Transport.
+
+In the Boss Room sample, we found that the Max Packet Queue Size default value was too low, so we increased it. However, it didn't make sense to increase the Max Packet Queue Size too much because Boss Room only uses reliable channels for its NetworkVariable updates, RPCs, and custom messages. Reliable channels only support 32 in-flight packets per connection.
+
+As a result, the maximum number of reliable packets sent or received in a single frame is the number of players (minus the host) multiplied by 32 (the maximum number of in-flight packets). For example, a game of eight players would have a maximum of 224 (seven times 32) reliable in-flight packets. To allow some leeway for the internal traffic from Unity Transport itself (such as resend/ACKs of reliable packets and heartbeats), we chose a slightly higher value of 256.
+
+## NetworkManager tick rate configuration {#networkmanager-tick-rate-configuration}
+
+Netcode's [NetworkManager](../../components/networkmanager.md) provides some configuration options, one of which is the [tick rate](../../advanced-topics/networktime-ticks.md). The tick rate configuration option determines the frequency at which network ticks occur. The ideal tick rate value relies on balancing smoothness, accuracy, and bandwidth usage.
+
+Lowering the tick rate reduces the frequency of NetworkVariable update messages (because they're sent at each tick). However, since it reduces the frequency of updates, it also reduces the smoothness of gameplay for the clients. You can reduce the impact of lower tick rates by using interpolation to provide smoothness, such as in the NetworkTransform. However, because there are fewer updates, the interpolation will be less accurate because it has less information.
+
+In the Boss Room sample, we found an ideal tick rate value by manually testing different values using the same scenarios. To define the scenarios, we looked at where we used NetworkVariables and which most often needed to be updated to provide smooth gameplay. We identified NetworkTransforms as the most sensitive use of NetworkVariables, so we defined our scenarios around players moving, launching arrows, and tossing items. We compared video captures of these scenarios and determined that the smallest tick rate value that gave clients smooth and accurate gameplay was 30 ticks per second.
+
+## Further potential optimizations {#further-potential-optimizations}
+
+Even with all the optimizations above, it's possible to further reduce the bandwidth requirements of the Boss Room sample with additional optimizations.
+
+As a vertical slice of a small-scale co-op game, the bandwidth usage of the Boss Room sample is already pretty low. Still, the following techniques can reduce it further or improve other performance considerations, such as responsiveness.
+
+### Unreliable RPCs vs. reliable RPCs {#unreliable-rpcs-vs-reliable-rpcs}
+
+You can use unreliable RPCs when possible instead of only using reliable RPCs. The Boss Room sample uses only reliable messages for RPCs, which means that if a client doesn't receive an RPC sent by the server, the server will resend it until the client receives and acknowledges it (and vice versa).
+
+Reliable messages aren't necessary for all RPCs, though. For example, it wouldn't pose that much of an issue if a client (having network issues) doesn't receive the RPC triggering the visual effect of a single Imp's attack. This is because the client would receive the impact of the Imp's attack (such as position updates and hit points) after recovering from the issue. As a result, there's no need to slow down the server and, by extension, the whole game to ensure that this client properly receives this specific message. An unreliable RPC would increase the game's responsiveness without much downside in such a case.
+
+### Sent data size {#sent-data-size}
+
+You can reduce the size of sent data by using smaller primitive types or encoding values into bits and bytes.
+
+One method of encoding values into smaller primitive types is quantization. Quantization involves mapping input values from a large set to output values in a smaller set. Common examples of quantization include rounding and truncating.
+
+Take the following example. It shows how quantization can considerably reduce bandwidth in scenarios where high precision isn't essential.
+
+Let's say you're designing a game where you have positional values between 0 and 1000, and you don't need values more precise than a decimeter. Positional values typically use 3x32 bits (for the three floats that comprise a Vector3). However, since, in your game, precision isn't essential past the size of a decimeter, you can serialize the positional values by multiplying by 10, then only encode the integer part of the product. Doing so gives you the precision you need with fewer bits. Instead of 32 bits per axis, you use 14, which means that the total number of bits you need is 48 instead of the usual 96. When you receive the data, you can deserialize it by dividing the value by 10 to obtain the float value.
+
+See [Quantization](https://en.wikipedia.org/wiki/Quantization_(signal_processing)) and [Snapshot compression](https://gafferongames.com/post/snapshot_compression/#optimizing-position).
+
+### Pathfinding optimizations {#pathfinding-optimizations}
+
+There are multiple ways to implement pathfinding in a networked game, each with tradeoffs between bandwidth usage, CPU costs, determinism, and position synchronization. The most common pathfinding techniques include:
+
+* [Calculating the paths and moving everything on the server.](#technique-1)
+* [Calculating the paths on the server, then sending them to the clients.](#technique-1)
+* [Calculating the paths on the client and sending the movement directions to the server.](#technique-1)
+
+#### Calculating the paths and moving everything on the server {#technique-1}
+
+The first technique involves calculating the paths, moving everything on the server, then synchronizing the positions with the clients. This technique is easy to implement and ensures that clients have the latest positions. However, it relies on sending position updates every frame, which uses a lot of bandwidth and doesn't scale well if a game has many characters moving around.
+
+| PROS | CONS |
+|--------------------------------------------|-------------------------------------------------|
+| Easy to implement | Uses a lot of bandwidth |
+| Ensures clients have the latest positions | Doesn't scale well with many moving characters |
+
+#### Calculating the paths on the server, then sending them to the clients {#technique-2}
+
+The second technique involves calculating the paths on the server, then sending the paths to the clients and allowing them to simulate the movements themselves. It works for both deterministic and non-deterministic pathfinding by sending key position updates. Calculating the paths on the server reduces bandwidth usage, but implementing this technique involves a lot of hidden complexity.
+
+An issue with this technique is that, since clients receive the whole paths of characters, it can lead to cheating because clients know where other players will be in the future. Clients knowing the future position of other players can introduce a big issue in competitive games like MOBA multiplayer online battle arena (MOBA) and real-time strategy (RTS) games.
+
+| PROS | CONS |
+|-----------------------------------------------------------------|----------------------------------------------------------------------------------------|
+| Reduces bandwidth usage | Implementation involves a lot of hidden complexity |
+| Works for both deterministic and non-deterministic pathfinding | Increases the likelihood of cheating by knowing the future positions of other players |
+
+A variant of this technique is to send only the destination and let the clients calculate the paths (instead of sending the whole paths). Offloading path calculation to the clients saves even more bandwidth but adds CPU costs to clients and makes determinism more difficult.
+
+#### Calculating the paths on the client and sending the movement directions to the server {#technique-3}
+
+The third technique involves calculating the paths on the clients, then sending the movement directions to the server. After receiving the client movement directions, the server synchronizes the positions across the clients. This technique is easy to implement and saves server CPU usage but uses much more bandwidth for constant synchronization. It also only works for player-controlled entities.
+
+| PROS | CONS |
+|---------------------------|--------------------------------------------|
+| Easy to implement | Increases bandwidth usage |
+| Reduces server CPU usage | Only works for player-controlled entities |
+
+#### Pathfinding in Boss Room {#pathfinding-in-boss-room}
+
+The Boss Room sample uses the first technique: it calculates the paths and moves everything on the server to keep the positions synchronized with the clients. This technique works well with the Boss Room sample because it doesn't have too many characters moving simultaneously.
+
+The second technique wasn't an option because some actions, like the Archer's attacks, require aiming. A position that can become desynchronized between a client and the server can negatively impact gameplay.
+
+The third technique wasn't ideal either because most of the entities in the Boss Room sample aren't player-controlled.
+
+## Dedicated game server (DGS) optimizations {#dgs-optimizations}
+
+See [DGS game changes](../../../tools/porting-to-dgs/game-changes.md) and [Optimizing server builds](../../../tools/porting-to-dgs/optimizing-server-builds.md).
diff --git a/versioned_docs/version-2.0.0/learn/bossroom/spawn-networkobjects.md b/versioned_docs/version-2.0.0/learn/bossroom/spawn-networkobjects.md
new file mode 100644
index 000000000..bd0a03e8f
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/bossroom/spawn-networkobjects.md
@@ -0,0 +1,27 @@
+---
+id: spawn-networkobjects
+title: Dynamically spawning NetworkObjects in Boss Room to resolve zombie NetworkObjects
+description: Learn how to dynamically spawn NetworkObjects in Boss Room to resolve zombie NetworkObjects.
+---
+:::note
+Required reading: [Object Spawning](../../basics/object-spawning.md).
+:::
+
+This document serves as a walkthrough of Boss Room's approach to solving the following issue: Late-joining clients entering networked sessions encountering zombie `NetworkObjects`. Zombie `NetworkObjects` represent `NetworkObjects` that are instantiated for a client due to scene loads but aren't despawned or destroyed by Netcode.
+
+This is a particular Netcode limitation of NetworkObject spawning: `NetworkObjects` that belong to a scene object should not be destroyed until its scene has been unloaded through Netcode's scene management.
+
+The scenario in question:
+
+* A host loads a scene and destroys a NetworkObject that belonged to that scene.
+* A client joins the host's session and loads the additive scene. This operation loads **all** the `GameObjects` included in the additive scene. The NetworkObject that was destroyed on the server won't be destroyed on the client's machine.
+
+This scenario manifested inside Boss Room, whereby late-joining clients joining a game session encountered zombie NetworkObjects that were not destroyed over the network.
+
+Additive scenes now contain Prefab instances of a custom spawner, [`NetworkObjectSpawner`](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/NetworkObjectSpawner.cs) to accommodate this visual inconsistency.
+
+Compositionally, these additive scenes now only contain the following:
+
+* Prefab instances of level geometry.
+* Prefab instances of NetworkObjects that will **not** be despawned nor destroyed for the scene's lifetime. Examples include [BreakablePot](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Prefabs/Game/BreakablePot.prefab) and [BreakableCrystal](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Prefabs/Game/BreakableCrystal.prefab).
+* Prefab instances of `NetworkObjectSpawner`, which spawn NetworkObjects that **may** be destroyed or despawned during the scene's lifetime. Examples include [Imp](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/GameData/Character/Imp/Imp.asset), [VandalImp](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/GameData/Character/VandalImp/VandalImp.asset), and [ImpBoss](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/GameData/Character/ImpBoss/ImpBoss.asset).
diff --git a/versioned_docs/version-2.0.0/learn/clientside-interpolation.md b/versioned_docs/version-2.0.0/learn/clientside-interpolation.md
new file mode 100644
index 000000000..5f1bc990d
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/clientside-interpolation.md
@@ -0,0 +1,29 @@
+---
+id: clientside_interpolation
+title: Improving performance with client-side interpolation
+---
+
+As outlined in [Understanding latency](lagandpacketloss.md), latency and jitter can negatively affect gameplay experience for users. In addition to managing [tick and update rates](tick-and-update-rates.md), you can also use client-side interpolation to improve perceived latency for users.
+
+## Without latency mitigation
+
+Without any kind of compensation for latency, the client performs two simple operations:
+
+* Sends inputs from the client to the server
+* Receives states from the server and renders them
+
+This is a conservative approach that never shows an incorrect user state, but exposes users directly to the effects of latency. Regardless of the client's potential frame rate, the game will only ever run at the speed the server (with its limiting [network factors](lagandpacketloss.md#network-latency)) is capable of, which can severely reduce frame rates and produce perceivable input lag. It also produces an uneven game speed, as jitter in the network causes states to arrive and be rendered at inconsistent intervals.
+
+In addition to reduced responsiveness, this approach can also directly interfere with gameplay in certain genres such as first-person shooters. Because the information from the server is always slightly behind, due to network latency, players are forced to aim ahead of their target to compensate.
+
+## With client-side interpolation
+
+When using client-side interpolation, all clients intentionally run slightly behind the server, giving them time to transition smoothly between state updates and conceal the effects of latency from users. To implement client-side interpolation, use the [NetworkTransform](../components/networktransform.md) component.
+
+In a standard client-server [topology](../terms-concepts/network-topologies.md), clients are able to render a state that's approximately half the [round-trip time (RTT)](lagandpacketloss.md#round-trip-time-and-pings) behind the server. When using client-side interpolation, a further intentional delay is added so that by the time the client is rendering state _n_, it's already received state _n+1_, which allows the client to always smoothly transition from one state to another. This is effectively increasing latency, but in a consistent, client-universal way that can be used to reduce the negative impacts of unpredictable network jitter on gameplay.
+
+The delay added to enable client-side interpolation is called the interpolation period, and should always be less than the interval the server waits between sending packets to clients, to avoid stutter.
+
+## Boss Room example
+
+In the [Boss Room sample](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/), NetworkTransform components are used for client-side interpolation. Since transforms are updated in FixedUpdate, however, there is also some server-side interpolation that is needed on the host to smooth out movement. See [PhysicsProjectile](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/Projectiles/PhysicsProjectile.cs) and [PositionLerper](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Utils/PositionLerper.cs) for an example of how it's done.
diff --git a/versioned_docs/version-2.0.0/learn/dealing-with-latency.md b/versioned_docs/version-2.0.0/learn/dealing-with-latency.md
new file mode 100644
index 000000000..67572e786
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/dealing-with-latency.md
@@ -0,0 +1,393 @@
+---
+id: dealing-with-latency
+title: Tricks and patterns to deal with latency
+sidebar_label: Dealing with Latency
+description: Tricks and patterns to hide latency, what's acceptable to manage client side with client authority before sending it to the server, prediction, server rewind, action anticipation, etc.
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+## TL;DR
+
+
+Issue to solve | How to solve it
+--- | ---
+Security | Server authority
+Responsiveness | Prediction, action casting, client authority
+Accuracy/consistency | server rewind, server authority
+
+
+---
+
+As mentioned in [latency](lagandpacketloss.md) and [tick](ticks-and-update-rates.md), waiting for your server's response makes your game feel unresponsive.
+
+Latency destroys your gameplay experience and makes your game frustrating. It doesn't take much to make a multiplayer game unplayable. Add 200ms between your inputs and what you see on your screen and you'll want to throw your computer through the window.
+
+
+
+Trying to deal with lag naively can introduce security and consistency issues. This page will help you get started with these techniques.
+
+:::info
+
+## Security
+
+Players can mess with any client-side code and do things such as forge false network messages sent to the server.
+
+Even if you specify in your client logic that you can't kill an Imp (for example) if it's more than 10 meters away, if the "kill Imp" message is a server RPC and there's no range check server-side, players can forge that network message to bypass your client-side logic. The ways a player might forge that kind of message is beyond the scope of this document, however, you should always keep in mind you can't trust clients. Your server must have logic to validate player actions coming from clients.
+
+
+
+## Consistency
+
+In addition to responsiveness, the accuracy of your simulation is important. Not only can it break your player's immersion, competitive games often have prize pools of multiple millions of dollars where you want to make sure when your user is targeting something on their screen, it actually hits.
+
+With latency, what a client receives from the server is RTT/2 ms late. The information available client-side isn't the "live" information, it's the information sent over the internet some time earlier (for example, 200ms ago). This means if a local player collides with a server-driven networked object, the player sees the Collider overlap with it before the server reacts and tells it to move.
+
+
+
+This also means if a player shoots a target's head, the shot targets a head that's RTT/2 ms behind and reaches the server RTT/2 ms later (meaning you have a full RTT ms of desynchronization between your shot and the actual hit). This means any interactions I'm making on that object will see a delayed effect.
+:::
+
+In summary, you want accuracy, security, and responsiveness for your game.
+
+## Authority
+
+### Server authoritative games
+
+The authority is who has the right to make final gameplay decisions over objects. A server authoritative game has all its final gameplay decisions executed by the server.
+
+
+
+
+
+#### Good for world consistency
+
+An advantage of server authoritative games is consistency. Since the server (a single node on the network) makes all gameplay decisions (such as a player opening a door or a bot shooting the player), you can be sure the decisions are made at the same time. A client authoritative game would have decisions made on client A and other decisions on client B, with both separated by RTT ms of Internet lag. Player A killing player B while player B was already hiding behind cover would cause consistency issues. Having all this gameplay logic on one single node (the server) makes these kinds of considerations irrelevant, since everything happens in the same execution context.
+
+
+
+#### Good for security
+
+Critical data (like your character health or position) can be **server authoritative**, so cheaters can't mess with it. In that instance, the server has the final say on that data's value. You wouldn't want players on their clients to set their health (or even worst, other player's health) at will.
+
+:::info
+Games that use the **Host** model still have this risk because one of the clients acts as a client and a server. Pure servers hosted by the game developer (dedicated servers) won't run into this issue.
+:::
+
+Netcode for GameObjects is server authoritative, which means it only allows the server to write to `NetworkVariable`s. However, when accepting RPCs coming from clients, you must add validation code, since those RPCs are coming from *never to be trusted* sources.
+
+Note here an input from a client can be anything, from a user interacting with another player to revive them, to a player sending keys and clicks for position changes.
+
+:::info
+The rest of the document assumes your game is server authoritative.
+:::
+
+#### Issue: Reactivity
+
+An issue with server authority is you're waiting for your server to tell you to update your world. This means that if you send an input to the server and wait for the server to tell you your position change, you'll need to wait for a full **RTT** before you see the effect. There are [patterns](#patterns-to-solve-these-issues) you can use to solve this issue while still remaining server authoritative.
+
+### Client authority
+
+In a **client authoritative** (or **client driven**) game using Netcode for GameObjects, you still have a server that's used to share world state, but clients will own and impose their reality.
+
+
+
+
+
+#### Good for reactivity
+
+You can often use this when you trust your users or their devices. For example, you might have a client tell the server "I killed player X" instead of "I clicked in that direction" and have the server simulate that action to return the result. This way, the client shows the death animation for the enemy as soon as the player clicks (since the death is already confirmed and owned by the client). The server would only relay that information back to other users.
+
+#### Issue: World consistency
+
+There are possible synchronizations issues with client authoritative games. If your character moves client-side thinking everything is okay and an enemy has stuns it in the meantime, that enemy will have stunned your character earlier on a different version of the world from the one you're seeing. See [latency page](lagandpacketloss.md). If you let the client make an authoritative decision using outdated information, you'll run into synchronization issues, overlapping physics objects, and similar issues.
+
+:::info
+
+#### Owner authority vs All clients authority
+
+Mltiple clients with the ability to affect the same shared object can quickly become a mess.
+
+
+
+To avoid this, it's recommended to use client **owner** authority, which allows only the owner of an object to interact with it. Since the server controls ownership in Netcode, there's no possibility of two clients running into a [race condition](https://en.wikipedia.org/wiki/Race_condition#In_software). To allow two clients to affect the same object, you must ask the server for ownership, wait for it, then execute the client authoritative logic you want.
+
+
+:::
+
+#### Issue: Security
+
+Client authority is a pretty dangerous door to leave open on your server because any malicious player can forge messages to say "kill player a, b, c, d, e, f, g" and win the game. It's pretty useful though for reactivity. Since the client is making all the important gameplay decisions, it can display the result of user inputs as soon as they happen instead of waiting a few hundred milliseconds.
+
+When you don't think there's any reason for your players to cheat, client authority can be a great way to have reactivity without the complexity added with techniques like [input prediction](#prediction).
+
+
+
+Another way of solving this issue in a client authoritative game is using soft validation server side. Instead of doing all simulation server side, the server only does basic validation. The server would, for example, do range checks to make sure a player isn't teleporting to places it shouldn't. Doing so is acceptable for most [PvE](https://en.wikipedia.org/wiki/Player_versus_environment) games. However, [PvP](https://en.wikipedia.org/wiki/Player_versus_player) games usually require server authority.
+
+
+
+ Summary | -
+ --- | ---
+ Server authority | More secure. Less reactive. No sync issues.
+ Client authority | Less secure. More reactive. Possible sync issues.
+
+### Boss Room's authority
+
+
+
+Boss Room's [actions](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/tree/v2.1.0/Assets/BossRoom/Scripts/Server/Game/Action) uses a server authoritative model. The client sends inputs (mouse clicks for the character's destination) and the server sends back positions. This way, every features in the world are on the same world time. If the Boss charges and bumps you, you'll see your character fly away as soon as the boss touches you, not pass through you and then see you fly away.
+
+
+
+:::info
+The thought process behind the server authoritative nature of Boss Room is "server authoritative by default."
+:::
+
+While developing Boss Room, the team knew that everything is synced and secure by default, which made designing gameplay simpler. Boss Room then added reactive gameplay exceptions on a case-by-case basis (see the following sections on [patterns to solve latency issues](#patterns-to-solve-latency-issues-in-a-server-authoritative-game).
+
+Having only one source of truth makes debugging your game easier. You know you can trust the information you're seeing server-side is the "truth" and that the information relayed to clients is also the "truth" (since it comes from the server).
+
+
+
+Boss Room, being a coop game, it might have benefited from using client authority. However, players would have seen issues with syncing with the Boss charge, for example. The server driven Boss would charge your client driven client. Mixing authority with server driven AIs and client driven players can easily have become a mess.
+
+:::info
+Rule of thumb: A good way to think about your game architecture at first is to have your game server authoritative by default and make exceptions for reactivity when security and consistency allows it.
+:::
+
+:::info
+A pattern we've seen that helped when not sure about using client or server authority is to implement your game behaviour not by server/client, but authoritative/non-authoritative. By abstracting this to authority instead of isServer/isClient, your code can easily be swapped to client or server authority without too many refactors.
+
+```csharp
+// before
+if (isServer)
+{
+ // take an authoritative decision
+ // ...
+}
+if (isClient) // each of these need to be swapped if switching authority
+{
+ // ...
+}
+
+// after
+bool HasAuthority => isServer; // can be set for your whole class or even project
+// ...
+if (HasAuthority)
+{
+ // take an authoritative decision
+ // ...
+}
+if (!HasAuthority)
+{
+ // ...
+}
+```
+
+:::
+
+## Patterns to solve latency issues in a server authoritative game
+
+Summary |
+--- | ---
+Client authority | Less secure. More reactive. Possible sync issues.
+Action anticipation | More secure. Somewhat reactive. Possible visual sync issues.
+Prediction | More secure. More reactive. Correction on sync issues. Complex and tentacular.
+Server side rewind | More secure. More accurate by favoring the attacker. Shot behind a wall issue.
+
+### Allow low impact client authority
+
+When designing your feature, keep in mind using server authority as the default. Then identify which feature needs reactivity and doesn't have a big impact on security/world consistency.
+User inputs are usually a good example. Since users already own their inputs (I own my key press, the server can't tell me "no you haven't pressed the w key") user input data can easily be client driven. In FPS games, your look direction can easily be client driven without much impact. The client will send to the server its look direction instead of mouse movements. Having a correction on where you look would feel weird and security for this has challenges anyway (how do you differentiate an aim bot vs someone flicking their mouse super fast).
+
+
+
+
+
+If a player selects an imp, the selection circle will be client driven, it won't wait for the server to tell us we've selected the imp.
+
+
+
+[Click](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Input/ClientInputSender.cs) is client driven, [AOE selection](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/AoeActionInput.cs) is client driven. AOE's distance check is client driven. However the distance check is done [server side too](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/AOEAction.cs). This way if there's too much latency between a client click and the server side position, the server will do a sanity check to make sure that for its own state, the click is within the allowed range.
+
+
+
+:::note
+The above examples are atomic actions. They happen on click.
+To do continuous client driven actions, there's a few more considerations to take.
+
+- You need to keep a local variable to keep track of your client authoritative data.
+- You then need to make sure you don't send RPCs to the server (containing your authoritative state) when no data has changed and do dirty checks.
+- You'd need to send it on tick or at worst on FixedUpdate. Sending on Update() would spam your connection.
+
+A sample for a [ClientNetworkTransform](../components/networktransform.md#clientnetworktransform) has been created, so you don't have to reimplement this yourself for transform updates. A [sample](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/tree/main/Basic/ClientDriven) has been created on how to use it. See [movement script](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/blob/v1.2.1/Basic/ClientDriven/Assets/Scripts/ClientPlayerMove.cs).
+:::
+
+:::info
+A rule of thumb here is to ask yourself: "Can the server correct me on this?". If it can, use server authority.
+:::
+
+### Client Side Prediction
+
+Predicting what the server will send you.
+
+Prediction is a common way of making an educated "guess" as to what the server will send you. Your game can stay server authoritative, but instead of waiting a full RTT for your action results, your client can simulate and run gameplay code of what it thinks will happen as soon as your players trigger inputs. For example, instead of waiting a full RTT for the server to tell me where I moved, I can directly update my movements according to my inputs. This is close to client authority, except with this technique you can be corrected:
+
+The world (and especially the internet) is messy. A client can guess wrong. An event produced by another player can come and mess your own local guess or your physic simulation can be non-deterministic.
+
+With the movement example, I can have an enemy come and stun me while I thought I can still move. 200 ms latency is enough time for a stun to happen and create a discrepancy between the move I "predicted" client side and what happened server side. This is where "reconciliation" (or "correction") comes in play. The client keeps a history of the positions it predicted. Being still server authoritative, the client still receives (outdated by x ms of latency) positions coming from the server. The client will validate whether the positions it predicted in the past fits with the old positions coming from the server. The client can then detect discrepancies and "correct" its position according to the server's authoritative position.
+This way, clients can stay server authoritative while still be reactive.
+
+#### Input Prediction vs World Prediction vs Extrapolation
+
+Local input prediction will predict your state using your local player's inputs.
+
+You can also predict other objects in your world by predicting from the last server data your received.
+Knowing an AI's state at frame i, we can predict its state at time i+1 assuming it's deterministic enough to run the same both client side and server side.
+
+Extrapolation is an attempt to estimate a future game state, without taking into account latency. On receipt of a packet from the server, the position of an object is updated to the new position. Awaiting the next update, the next position is extrapolated based on the current position and the movement at the time of the update.
+
+The client will normally assume that a moving object will continue in the same direction. When a new packet is received, the position may be updated.
+
+For Netcode for gameobjects (Netcode), a basic extrapolation implementation has been provided in [`NetworkTransform`](../components/networktransform.md) and is estimated between the time a tick advances in server-side animation and the update of the frame on the client-side. The game object extrapolates the next frame's values based on the ratio.
+:::
+
+
+
+
+
+
+
+
+
+
+
+
+:::info
+While Netcode for GameObjects doesn't have a full implementation of client-side prediction and reconciliation, you can build such a system on top of the existing client-side anticipation building-blocks, `AnticipatedNetworkVariable` and `AnticipatedNetworkTransform`. These components allow differentiating between the "authoritative" value and the value that is shown to the players. These components provide most of the information needed to implement prediction, but do require you to implement certain aspects yourself. Because of the complexity inherent in building a full client prediction system, the details of that are left for users, and we recommend only advanced users pursue this option.
+
+For more information, refer to the [client anticipation](../advanced-topics/client-anticipation.md) documentation.
+
+:::
+
+### Controlled Desyncs
+
+It can be hard to handle misprediction corrections elegantly and without taking your players out of their immersion. Clients also can't always stay in sync tick by tick, frame by frame. You can adapt your gameplay and animations to allow your clients to desync for a few seconds, as long as they reach a common state and resync again to make corrections seamless. By using controlled desyncs, clients can resolve and reinterpret how they reach a common state independently based on their local context. You can consider this technique as a "smart context-aware interpolation" or an "elegant correction" when predicting. It reuses some of [action anticipation](#action-anticipation)'s technique where you use non-gameplay-important animations to hide discrepancies caused by lag and reinterpret how the client will reach the target authoritative state.
+
+For example, you could have an assassination mechanic that you want to seamlessly handle misprediction correction. You could have your client tell the server "I killed that target," have the server validate to prevent cheating (like with server rewind), and still give advantage to the attacker.
+
+In this example, _Alice the Assassin_ is chasing _Bob the Victim_. _Bob_ enters a room and quickly closes the door behind them at time _t=0_ seconds. Simultaneously at _t=0_, _Alice_ hits the **kill** button. Both actions are client-driven and reach the server at the same time, so the server would tell all clients "Alice killed Bob" at _t=0.1_. _Bob_ receives the "You got killed" message at _t=0.2_. However, _Bob_ locally closed their door at _t=0_, it would appear that _Alice_ killed _Bob_ through the door.
+
+One solution is to use server authoritative gameplay with prediction and correction on both clients as described in other sections on this page. The door is corrected by teleporting back open, and the killing animations would play as usual. That correction would remove your players from their immersion and frustrate _Bob_.
+
+Another solution is to use action anticipation on the door closing and have the door be server driven. You remove the correction and desync problems altogether. However, it still adds lag to each door opening and closing as an instant action without animation to hide the lag.
+
+For the best user experience, you can use controlled desyncs. You could add windows in your doors and reinterpret the kill action depending on local client state. _Alice_ could see a knife kill while the door is still open (they haven't received the "door closed" update from the server yet), and _Bob_ could see a gun kill through the window of the locally closed door instead. Ultimately, clients only care about the final "Bob is dead and killed by Alice" state. You let clients reinterpret how they reach that final state according to their own different local context.
+
+Some other examples include:
+- Physics based doors swinging in different direction based on local collision when there's contention
+- IK solving locally for your feet when walking on stairs
+- Death ragdolls where a dead character's body doesn't influence your gameplay anymore and can desync from one client to another. The server syncs all clients that "this character is now dead" and send it's death position. From that point, clients can apply ragdoll physics how they want without syncing between clients. Since they have no gameplay impact, it doesn't matter if the ragdoll is in a tree for one person and a ditch for another. Eventually, the players respawn or the ragdolls disappear, and your game state is in sync again.
+
+In each situation, you need to ensure the reinterpretation doesn't affect gameplay critical systems. In the first example, if the number of gun kills and knife kills are important to your player's stats, this solution might not be doable.
+
+There are situations when clients and servers need to be in constant sync. For example, high precision tactical shooters try to ensure the game is fair for both attackers and targets. Outside of those specific situations, controlled desyncs can maintain player immersion while dealing with lag. As long as the clients end in the same state and doesn't accumulate discrepencies, your players will be fooled. The goal is to give your players the _illusion_ they are playing in the same world, when they actually may not.
+
+### Action Anticipation
+
+There's multiple reasons for not having server authoritative gameplay code run both client side (with [prediction](#client-side-prediction)) and server side. For example, your simulation can be not deterministic enough to trust that the same action client side would happen the same server side. If I throw a grenade client side, I want to make sure the grenade's trajectory is the same server side. This often happens with world objects with a longer life duration, with greater chances of desyncing. In this case, the safest approach would be a server authoritative grenade, to make sure everyone has the same trajectory. But how do you make sure the throw feels responsive and that your client doesn't have to wait for a full RTT before seeing anything react to their input?
+
+For a lot of games, when triggering an action, you'll see an animation/VFX/sound trigger before the action is actually executed. A trick often used for lag hiding is to trigger a non-gameplay impacting animation/sound/VFX on player input (immediately), but still wait for the server authoritative gameplay elements to drive the rest of the action. If the server has a different state (your action was cancelled server side for some reason), the worst that happens client side is you've played a useless quick animation. It's easy to just let the animation finish or cancel it.
+
+This is referenced as action casting or action anticipation. You're "casting" your action client side while waiting for the server to send the gameplay information you need.
+
+
+
+For your grenade, a client side "arm throw" animation can run, but the client would wait for the grenade to be spawned by the server. With normal latencies, this usually feels responsive. With higher abnormal latencies, you can run into the arm animating and no grenade appearing yet, but it would still feel responsive to users. It would feel strange, but at least it would feel responsive and less frustrating.
+
+In Boss Room for example, our movements use a small "jump" animation as soon as you click somewhere to make your character move.
+The client then waits for the server to send position updates. The game still feels reactive, even though the character's movements are server driven.
+
+:::info
+For example, Boss Room plays an animation on [Melee action](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/MeleeActionFX.cs) client side while waiting for the server to confirm the swing. If the server doesn't confirm, worst comes to worst we've played an animation for nothing and nothing else is desynced. Your players will be none the wiser.
+:::
+
+This is also useful for any action that needs to interract with the world. An ability that makes you invulnerable would need to be on the same time as other server events. If I predict my invulnerability, but a sniper headshots me before my input has reached the server, I'll see my invulnerable animation, but will still get killed. This is pretty frustrating for users. Instead, I can play a "getting invulnerable" animation with the character playing an animation, wait for the server to tell me "you're invulnerable now" and then display my invulnerable status. This way, if a sniper shoots me, the client will receive both the sniper shot and the invulnerability messages on the same timeline, without any desync.
+
+
+
+:::info
+Top: player with zero artificial latency, doing a jump and moving almost instantly.
+Bottom: player with 1000ms RTT, doing the same. A jump (action anticipation) and moving when the server tells it too, a full RTT later.
+
+
+
+Players don't have to wait for their mouse movements to be synced for AOE. They're independant. The click will trigger a server RPC (you can see the added delay on the bottom video)
+
+
+:::
+
+Action anticipation can also be used to set the value of a network variable or network transform on the assumption that an action succeeds while waiting for the server to respond. This is the first building block of client-side prediction mentioned above, with the most simple form being to set a value and let the server overwrite it later. This is done in Netcode for GameObjects using `AnticipatedNetworkVariable` and `AnticipatedNetworkTransform`. For more information, refer to the [client anticipation](../advanced-topics/client-anticipation.md) documentation.
+
+### Server Side Rewind (also called Lag Compensation)
+
+Server rewind is a security check on a client driven feature to make sure we stay server authoritative. A common usecase is snipers.
+If I aim at an enemy, I'm actually aiming at a ghost representation of that enemy that's RTT/2 ms late. If I click its head, the input sent to the server will take another RTT/2 ms to get to the server. That's a full RTT to miss my shot and is frustrating.
+The solution for this is to use server rewind by "favoring the attacker". Psychology 101: it's way more frustrating for an attacker to always miss their shots than for a target to get shot behind a wall once in a while. The client sends along with its input a message telling the server "I have hit my target at time t". The server when receiving this at time t+RTT/2 will rewind its simulation at time t-RTT, validate the shot and correct the world at the latest time (ie kill the target). This allows for the player to feel like the world is consistent (my shots are hitting what they're supposed to hit) while still remaining secure and server authoritative.
+
+**Note**: the server rewind of the game's state is done all in the same frame, this is invisible to players.
+This is a server side check that allows validating a client telling you what to do.
+
+
+
+:::info
+There's no server side rewind implementation right now in Netcode for GameObjects, but you can implement your own. See our [roadmap](https://unity.com/roadmap/unity-platform/multiplayer-networking) for more information.
+:::
+
+**Other syncing techniques not relevant to Netcode for GameObjects**
+Deterministic lockstep/
+
+A method of networking a system from one computer to another by sending only the inputs that control that system, rather than the state of that system. This allows for a big amount of entities to be synced (think RTS with hundreds of units)
+
+Deterministic rollback/
+
+An enhancement of deterministic lockstep where clients forward-predict inputs while waiting for updates. This setup enables a more responsive game than lockstep. It's relatively inexpensive.
diff --git a/versioned_docs/version-2.0.0/learn/distributed-authority-quick-start.md b/versioned_docs/version-2.0.0/learn/distributed-authority-quick-start.md
new file mode 100644
index 000000000..e0cf9522f
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/distributed-authority-quick-start.md
@@ -0,0 +1,305 @@
+---
+id: distributed-authority-quick-start
+title: Distributed authority quickstart for Netcode for GameObjects
+---
+
+Use this guide to learn how to create your first [distributed authority](../terms-concepts/distributed-authority.md) Netcode for GameObjects project. It walks you through the connection setup, including connecting to the distributed authority service, and adding basic gameplay.
+
+:::note Beta feature
+Distributed authority is still in beta. During the beta phase, using the distributed authority service provided by the [Multiplayer Services package](https://docs.unity.com/ugs/en-us/manual/mps-sdk/manual) is free. When distributed authority is fully released, [using the service will incur a cost](https://unity.com/products/gaming-services/pricing).
+:::
+
+## Prerequisites
+
+Before you begin, you need the following:
+
+- An active Unity account with a valid license.
+- The [Unity Hub](https://unity.com/download).
+- A supported version of the Unity 6 Editor.
+ - Additional requirements information can be found here: [Netcode for GameObjects requirements](https://docs-multiplayer.unity3d.com/netcode/current/installation).
+
+## Project setup
+
+1. Create a new Unity Project using the **3D** template.
+2. Connect the project to Unity Cloud by selecting the **Connect to Unity Cloud** checkbox.
+
+## Install packages
+
+- Install the latest `com.unity.netcode.gameobjects` Netcode for GameObjects **v2.0.0** package.
+- Install the latest `com.unity.services.multiplayer` Multiplayer Services SDK package.
+
+## Netcode for GameObjects setup
+
+1. Using the SampleScene, add a new *Empty* object and name it *NetworkManager*.
+
+2. Attach a Network Manager component to it.
+![add network manager](/img/learn/distributed-authority-quick-start/network-manager.png)
+
+3. Under the Network Settings, set the **Network Topology** property to **Distributed Authority**.
+![set network topology](/img/learn/distributed-authority-quick-start/network-topology.png)
+
+4. Under **Network Transport**, select **UnityTransport** from the list of options to add.
+![use unity transport](/img/learn/distributed-authority-quick-start/unity-transport.png)
+
+5. Save any changes to your objects and scene.
+
+## Connection setup
+
+1. Create a new script called *ConnectionManager.cs*. This script provides a user interface and the script logic required to connect to a distributed authority service session:
+```cs
+using System;
+using System.Threading.Tasks;
+using Unity.Netcode;
+using Unity.Services.Authentication;
+using Unity.Services.Core;
+using Unity.Services.Multiplayer;
+using UnityEngine;
+
+public class ConnectionManager : MonoBehaviour
+{
+ private string _profileName;
+ private string _sessionName;
+ private int _maxPlayers = 10;
+ private ConnectionState _state = ConnectionState.Disconnected;
+ private ISession _session;
+ private NetworkManager m_NetworkManager;
+
+ private enum ConnectionState
+ {
+ Disconnected,
+ Connecting,
+ Connected,
+ }
+
+ private async void Awake()
+ {
+ m_NetworkManager = GetComponent();
+ m_NetworkManager.OnClientConnectedCallback += OnClientConnectedCallback;
+ m_NetworkManager.OnSessionOwnerPromoted += OnSessionOwnerPromoted;
+ await UnityServices.InitializeAsync();
+ }
+
+ private void OnSessionOwnerPromoted(ulong sessionOwnerPromoted)
+ {
+ if (m_NetworkManager.LocalClient.IsSessionOwner)
+ {
+ Debug.Log($"Client-{m_NetworkManager.LocalClientId} is the session owner!");
+ }
+ }
+
+ private void OnClientConnectedCallback(ulong clientId)
+ {
+ if (m_NetworkManager.LocalClientId == clientId)
+ {
+ Debug.Log($"Client-{clientId} is connected and can spawn {nameof(NetworkObject)}s.");
+ }
+ }
+
+ private void OnGUI()
+ {
+ if (_state == ConnectionState.Connected)
+ return;
+
+ GUI.enabled = _state != ConnectionState.Connecting;
+
+ using (new GUILayout.HorizontalScope(GUILayout.Width(250)))
+ {
+ GUILayout.Label("Profile Name", GUILayout.Width(100));
+ _profileName = GUILayout.TextField(_profileName);
+ }
+
+ using (new GUILayout.HorizontalScope(GUILayout.Width(250)))
+ {
+ GUILayout.Label("Session Name", GUILayout.Width(100));
+ _sessionName = GUILayout.TextField(_sessionName);
+ }
+
+ GUI.enabled = GUI.enabled && !string.IsNullOrEmpty(_profileName) && !string.IsNullOrEmpty(_sessionName);
+
+ if (GUILayout.Button("Create or Join Session"))
+ {
+ CreateOrJoinSessionAsync();
+ }
+ }
+
+ private void OnDestroy()
+ {
+ _session?.LeaveAsync();
+ }
+
+ private async Task CreateOrJoinSessionAsync()
+ {
+ _state = ConnectionState.Connecting;
+
+ try
+ {
+ AuthenticationService.Instance.SwitchProfile(_profileName);
+ await AuthenticationService.Instance.SignInAnonymouslyAsync();
+
+ var options = new SessionOptions() {
+ Name = _sessionName,
+ MaxPlayers = _maxPlayers
+ }.WithDistributedAuthorityNetwork();
+
+ _session = await MultiplayerService.Instance.CreateOrJoinSessionAsync(_sessionName, options);
+
+ _state = ConnectionState.Connected;
+ }
+ catch (Exception e)
+ {
+ _state = ConnectionState.Disconnected;
+ Debug.LogException(e);
+ }
+ }
+}
+```
+
+:::note
+
+It's important to wait until `OnClientConnectedCallback` has been triggered before spawning objects. Spawning objects early will result in errors and unexpected behaviour.
+
+:::
+
+2. Add the `ConnectionManager` component script you created to the *NetworkManager* object.
+![add connection manager](/img/learn/distributed-authority-quick-start/create-connection-manager.png)
+
+## Adding gameplay
+
+1. Create a new Script called *PlayerCubeController.cs*:
+```cs
+using Unity.Netcode.Components;
+using UnityEngine;
+#if UNITY_EDITOR
+using Unity.Netcode.Editor;
+using UnityEditor;
+///
+/// The custom editor for the component.
+///
+[CustomEditor(typeof(PlayerCubeController), true)]
+public class PlayerCubeControllerEditor : NetworkTransformEditor
+{
+ private SerializedProperty m_Speed;
+ private SerializedProperty m_ApplyVerticalInputToZAxis;
+
+
+ public override void OnEnable()
+ {
+ m_Speed = serializedObject.FindProperty(nameof(PlayerCubeController.Speed));
+ m_ApplyVerticalInputToZAxis = serializedObject.FindProperty(nameof(PlayerCubeController.ApplyVerticalInputToZAxis));
+ base.OnEnable();
+ }
+
+
+ public override void OnInspectorGUI()
+ {
+ var playerCubeController = target as PlayerCubeController;
+
+
+ playerCubeController.PlayerCubeControllerPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(playerCubeController.PlayerCubeControllerPropertiesVisible, $"{nameof(PlayerCubeController)} Properties");
+ if (playerCubeController.PlayerCubeControllerPropertiesVisible)
+ {
+ EditorGUILayout.PropertyField(m_Speed);
+ EditorGUILayout.PropertyField(m_ApplyVerticalInputToZAxis);
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+
+ EditorGUILayout.Space();
+
+
+ playerCubeController.NetworkTransformPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(playerCubeController.NetworkTransformPropertiesVisible, $"{nameof(NetworkTransform)} Properties");
+ if (playerCubeController.NetworkTransformPropertiesVisible)
+ {
+ // End the header group prior to invoking the base OnInspectorGUID in order to avoid nested
+ // foldout groups.
+ EditorGUILayout.EndFoldoutHeaderGroup();
+ // If NetworkTransform properties are visible, then both the properties any modified properties
+ // will be applied.
+ base.OnInspectorGUI();
+ }
+ else
+ {
+ // End the header group
+ EditorGUILayout.EndFoldoutHeaderGroup();
+ // If NetworkTransform properties are not visible, then make sure we apply any modified properties.
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+}
+#endif
+
+
+public class PlayerCubeController : NetworkTransform
+{
+#if UNITY_EDITOR
+ // These bool properties ensure that any expanded or collapsed property views
+ // within the inspector view will be saved and restored the next time the
+ // asset/prefab is viewed.
+ public bool PlayerCubeControllerPropertiesVisible;
+ public bool NetworkTransformPropertiesVisible;
+#endif
+
+
+ public float Speed = 10;
+ public bool ApplyVerticalInputToZAxis;
+
+
+ private Vector3 m_Motion;
+
+
+ private void Update()
+ {
+ // If not spawned or we don't have authority, then don't update
+ if (!IsSpawned || !HasAuthority)
+ {
+ return;
+ }
+
+
+ // Handle acquiring and applying player input
+ m_Motion = Vector3.zero;
+ m_Motion.x = Input.GetAxis("Horizontal");
+
+
+ // Determine whether the vertical input is applied to the Y or Z axis
+ if (!ApplyVerticalInputToZAxis)
+ {
+ m_Motion.y = Input.GetAxis("Vertical");
+ }
+ else
+ {
+ m_Motion.z = Input.GetAxis("Vertical");
+ }
+
+
+ // If there is any player input magnitude, then apply that amount of
+ // motion to the transform
+ if (m_Motion.magnitude > 0)
+ {
+ transform.position += m_Motion * Speed * Time.deltaTime;
+ }
+ }
+}
+```
+2. In the open *SampleScene*, create a 3D cube and name it *PlayerCube*.
+![create PlayerCube object](/img/learn/distributed-authority-quick-start/player-cube.png)
+3. Add a NetworkObject component to the *PlayerCube*.
+![add a NetworkObject component](/img/learn/distributed-authority-quick-start/add-networkobject.png)
+4. Set the NetworkObject Ownership to "None".
+5. Add the *PlayerCubeController* to the *PlayerCube*.
+![add the PlayerCubeController component](/img/learn/distributed-authority-quick-start/add-playercubecontroller.png)
+6. Create a Prefabs folder in the root Assets folder.
+7. Drag and drop the *PlayerCube* object into the newly created Prefabs folder.
+![create the player cube prefab](/img/learn/distributed-authority-quick-start/create-playercube-prefab.png)
+8. Delete the *PlayerCube* object from your scene.
+9. Open the Network Manager, navigate to **Prefab Settings**, and set the **Default Player Prefab** to be the newly created *PlayerCube*.
+![set the default player prefab](/img/learn/distributed-authority-quick-start/assign-default-player-prefab.png)
+10. Save all changes to the scene.
+
+## Next steps
+
+Hit play, fill out the **Profile Name** and **Session Name**, then click **Create or Join Session**. The profile name is the name of the player, so ensure this is different on every client. The session name is the identifier of the session you are joining, so this should be the same on every client. If everything has been set up correctly you will see the game create a session, connect to it, and spawn a PlayerCube.
+
+If you create a build and connect a new profile to the same session you will see a second PlayerCube spawn and sync up with the first.
+
+![success](/img/learn/distributed-authority-quick-start/gameplay.png)
diff --git a/versioned_docs/version-2.0.0/learn/faq.md b/versioned_docs/version-2.0.0/learn/faq.md
new file mode 100644
index 000000000..2f5eed4b8
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/faq.md
@@ -0,0 +1,101 @@
+---
+id: faq
+title: Frequently asked questions
+---
+
+The FAQ provides immediate answers for questions collected from the Community on developing games with Multiplayer, including Netcode for GameObjects (Netcode), Transport, and more.
+
+## Unity Netcode for GameObjects (Netcode)
+
+
+
+### Does Netcode have a Public Roadmap?
+
+See the [Multiplayer Networking Public Roadmap](https://unity.com/roadmap/unity-platform/multiplayer-networking) to review, suggest, and vote on features for all Multiplayer Networking, Netcode, and documentation.
+
+### Implement a Dedicated Server vs a Listen Server, would I need to make changes to the codebase?
+
+Netcode works with both a Listen Server and a Dedicated Server model. You just have to be careful that you're using things like `IsServer` and `IsHost` correctly.
+
+### Does Netcode have any Matchmaking functionality?
+
+You would have to implement matchmaking using third party matchmaking services. Netcode has no matchmaking functionality.
+
+### What are recommendations for getting a game connecting over the internet?
+
+The Multiplayer Technology Team recommend the following:
+
+1. Upload your server build to a cloud provider or another server machine and run it there.
+2. Host your game locally and open ports in your router.
+
+ It should work just like over LAN you just have to connect to the public IP itself. Make sure to open UDP on the router. Many forward ports tutorials are available to review, including this option https://portforward.com/.
+
+3. Use a Relay.
+
+ [Unity Relay](https://docs.unity.com/relay/introduction.html) offers a way for game developers to securely offer increased connectivity between players by using a join code style workflow without needing to invest in a third-party solution. The Relay service enables developers to connect players together using a listen server. Instead of using dedicated game servers (DGS), the Relay service provides connectivity through a universal Relay server acting as a proxy.
+
+ Another option is to use something like the `SteamP2PTransport`, which will work without the need of setting up any servers if you release your game on Steam.
+
+### Is it good for add Spawnable object into NetworkConfig after start host?
+
+Yes, but you need to ensure that all your clients add the same object to their configurations as well. You can't only add it on the host.
+
+### How do I join from two devices on the same network?
+
+The client need to use the local IPv4 address of your server. On Windows, you can find that address by opening the Command Prompt and typing `ipconfig`. Search for the `IPv4 Address` value on the server's machine.
+
+Your client needs an input field to input the server's IP. If you just need something for prototyping, you can use [NetworkManagerHud](https://github.com/Unity-Technologies/multiplayer-community-contributions/tree/main/com.community.netcode.extensions/Runtime/NetworkManagerHud). You should attach this code to the NetworkManager GameObject.
+
+### What's the best method for spawning?
+
+Spawning can always be done on the host/server. If you want to give a client control over spawning objects, you need to implement a server RPC that you call on the client to spawn the object.
+
+### What are best practices for handing physics with Netcode?
+
+Networked physics is complicated, with many different ways to handle them. Currently, physics can be a little difficult to handle with Netcode and the built-in `NetworkTransform`.
+
+The Multiplayer Technology Team recommends the following:
+
+- Simulate the physics on the server and transforms on the client.
+- Remove the Rigidbody component from all your client objects and have just the server drive the position of the physics object. This should help reduce stutter on the client.
+
+### How do you implement on Steam?
+
+The Steam transport should be quite straightforward to use. Just add it to your project and set the `ConnectToSteamID` in the transport on the client to connect to the host that's all you need.
+
+
+
+## Boss Room and Bitesize Samples
+
+
+
+### Why do I get path too long errors with Boss Room on Windows?
+
+Using Windows' built-in extracting tool may generate an `Error 0x80010135: Path too long` error window which can invalidate the extraction process.
+
+As a workaround, shorten the zip file to a single character (for example "c.zip") and move it to the shortest path on your computer (such as in root `C:\`) and retry. If that solution fails, another workaround is to extract the downloaded zip file using an application like 7zip.
+
+### Why do I get unidentified developer errors with Boss Room?
+
+If you try to run a build on OSX and receive a warning dialog mentioning an "unidentified developer," you might need to override your security settings for this application:
+
+1. In the Finder on your Mac, locate the application you want to open.
+
+:::note
+Don't use Launchpad, it doesn't allow you to access the shortcut menu.
+:::
+
+1. Control-click the app icon, then choose **Open** from the shortcut menu.
+1. Select **Open**.
+
+The app is saved as an exception to your security settings. You can open it in the future by double-clicking it just as you can any registered app.
+
+See [Apple Support](https://support.apple.com/guide/mac-help/open-a-mac-app-from-an-unidentified-developer-mh40616/mac) for details.
+
+### Why is there an `InitBootStrap` scene as the startup scene for Boss Room and Bitesize Samples?
+
+The initial reason is that in Netcode the `NetworkManager` is a singleton class. The Bitesize Samples Team initially created it in the main menu, but when the host was leaving the in-game/networked scene, the Network Manager was getting destroyed, which led to not being able to host a game again without restarting the game instance.
+
+The Bootstrap scene ensures that the NetworkManager and other singletons are initialized first and will be there when you get back to main menu.
+
+
diff --git a/versioned_docs/version-2.0.0/learn/lagandpacketloss.md b/versioned_docs/version-2.0.0/learn/lagandpacketloss.md
new file mode 100644
index 000000000..4ed4ae631
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/lagandpacketloss.md
@@ -0,0 +1,56 @@
+---
+id: lagandpacketloss
+title: Understanding latency
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+Multiplayer games operating over the internet have to manage adverse network factors that don't affect single-player or LAN-only multiplayer games, most notably [network latency](#network-latency). Latency (also known as lag) is the delay between a user taking an action and seeing the expected result. When latency is too high, a game feels unresponsive and slow.
+
+Generally, 200ms of latency is the point at which users notice gameplay degradation, although different types of games can tolerate more or less latency. For example, first-person shooter games perform best with less than 100ms of latency, whereas real-time strategy games can tolerate higher latency values of up to 500ms before gameplay is meaningfully impacted.
+
+In addition to the sources of latency described on this page, [ticks and update rates](ticks-and-update-rates.md) can also affect the user experience of your game.
+
+## Sources of latency
+
+There are a number of factors that contribute to latency, some of which can be minimized, although it's impossible to get rid of latency entirely.
+
+### Non-network latency
+
+Non-network latency refers to latency incurred by processes that happen before there's any involvement with the network. This is an area where you have more control over optimization to reduce latency (whereas network conditions are often beyond your control). Non-network latency is also referred to as input lag: the time it takes user input to be rendered on screen.
+
+Factors that contribute to non-network latency include:
+
+- **Input sampling delay**: The time it takes for an input device, such as a mouse or keyboard, to recognize that it's been activated and the time it takes for the game to detect that change.
+- **Render pipeline delay**: The time it takes for the GPU to render the outcome of inputs, which are often batched together to be processed in groups rather than individually.
+- **Vertical synchronization (VSync)**: A graphics technology that synchronizes the frame rate of the GPU with the refresh rate of the connected monitor. VSync can reduce undesirable visual behavior known as screen tearing, at the cost of increased latency incurred by the reduced frame rate.
+- **Display processing delay**: Display devices typically process incoming signals to some degree (such as deinterlacing and noise cancellation), which adds to latency.
+- **Pixel response time**: LCD screen pixels physically take time to change their brightness in response to inputs.
+
+### Network latency
+
+Network latency refers to latency incurred by interactions over the network after local processing is complete.
+
+Factors that contribute to network latency include:
+
+- **Processing delay**: The time it takes for the network router to read packet headers and forward them to the appropriate location. Processing delay also includes any encryption, network address translation (NAT), or network mapping that the router might be doing. This delay is generally small, but can add up when packets move between multiple locations.
+- **Transmission delay**: The time it takes for packets to be transmitted across the network. Transmission delay is proportional to the size of the packet (in bits) and is usually greatest in the parts of the network that connect directly to end users, which often have lower relative bandwidth. Sending fewer, larger packets can reduce transmission delay, because more bits are spent on game data rather than packet headers.
+- **Queueing delay**: The time packets spend waiting in queues. When a router receives more packets than it can process, those packets are added to a queue, which causes delays. Similarly, network interfaces can only output a limited number of packets at a time, so there can also be transmission queues. These queueing delays can add significantly to latency.
+- **Propagation delay**: The time it takes for signals to physically travel across the network. In [client-server topologies](../terms-concepts/network-topologies.md), this can be optimized by having servers located geographically closer to players.
+
+#### Round-trip time and pings
+
+Round-trip time (RTT) is a measure of how long it takes a packet to travel from one location on a network to another and receive a response packet back. You can use RTT to understand how much network latency your game is experiencing in different network conditions.
+
+A ping is a simplified way of measuring RTT that involves sending a very basic message, with no processing at either end of the interaction, to get a general idea of network responsiveness and latency.
+
+
+
+The time between sending the request and receiving the answer is the value of your ping. Sending and receiving data can take different amounts of time: for example, with a 20ms ping it might take 15ms to send a request from the client to the server and only 5ms to receive a response. Higher ping values indicate a lot of network latency, which can make games feel slow and unresponsive.
+
+#### Jitter and packet loss
+
+RTT can be affected by changing network conditions and is unlikely to remain constant, usually hovering around an average value. The degree to which this average value varies is referred to as jitter. Jitter can affect network latency mitigation and cause packets to arrive out of order.
+
+In addition to being delayed, packets can also be lost, which degrades gameplay experience either by losing key information and causing unpredictable behavior, or requiring it to be sent again, causing delays.
diff --git a/versioned_docs/version-2.0.0/learn/listenserverhostarchitecture.md b/versioned_docs/version-2.0.0/learn/listenserverhostarchitecture.md
new file mode 100644
index 000000000..2980ad5f6
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/listenserverhostarchitecture.md
@@ -0,0 +1,87 @@
+---
+id: listen-server-host-architecture
+title: Create a game with a listen server and host architecture
+sidebar_label: Listen server and host architecture
+---
+
+## What is a listen server
+
+A listen server acts as both a server and client on a single player's machine for multiplayer game play. This means one player both plays the game and owns the game world while other players connect to this server.
+
+This set up has performance, security, and cost considerations for implementation.
+
+### Disadvantages
+
+- Network performance relies on the residential internet connection of the host player and their machine's output efficiency. Both may cause the remote players connecting to the host to suffer performance issues.
+- The host player may have a large latency advantage over the remote players.
+- With access to all of the game world's information, the host player has an easier opportunity to cheat.
+- The server, i.e. the game ceases to exist when the host player leaves the game.
+
+### Advantages
+
+- Essentially free compared to dedicated server options.
+- Doesn't require special infrastructure or forward planning to set up. This makes them common use for LAN parties because latency and bandwidth issues aren't a concern.
+
+## When to use a listen server architecture
+
+Listen server architecture is a popular choice for single player games that want to provide the option to add a friend into an existing game world. Listen servers are best suited for a smaller player group (< 12) and games that don't require a persistent world.
+
+:::info
+*Persistent world* in Netcode for GameObjects means "a persistent online world."
+
+For example, the game state isn't bound to a player or a session, but is typically tied to the host.
+:::
+
+In contrast to dedicated servers, listen servers are cheaper without the need to run dedicated authoritative servers for a game. Often, the listen server approach is chosen to avoid setting up a system to orchestrate the game server fleet.
+
+:::note
+You still need to set up matchmaking for your player to join together to play. A listen server game requires redirecting players to the client-hosted server.
+:::
+
+## Connecting to a listen server
+
+Personal computers are hidden behind NATs (Network Address Translation devices) and routers to protect them from direct access. To connect to a listen server, you may choose an option such as [port forwarding](#port-forwarding), a [relay server](#relay-server), [NAT punch-through](#nat-punchthrough), or a [NAT punch with relay fallback](#nat-punch-and-relay-fallback).
+
+### Port Forwarding
+
+With port forwarding, the host can allow another player to connect to a listen server by forwarding a public port on their router to a machine in their local network.
+
+Considerations:
+
+* It has risks. By opening ports, you create direct pathways for hackers and malware attacks to access your system.
+* The host must manually open the ports on their router, and this requires some technical knowledge the average user may not have.
+* The host may not always have access to their router and would not be able to open a port. For example, the host may be using a mobile device, a corporate network, or public WiFi.
+
+Port forwarding may not be a viable option for a released game but can be useful for development. For more information about port forwarding, see https://portforward.com/.
+
+### Relay Server
+
+A dedicated server has ports already forwarded for players to connect anytime. These servers can run in the cloud or a data center. The relay server option uses these servers to send data between players.
+
+In a listen server relay scenario, the host and all clients connect to the same listen server. Clients send packets to the relay server, which then redirects these packets to the intended recipient.
+
+Advantages:
+
+* Compared to direct connecting through port forwarding, a relay server should always work for any client.
+* A relay server knows when the host client disconnects and can inform the other clients or start a host migration process.
+
+Disadvantages:
+
+A relay server costs money, and the round trip times for packet exchange may be higher because they have to go through the relay server instead of being sent directly to the other client.
+
+### NAT Punch-through
+
+Network Address Translation (NAT) punch-through, also known as hole punching, opens a direct connection without port forwarding. When successful, clients are directly connected to each other to exchange packets. However, depending on the NAT types among the clients, NAT punching often fails.
+
+Ways to NAT punch:
+* Session Traversal Utilities for NAT [STUN](../reference/glossary/network-terms.md#session-traversal-utilities-for-nat-stun)
+* Interactive Connectivity Establishment [ICE](../reference/glossary/network-terms.md#interactive-connectivity-establishment-ice)
+* User Datagram Protocol [(UDP) hole punching](../reference/glossary/network-terms.md#udp-hole-punching)
+
+Because of its high rate of failure, NAT punch-through is typically only used with a relay fallback.
+
+### NAT Punch and Relay Fallback
+
+This option combines NAT punching with a relay fallback. Clients first try to connect to the host by NAT punching and default back to the relay server on failure. This reduces the workload on the relay server while allowing clients to still connect to the host.
+
+It is widely used because it reduces the hosting costs of relay servers.
diff --git a/versioned_docs/version-2.0.0/learn/rpcnetvarexamples.md b/versioned_docs/version-2.0.0/learn/rpcnetvarexamples.md
new file mode 100644
index 000000000..a1a976241
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/rpcnetvarexamples.md
@@ -0,0 +1,72 @@
+---
+id: rpcnetvarexamples
+title: RPCs vs NetworkVariables examples
+sidebar_label: RPCs vs NetworkVariables examples
+---
+This page has examples of how the Small Coop Sample (Boss Room) uses `RPC`s and `NetworkVariable`s. It gives guidance on when to use `RPC`s versus `NetworkVariable`s in your own projects.
+
+See the [RPC vs NetworkVariable](rpcvnetvar.md) tutorial for more information.
+
+## RPCs for movement
+
+Boss Room uses RPCs to send movement inputs.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/UserInput/ClientInputSender.cs
+```
+
+Boss Room wants the full history of inputs sent, not just the latest value. There is no need for `NetworkVariable`s, you just want to blast your inputs to the server. Since Boss Room isn't a twitch shooter, it sends inputs as reliable `RPC`s without worrying about the latency an input loss would add.
+
+## Arrow's GameObject vs Fireball's VFX
+
+The archer's arrows use a standalone `GameObject` that's replicated over time. Since this object's movements are slow, the Boss Room development team decided to use state (via the `NetworkTransform`) to replicate the ability's status (in case a client connected while the arrow was flying).
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/Projectiles/PhysicsProjectile.cs
+```
+
+Boss Room might have used an `RPC` instead (for the Mage's projectile attack). Since the Mage's projectile fires quickly, the player experience isn't affected by the few milliseconds where a newly connected client might miss the projectile. In fact, it helps Boss Room save on bandwidth when managing a replicated object. Instead, Boss Room sends a single RPC to trigger the FX client side.
+
+```csharp reference
+
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/Projectiles/FXProjectile.cs
+
+```
+
+## Breakable state
+
+Boss Room might have used a "break" `RPC` to set a breakable object as broken and play the appropriate visual effects. Applying the "replicate information when a player joins the game mid-game" rule of thumb, the Boss Room development team used `NetworkVariable`s instead. Boss Room uses the `OnValueChanged` callback on those values to play the visual effects (and an initial check when spawning the `NetworkBehaviour`).
+
+```csharp reference
+
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/Breakable.cs#L59-L78
+
+```
+
+The visual changes:
+
+```csharp reference
+
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/Breakable.cs#L146-L156
+
+```
+
+:::tip Lesson Learned
+
+**Error when connecting after imps have died**: The following is a small gotcha the Boss Room development team encountered while developing Boss Room. Using `NetworkVariable`s isn't magical. If you use `OnValueChanged`, you still need to make sure you initialize your values when spawning for the first time. `OnValueChanged` isn't called when connecting for the first time, only for the next value changes.
+
+![imp not appearing dead](/img/01_imp_not_appearing_dead.png)
+
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerAnimationHandler.cs#L23-L30
+```
+
+
+:::
+
+## Hit points
+
+Boss Room syncs all character and object hit points through `NetworkVariable`s, making it easy to collect data.
+
+If Boss Room synced this data through `RPC`s, Boss Room would need to keep a list of `RPC`s to send to connecting players to ensure they get the latest hit point values for each object. Keeping a list of `RPC`s for each object to send to those `RPC`s on connecting would be a maintainability nightmare. By using `NetworkVariable`s, Boss Room lets the SDK do the work.
diff --git a/versioned_docs/version-2.0.0/learn/rpcvnetvar.md b/versioned_docs/version-2.0.0/learn/rpcvnetvar.md
new file mode 100644
index 000000000..443b65318
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/rpcvnetvar.md
@@ -0,0 +1,114 @@
+---
+id: rpcvnetvar
+title: RPC vs NetworkVariable
+sidebar_label: RPC vs NetworkVariable
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+Choosing the wrong data syncing mechanism can create bugs, use too much bandwidth, and add too much complexity to your code.
+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.
+
+## Choosing between `NetworkVariable`s or RPCs
+
+- Use RPCs for transient events, information only useful for a moment when it's received.
+- Use `NetworkVariable`s for persistent states, for information that will be around more than a moment.
+
+A quick way to choose which to use is to ask yourself: "Should a player joining mid-game get that information?"
+
+
+
+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.
+
+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.
+
+
+s
+
+In that case, it's preferable to use `NetworkVariable`s as show below:
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/GameplayObjects/SwitchedDoor.cs#L10-L26
+```
+
+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.
+
+`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.
+
+
+
+`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.
+
+## Why not use `NetworkVariable`s for everything?
+
+RPCs are simpler.
+
+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.
+
+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.
+
+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.
+
+`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.
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/Input/AoeActionInput.cs
+```
+
+`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).
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/AOEAction.cs#L8-L-40
+```
+
+The following snippet of code is triggered by an RPC coming from the server
+
+```csharp reference
+https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/v2.2.0/Assets/Scripts/Gameplay/Action/ConcreteActions/AOEAction.cs#L77-L82
+```
+
+:::tip
+If you want to make sure two variables are received at the same time, RPCs are great for this.
+
+If you change `NetworkVariables` "a" and "b", there is no guarantee they will both be received client side at the same time.
+
+
+
+Sending them as two parameters in the same RPC ensures they will be received at the same time client side.
+
+
+
+`NetworkVariable`s are great when you only care about the latest value.
+
+:::
+
+
+## Summary
+
+`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.
+
+RPCs are great for sending transient events. Use them when transmitting short-lived events.
diff --git a/versioned_docs/version-2.0.0/learn/sample-dedicated-server.md b/versioned_docs/version-2.0.0/learn/sample-dedicated-server.md
new file mode 100644
index 000000000..3ce8ff02f
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/sample-dedicated-server.md
@@ -0,0 +1,201 @@
+---
+id: sample-dedicated-server
+title: Dedicated game server sample
+---
+
+## Dedicated Game Server sample
+
+[The Dedicated Game Server sample](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/tree/main/Experimental/DedicatedGameServer) project demonstrates how the dedicated server model works and the tools that you can use to test multiplayer in the editor.
+
+This project uses the following packages and services:
+
+* [Dedicated Server](https://docs.unity3d.com/Packages/com.unity.dedicated-server@1.0/manual/index.html)
+* [Netcode For GameObjects](https://docs-multiplayer.unity3d.com/netcode/current/about/)
+* [Unity Transport](https://docs-multiplayer.unity3d.com/transport/current/about/)
+* [Multiplayer Play Mode](https://docs-multiplayer.unity3d.com/mppm/current/about/)
+* [Game Server Hosting](https://docs.unity.com/ugs/en-us/manual/game-server-hosting/manual/welcome-to-multiplay)
+* [Matchmaker](https://docs.unity.com/ugs/en-us/manual/matchmaker/manual/matchmaker-overview)
+
+
+### Sample features
+
+This section describes how the following features are configured to use the dedicated server:
+
+- [Dedicated Game Server sample](#dedicated-game-server-sample)
+ - [Sample features](#sample-features)
+ - [Project settings](#project-settings)
+ - [Strip generic components from the server](#strip-generic-components-from-the-server)
+ - [Split scripts across the client, server, or network](#split-scripts-across-the-client-server-or-network)
+ - [Synchronize animations between clients](#synchronize-animations-between-clients)
+ - [Automatically synchronized animations](#automatically-synchronized-animations)
+ - [Manually synchronized animations](#manually-synchronized-animations)
+ - [Navigation](#navigation)
+ - [Use multiplayer roles to control game logic](#use-multiplayer-roles-to-control-game-logic)
+- [Integrate with Unity Gaming Services (UGS)](#integrate-with-unity-gaming-services-ugs)
+- [Set default command line arguments](#set-default-command-line-arguments)
+
+### Project settings
+
+In this sample some GameObjects and components exist on the clients, some exist on the server, and some exist on both. This section explains how this sample strips generic GameObjects and components from the client or the server.
+
+#### Strip generic components from the server
+
+This project automatically strips the rendering, UI, and Audio components. To learn which settings automatically strip components, perform the following actions:
+
+* Open the Project Settings window (menu: **Edit** > **Project Settings**).
+* Select **Multiplayer Roles**.
+* Select **Content Selection**.
+
+For more information, refer to [Automatically remove components from a Multiplayer Role](https://docs.unity3d.com/Packages/com.unity.dedicated-server@1.0/manual/automatic-selection.html).
+
+This sample strips other components and GameObjects from the server manually. To learn how to do this, refer to [Control which GameObjects and components exist on the client or the server](https://docs.unity3d.com/Packages/com.unity.dedicated-server@1.0/manual/content-selection.html).
+
+#### Split scripts across the client, server, or network
+
+This sample splits the logic of the Player Character and the AI Character into separate scripts so that you can use the Content Selection window to run each character separately on the client, server and network. For example, the `PlayerCharacter` script logic is split into the following scripts:
+* Client Player Character. This script only exists on the clients.
+* Server Player Character.This script only exists on the server.
+* Networked Player Character: This script inherits from `NetworkBehaviour`.It synchronizes data and sends messages between the server and clients. This script exists on both clients and the server.
+
+These scripts separate the logic of each player which means you can strip the components that each script uses. For example, Client Player Character is the only script that uses the Player Character’s `CharacterController` component, so you can safely strip the `CharacterController` component from the server. To learn where the scripts in this sample exist, do the following:
+1. Select a Player Character GameObject.
+2. Open the GameObject’s Inspector window.
+3. Refer to the script component’s [Multiplayer role icon](https://docs.unity3d.com/Packages/com.unity.dedicated-server@1.0/manual/mutliplayer-roles-icons.html).
+
+The logic for scripts that contain a small class, like the doors and switches in this sample scene, exist in a single script that inherits from ``NetworkBehaviour``.
+
+#### Synchronize animations between clients
+
+This sample handles synchronizes animations between clients in the following ways:
+
+* Automatically synchronized animations. This process uses the NetworkAnimator component.
+* Manually synchronized animations. Use this process to strip animators from the server.
+
+##### Automatically synchronized animations
+
+The Animator component and the NetworkAnimator script synchronize animations across the clients and servers. The server or the owner of the animations, for example a PlayerCharacter script that uses a `ClientNetworkAnimator`, handles and automatically synchronizes animations between clients. This is necessary for animations that drive logic on the server. For example, in this sample the door animation (door_boss_ani) is synchronized automatically, but its game state determines whether to enable or disable its colliders and navmesh obstacles.
+
+##### Manually synchronized animations
+
+The Animator components on the AICharacter prefab in this sample are stripped from the server to reduce the build size which reduces the bandwidth and CPU resources that the server uses. This means that the NetworkAnimator doesn’t automatically synchronize animations between clients and requires manually synchronized animations.
+
+Each client uses data and events that are synchronized between them to drive the animation. The server handles their movement, and synchronizes their speed and transform values. Clients use that information to drive the character’s animation.
+
+`ServerAICharacter.cs`:
+
+```
+void Update()
+ {
+ if (!m_NavMeshAgent.pathPending && m_NavMeshAgent.remainingDistance < k_ReachDist)
+ {
+ GotoNextPoint();
+ }
+ m_NetworkedAICharacter.Speed = m_NavMeshAgent.velocity.magnitude;
+ }
+```
+
+`ClientAICharacter.cs`:
+
+```
+void Update()
+ {
+ if (m_NetworkedAICharacter.IsSpawned)
+ {
+ m_Animator.SetFloat(k_AnimIdSpeed, m_NetworkedAICharacter.Speed);
+ }
+ }
+```
+
+#### Navigation
+
+The AI characters in this sample use the navigation system. The AI characters exist on the server which means their navigation data and components are not required on clients and can be stripped. This includes the Navmesh and the NavMeshAgent, NavMeshModifier, and NavMeshObstacle components.
+
+Other GameObjects specific to servers are also stripped from clients, like the player spawn locations and the patrols.
+
+#### Use multiplayer roles to control game logic
+
+This sample assigns a [Multiplayer Role](https://docs.unity3d.com/Packages/com.unity.dedicated-server@1.0/manual/multiplayer-roles.html) to move Clients and Servers to different scenes when the application starts.
+
+```
+///
+ /// Initializes the application's network-related behaviour according to the configuration. Servers load the main
+ /// game scene and automatically start. Clients load the metagame scene and, if autoconnect is set to true, attempt
+ /// to connect to a server automatically based on the IP and port passed through the configuration or the command
+ /// line arguments.
+ ///
+
+ void InitializeNetworkLogic()
+ {
+ var commandLineArgumentsParser = new CommandLineArgumentsParser();
+ ushort listeningPort = (ushort) commandLineArgumentsParser.Port;
+ switch (MultiplayerRolesManager.ActiveMultiplayerRoleMask)
+ {
+ case MultiplayerRoleFlags.Server:
+ //lock framerate on dedicated servers
+ Application.targetFrameRate = commandLineArgumentsParser.TargetFramerate;
+ QualitySettings.vSyncCount = 0;
+ m_ConnectionManager.StartServerIP(k_DefaultServerListenAddress, listeningPort);
+ break;
+ case MultiplayerRoleFlags.Client:
+ {
+ SceneManager.LoadScene("MetagameScene");
+ if (AutoConnectOnStartup)
+ {
+ m_ConnectionManager.StartClient(k_DefaultClientAutoConnectServerAddress, listeningPort);
+ }
+ break;
+ }
+ case MultiplayerRoleFlags.ClientAndServer:
+ throw new ArgumentOutOfRangeException("MultiplayerRole", "ClientAndServer is an invalid multiplayer role in this sample. Please select the Client or Server role.");
+ }
+ }
+```
+
+The Multiplayer Role also defines how the game handles connection events:
+
+```
+void OnConnectionEvent(ConnectionEvent evt)
+ {
+ if (MultiplayerRolesManager.ActiveMultiplayerRoleMask == MultiplayerRoleFlags.Server)
+ {
+ switch (evt.status)
+ {
+ case ConnectStatus.GenericDisconnect:
+ case ConnectStatus.ServerEndedSession:
+ case ConnectStatus.StartServerFailed:
+ // If server ends networked session or fails to start, quit the application
+ Quit();
+ break;
+ case ConnectStatus.Success:
+ // If server successfully starts, load game scene
+ NetworkManager.Singleton.SceneManager.LoadScene("GameScene01", LoadSceneMode.Single);
+ break;
+ }
+ }
+ else
+ {
+ switch (evt.status)
+ {
+ case ConnectStatus.GenericDisconnect:
+ case ConnectStatus.UserRequestedDisconnect:
+ case ConnectStatus.ServerEndedSession:
+ // If client is disconnected, return to metagame scene
+ SceneManager.LoadScene("MetagameScene");
+ break;
+ }
+ }
+ }
+```
+
+## Integrate with Unity Gaming Services (UGS)
+
+This sample uses the following Unity Gaming Services (UGS):
+
+* The [Game Server Hosting](https://docs.unity.com/ugs/en-us/manual/game-server-hosting/manual/welcome) service hosts the dedicated server builds in the cloud.
+* The [Matchmaker](https://docs.unity.com/ugs/en-us/manual/matchmaker/manual/matchmaker-overview) service allows clients to connect to those servers.
+
+## Set default command line arguments
+
+Some of the parameters in this sample are set in command line arguments, for example, the port that the servers listen on and the target framerate of the server which apply in a build. When you test a project in the editor, Unity uses a fallback value instead.
+
+This allows the Game Server Hosting service to specify which port a server uses when it is allocated. This sample uses the `DedicatedServer.Arguments` static class to read those values. It uses the [CLI Arguments Defaults](https://docs.unity3d.com/Packages/com.unity.dedicated-server@1.0/manual/cli-arguments.html) feature of the [Dedicated Server package](https://docs.unity3d.com/Packages/com.unity.dedicated-server@1.0/manual/index.html) to provide default values for those arguments.
diff --git a/versioned_docs/version-2.0.0/learn/ticks-and-update-rates.md b/versioned_docs/version-2.0.0/learn/ticks-and-update-rates.md
new file mode 100644
index 000000000..95d8f7bfd
--- /dev/null
+++ b/versioned_docs/version-2.0.0/learn/ticks-and-update-rates.md
@@ -0,0 +1,39 @@
+---
+id: ticks-and-update-rates
+title: Tick and update rates
+---
+import ImageSwitcher from '@site/src/ImageSwitcher.js';
+
+In addition to the effects of [latency](lagandpacketloss.md), gameplay experience in a multiplayer game is also affected by the server's [tick rate](#tick-rate) and the client's [update rate](#update-rate). Low tick and update rates reduce game responsiveness and add to perceived latency for users.
+
+## Tick rate
+
+Tick rate, also known as the simulation rate, is a measure of how frequently the server updates the game state. At the beginning of a tick, the server starts to process the data it's received from clients since the last tick and runs the necessary simulations to update the game state. The updated game state is then sent back to the clients. The faster the server finishes a tick, the earlier clients can receive the updated game state (subject to the client's [update rate](#update-rate)).
+
+![Tick rate](/img/tick_rate.png)
+
+Tick rate is measured in hertz (Hz). For example, a tick rate of 60 Hz means the server updates the game state sixty times a second, whereas a tick rate of 30 Hz means the server updates the game states only thirty times a second. Higher tick rates produce a more responsive game experience, at the cost of increased load on the simulating server.
+
+When a server fails to process all incoming client data before the end of the current tick, it produces gameplay issues such as rubber banding, player teleporting, hits getting rejected, and physics failing. As such, there's a balance between having a high tick rate to create responsive gameplay and ensuring that the server has enough time to process all client data before the end of a tick.
+
+## Update rate
+
+Update rate is a measure of how frequently the client sends and receives data to and from the server. It's also measured in hertz and, like tick rate, a higher update rate results in a more responsive game at the cost of increased processing and network demands on the client and server.
+
+
+
+In addition to adding to perceived latency, low update rates can cause their own issues, such as multiple updates being bundled together and arriving at the same time, causing undesirable behavior.
+
+In the example of 'super bullets': if an in-game gun is capable of shooting more times per second than the client can update, then at some point the impact of more than one bullet will be communicated in the same update. For players receiving this update, it will seem as if a single bullet is doing more damage than it should, because they're actually receiving updates from multiple bullets at once.
+
+The diagram below illustrates the difference between a 10 Hz update rate and a 60 Hz update rate. With a 10 Hz update rate, the game sends updates to the server ten times a second, so a gun that can fire 600 rounds per minute (RPM), or ten times a second, will only ever send a single bullet per update. A gun that fires at 750 RPM, more than ten times a second, will end up running into the super bullet problem. A higher update rate of 60 Hz resolves this issue, ensuring that there are enough updates for each bullet to arrive separately in its own update.
+
+
+
+### Discrepancy between tick rate and update rate
+
+If the update rate of a client is lower than the tick rate of the server, then the client won't see the benefit of the high tick rate, because it will only receive updates at the client update rate, even if multiple ticks have been processed in the interim.
diff --git a/versioned_docs/version-2.0.0/relay/relay.md b/versioned_docs/version-2.0.0/relay/relay.md
new file mode 100644
index 000000000..23845df1c
--- /dev/null
+++ b/versioned_docs/version-2.0.0/relay/relay.md
@@ -0,0 +1,182 @@
+---
+id: relay
+title: Using Unity Relay
+---
+
+With [Netcode for GameObjects](https://docs-multiplayer.unity3d.com/netcode/current/about/) you can use an IP address and a port to connect a client to a host over the internet. However, using an IP address to establish a connection doesn't always work. Instead, you can use [Unity Relay](https://docs.unity.com/ugs/en-us/manual/relay/manual/introduction) to initiate a connection between multiple clients and a host.
+
+Many factors impact how you connect to the remote host. To connect to a remote host, use one of the following methods:
+
+* Perform a [NAT punchthrough](../learn/listenserverhostarchitecture.md#option-c-nat-punchthrough): This advanced technique directly connects to the host computer, even if it's on another network.
+* Use a [relay server](https://docs.unity.com/relay/en/manual/relay-servers): A relay server exists on the internet with a public-facing IP that you and the host can access. After the client and the host connect to a relay server, they can send data to each other through the relay server.
+
+Netcode for GameObjects doesn't offer tools to help you punch through a NAT. However, you can use the Unity Relay service to relay all technology based on Unity Transport.
+
+## Using Unity Relay
+
+To access a Unity Relay server, do the following:
+
+* As the host, request an allocation on the relay server.
+* As a client, use the [join code](https://docs.unity.com/relay/en/manual/join-codes) that the host creates to connect to the relay server. This code allows the host and clients to communicate through the relay server without disclosing their IP addresses and ports directly.
+
+### Enable Unity Relay in a project
+
+To enable and set up Unity Relay in a project, follow the steps in [Get started with Relay](https://docs.unity.com/relay/en/manual/get-started).
+
+### Test the Unity Relay service in the Unity Editor
+
+From Unity version 2022.3, you can test the Relay service with Netcode for GameObjects in the Editor. To do this, do the following:
+
+1. Follow the steps in [Get started with Netcode for GameObjects](https://docs-multiplayer.unity3d.com/netcode/current/tutorials/get-started-ngo/).
+2. Follow the steps in [Get started with Relay](https://docs.unity.com/relay/en/manual/get-started).
+3. Open the inspector window and select the Network Manager.
+4. Navigate to the Start Connection section.
+5. Check the **Try Relay in the editor** box.
+6. Select **Start Server** or **Start Host** to start the server or host.
+7. In the inspector, copy the [join code](https://docs.unity.com/relay/en/manual/join-codes).
+8. Enter the join code in a new window running the same project.
+9. Select **Start Client**.
+
+This means you don't need to create UI elements to test the Relay service.
+
+If the connection fails then an error message appears in the UI and console.
+![](/img/relay/ngo-relay-connection.png)
+
+If Relay connects, a message appears in the inspector that displays the join code.
+![](/img/relay/ngo-relay-connected.png)
+
+You can copy the join code to share it, or test it in a project in a separate window. Refer to [testing locally](../tutorials/testing/testing_locally.md) for more details.
+
+:::note
+This Relay integration is only available in the Editor, which means you can't use it in a build. Instead, use the code snippets at the end of this page. These snippets use the Unity Transport Package. To do this in projects that don't use Transport, refer to the Relay documentation.
+:::
+
+### Create an allocation on a Relay server
+
+To create an [allocation](https://docs.unity.com/relay/en/manual/allocations) on a Relay server, make an authenticated call to the Unity backend using the SDK. To do this, call the `CreateAllocationAsync` method on the host with the maximum number of expected peers. For example, a host that requests a maximum of three peer connections reserves four slots for a four-player game. This function can throw exceptions, which you can catch to learn about the error that caused them.
+
+```csharp
+//Ask Unity Services to allocate a Relay server that will handle up to eight players: seven peers and the host.
+Allocation allocation = await Unity.Services.Relay.RelayService.Instance.CreateAllocationAsync(7);
+```
+
+The `Allocation` class represents all the necessary data for a [host player](https://docs.unity.com/relay/manual/players#Host) to start hosting using the specific Relay server allocated. You don't need to understand each part of this allocation; you only need to feed them to your chosen transport that handles the Relay communication on its own. For reference, here's a simple overview of those parameters:
+
+* A `RelayServer` class containing the IP and port of your allocation's server.
+
+* The allocation ID in a Base64 form and GUID form referred to as `AllocationIdBytes` and `AllocationId`.
+
+* A blob of encrypted bytes representing the [connection data](https://docs.unity.com/relay/en/manual/connection-data) (known as `ConnectionData`) allows users to connect to this host.
+
+* A Base64 encoded `Key` for message signature.
+
+Each allocation creates a unique [join code](https://docs.unity.com/relay/en/manual/join-codes) suitable for sharing over instant messages or other means. This join code allows your clients to join your game. You can retrieve it by calling the Relay SDK like so:
+
+```csharp
+string joinCode = await Unity.Services.Relay.RelayService.Instance.GetJoinCodeAsync(allocation.AllocationId);
+```
+
+With those two calls, you now have your Relay allocation ready and the associated join code. Pass the allocation parameters to your host transport and send the join code (a simple string) over the Internet by the mean of your choice to your clients.
+
+Remember to [authenticate](https://docs.unity.com/relay/en/manual/authentication) your users before using SDK methods. The easiest way is the anonymous one (shown in the following code snippet), but you can use more advanced techniques.
+
+```csharp
+//Initialize the Unity Services engine
+await UnityServices.InitializeAsync();
+if (!AuthenticationService.Instance.IsSignedIn)
+{
+ //If not already logged, log the user in
+ await AuthenticationService.Instance.SignInAnonymouslyAsync();
+}
+```
+
+### Join an allocation on a Relay server
+
+To join an allocation on a Relay server, the following must be true:
+
+* The host of the game has created a Relay allocation.
+* The client has received a join code.
+
+To join a relay, a client requests all the allocation parameters from the join code to join the game. To do this, use the join code to call the `JoinAllocationAsync` method as the following code snippet demonstrates:
+
+```csharp
+//Ask Unity Services to join a Relay allocation based on our join code
+JoinAllocation allocation = await Unity.Services.Relay.RelayService.Instance.JoinAllocationAsync(joinCode);
+```
+For more information about the join code connection process, refer to [Connection flow](https://docs.unity.com/relay/manual/connection-flow#4).
+
+### Pass allocation data to a transport component
+
+When an allocation exists, you need to make all traffic that comes from Netcode for GameObjects go through the Relay. To do this, perform the following actions to pass the allocation parameters to UnityTransport:
+
+1. Retrieve Unity transport from your `NetworkManager`:
+```csharp
+//Retrieve the Unity transport used by the NetworkManager
+UnityTransport transport = NetworkManager.Singleton.gameObject.GetComponent();
+```
+
+2. Call the `SetRelayServerData` method on the retrieved transport by passing the allocation data that you retrieved, as well as the connection type (here set to [dtls](https://docs.unity.com/relay/en/manual/dtls-encryption)). For example:
+
+```csharp
+transport.SetRelayServerData(new RelayServerData(allocation, connectionType:"dtls"));
+```
+
+3. Call `StartClient`, `StartHost` or `StartServer` and use the Netcode library.
+
+## Code sample
+
+Use the following code to work with the [Relay server](https://docs.unity.com/relay/en/manual/relay-servers). To start a server instead of a host, replace the `StartHost` call with `StartServer` in `StartHostWithRelay`.
+
+For more information, refer to [Unity Relay](https://docs.unity.com/ugs/en-us/manual/relay/manual/introduction).
+
+```csharp
+///
+/// Creates a relay server allocation and start a host
+///
+/// The maximum amount of clients that can connect to the relay
+/// The join code
+public async Task StartHostWithRelay(int maxConnections=5)
+{
+ //Initialize the Unity Services engine
+ await UnityServices.InitializeAsync();
+ //Always authenticate your users beforehand
+ if (!AuthenticationService.Instance.IsSignedIn)
+ {
+ //If not already logged, log the user in
+ await AuthenticationService.Instance.SignInAnonymouslyAsync();
+ }
+
+ // Request allocation and join code
+ Allocation allocation = await RelayService.Instance.CreateAllocationAsync(maxConnections);
+ var joinCode = await RelayService.Instance.GetJoinCodeAsync(allocation.AllocationId);
+ // Configure transport
+ NetworkManager.Singleton.GetComponent().SetRelayServerData(new RelayServerData(allocation, "dtls"));
+ // Start host
+ return NetworkManager.Singleton.StartHost() ? joinCode : null;
+}
+
+///
+/// Join a Relay server based on the JoinCode received from the Host or Server
+///
+/// The join code generated on the host or server
+/// True if the connection was successful
+public async Task StartClientWithRelay(string joinCode)
+{
+ //Initialize the Unity Services engine
+ await UnityServices.InitializeAsync();
+ //Always authenticate your users beforehand
+ if (!AuthenticationService.Instance.IsSignedIn)
+ {
+ //If not already logged, log the user in
+ await AuthenticationService.Instance.SignInAnonymouslyAsync();
+ }
+
+ // Join allocation
+ var joinAllocation = await RelayService.Instance.JoinAllocationAsync(joinCode: joinCode);
+ // Configure transport
+ NetworkManager.Singleton.GetComponent().SetRelayServerData(new RelayServerData(joinAllocation, "dtls"));
+ // Start client
+ return !string.IsNullOrEmpty(joinCode) && NetworkManager.Singleton.StartClient();
+}
+
+```
diff --git a/versioned_docs/version-2.0.0/release-notes/ngo-changelog.md b/versioned_docs/version-2.0.0/release-notes/ngo-changelog.md
new file mode 100644
index 000000000..536f3cb93
--- /dev/null
+++ b/versioned_docs/version-2.0.0/release-notes/ngo-changelog.md
@@ -0,0 +1,28 @@
+---
+id: ngo-changelog
+title: Netcode for GameObjects changelog
+description: Netcode for Gameobjects changelog and release notes
+---
+
+The following content tracks features, updates, bug fixes, and refactoring for the next release of Unity Netcode. Since Netcode for GameObjects is open source, you can access the full release notes and changelogs in the [com.unity.netcode.gameobjects GitHub repository](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects).
+
+| Release | Date | Changelog |
+|---|---|---|
+| 2.0.0-pre.4 | 2024-08-21 | [2.0.0-pre.4](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.0/changelog/CHANGELOG.html) |
+| 2.0.0-exp | 2024-06-03 | [2.0.0-exp](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/develop-2.0.0/com.unity.netcode.gameobjects/CHANGELOG.md#200-exp5---2024-06-03) |
+| 1.11.0 | 2024-08-20 | [1.11.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.11.0) |
+| 1.10.0 | 2024-07-22 | [1.10.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.10.0) |
+| 1.9.1 | 2024-04-18 | [1.9.1](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.9.1) |
+| 1.8.0 | 2023-12-12 | [1.8.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.8.0) |
+| 1.7.1 | 2023-11-15 | [1.7.1](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.7.1) |
+| 1.7.0 | 2023-10-11 | [1.7.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.7.0) |
+| 1.6.0 | 2023-08-29 | [1.6.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.6.0) |
+| 1.5.2 | 2023-07-24 | [1.5.2](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.5.2) |
+| 1.5.1 | 2023-06-09 | [1.5.1](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.5.1) |
+| 1.4.0 | 2023-04-10 | [1.4.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.4.0) |
+| 1.3.1 | 2023-03-27 | [1.3.1](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.3.1) |
+| 1.2.0 | 2022-11-21 | [1.2.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.2.0) |
+| 1.1.0 | 2022-10-18 | [1.1.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.1.0) |
+| 1.0.2 | 2022-09-08 | [1.0.2](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/ngo%2F1.0.2 )|
+| 1.0.1 | 2022-08-23 | [1.0.1](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/1.0.1) |
+| 1.0.0 | 2022-06-27 | [1.0.0](https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/releases/tag/1.0.0) |
diff --git a/versioned_docs/version-2.0.0/samples/release-notes/bitesize-changelog.md b/versioned_docs/version-2.0.0/samples/release-notes/bitesize-changelog.md
new file mode 100644
index 000000000..ea8eee81f
--- /dev/null
+++ b/versioned_docs/version-2.0.0/samples/release-notes/bitesize-changelog.md
@@ -0,0 +1,11 @@
+---
+id: bitesize-changelog
+title: Multiplayer Bitesize samples
+description: Bitesize changelog and release notes
+---
+
+The following content tracks features, updates, bug fixes, and refactoring for the next release of the Multiplayer Bitesize samples project. Since Multiplayer Bitesize is open source, you can access the full release notes and changelogs in the [com.unity.multiplayer.samples.bitesize GitHub repository](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize).
+
+| Release | Date | Changelog |
+|---|---|---|
+| 1.1.0 | 2022-12-13 | [1.1.0](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.bitesize/releases/tag/v1.1.0) |
diff --git a/versioned_docs/version-2.0.0/samples/release-notes/bossroom-changelog.md b/versioned_docs/version-2.0.0/samples/release-notes/bossroom-changelog.md
new file mode 100644
index 000000000..bf25ca120
--- /dev/null
+++ b/versioned_docs/version-2.0.0/samples/release-notes/bossroom-changelog.md
@@ -0,0 +1,20 @@
+---
+id: bossroom-changelog
+title: Boss Room changelog
+description: Boss Room changelog and release notes
+---
+
+The following content tracks features, updates, bug fixes, and refactoring for the next release of the Boss Room sample project. Since Boss Room is open source, you can access the full release notes and changelogs in the [com.unity.multiplayer.samples.coop GitHub repository](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop).
+
+| Release | Date | Changelog |
+|---|---|---|
+| 2.1.0 | 2023-04-27 | [2.1.0](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v2.1.0) |
+| 2.0.4 | 2022-12-14 | [2.0.4](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v2.0.4) |
+| 2.0.3 | 2022-12-09 | [2.0.3](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v2.0.3) |
+| 2.0.2 | 2022-11-01 | [2.0.2](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v2.0.2) |
+| 2.0.1 | 2022-10-25 | [2.0.1](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v2.0.1) |
+| 2.0.1 | 2022-10-06 | [2.0.1](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v2.0.0) |
+| 1.3.1-pre | 2022-09-15 | [1.3.1-pre](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v1.3.1-pre) |
+| 1.3.0-pre | 2022-06-23 | [1.3.0-pre](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v1.2.0-pre) |
+| 1.2.0-pre | 2022-04-28 | [1.2.0-pre](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v1.1.2-pre) |
+| 1.1.2-pre | 2022-04-14 | [1.1.2-pre](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/releases/tag/v1.1.1-pre) |
diff --git a/versioned_docs/version-2.0.0/terms-concepts/client-server.md b/versioned_docs/version-2.0.0/terms-concepts/client-server.md
new file mode 100644
index 000000000..080379109
--- /dev/null
+++ b/versioned_docs/version-2.0.0/terms-concepts/client-server.md
@@ -0,0 +1,26 @@
+---
+id: client-server
+title: Client-server topologies
+---
+
+Client-server is one possible [network topology](network-topologies.md) you can use for your multiplayer game.
+
+## Defining client-server
+
+In a client-server topology, a central server is responsible for running the main simulation and managing all aspects of running the networked game, including simulating physics, spawning and despawning objects, and authorizing client requests. Players connect to the server using separate client programs to see and interact with the game.
+
+Client-server encompasses a number of potential network arrangements. The most common is a dedicated game server, in which a specialized server manages the game and exists solely for that purpose. An alternative client-server arrangement is to have a [listen server](../learn/listenserverhostarchitecture.md), in which the game server runs on the same machine as a client.
+
+## Use cases for client-server
+
+Dedicated servers are often the most expensive network topology, but also offer the highest performance and can provide additional functionality such as competitive client prediction, rollback, and a centralized authority to manage any potential client conflicts. However, this comes at the cost of added latencies when communicating state changes from one client to another, as all state changes must be sent from client to server, processed, and then sent back out to other clients.
+
+Client-server is primarily used by performance-sensitive games, such as first-person shooters, or competitive games where having a central server authority is necessary to minimize cheating and the effects of bad actors.
+
+### Client-server versus distributed authority
+
+The primary differences between client-server and [distributed authority](distributed-authority.md) topologies are latency, cost, and security.
+
+* **Latency**: Client-server networks typically experience more latency, since all changes must be communicated to a relay service, then the server (where updates are authorized), then back out to clients, whereas clients in distributed authority networks have the authority to communicate changes directly to other clients via the relay service.
+* **Cost**: Client-server networks using a dedicated game server are typically an expensive option due to the hardware and running costs involved in maintaining a powerful server machine, although this does allow for higher performance and better [tick rates](../learn/ticks-and-update-rates.md). Distributed authority networks are cheaper, since they lack a dedicated central server and game simulations run solely on clients.
+* **Security**: Because client-server networks have a single central authority, they're more resilient to cheating and bad actors, and can support additional features such as client prediction and rollback.
diff --git a/versioned_docs/version-2.0.0/terms-concepts/distributed-authority.md b/versioned_docs/version-2.0.0/terms-concepts/distributed-authority.md
new file mode 100644
index 000000000..95d37a282
--- /dev/null
+++ b/versioned_docs/version-2.0.0/terms-concepts/distributed-authority.md
@@ -0,0 +1,52 @@
+---
+id: distributed-authority
+title: Distributed authority topologies
+---
+
+Distributed authority is one possible [network topology](network-topologies.md) you can use for your multiplayer game.
+
+:::note Beta feature
+Distributed authority is still in beta. During the beta phase, using the distributed authority service provided by the [Multiplayer Services package](https://docs.unity.com/ugs/en-us/manual/mps-sdk/manual) is free. When distributed authority is fully released, [using the service will incur a cost](https://unity.com/products/gaming-services/pricing).
+:::
+
+## Defining distributed authority
+
+In a distributed authority topology, game clients share responsibility for owning and tracking the state of objects in the network and have the authority to spawn and manage objects themselves, with additional options to configure ownership permissions. A small, lightweight central state service keeps track of changes in spawned object states and routes network traffic. There is no central server simulating the game: all clients run their own partial simulations and communicate their updates directly to other clients (via the central state service).
+
+Distributed authority is also distinct from peer-to-peer models, because it still involves a central service that all clients are connected to, rather than a model where communication is client-to-client, or all clients broadcasting to all other clients.
+
+### Session ownership
+
+Distributed authority provides additional permissions to manage object distribution while also incorporating the concept of a session owner. The session owner is given host-like permissions to handle global game state-related tasks that a typical client-server host handles. As long as global game states are persisted via [NetworkVariable](../basics/networkvariable.md) states, a client will be promoted to session owner if the current session owner leaves a distributed authority session. The newly promoted session owner takes over the management of these global game states.
+
+## Use cases for distributed authority
+
+Using a distributed authority topology is typically not suitable for high-performance competitive games that require an accurate predictive motion model. The distributed authority model successfully addresses a lot of visual and input-related issues, but does have some limitations:
+
+* Since authority and ownership of objects is distributed across clients, there's typically no single physics simulation governing the interaction of all objects. This can require approaching physics-related gameplay differently compared to a traditional client-server context.
+* Depending on the platform and overall design of your product, it can be easier for bad actors to cheat. The authority model gives more trust to individual clients. Evaluate your cheating tolerance when developing with distributed authority.
+
+For game designs that don't require a precise physics simulation or client prediction model (with potentially some form of rollback), a distributed authority approach can be a good option. It's less resource intensive than having a dedicated game server, and can make it simpler to implement many common netcode features when compared with equivalent implementations in a client-server topology.
+
+### Distributed authority versus client-server
+
+The traditional [client-server](client-server.md) model typically includes a service relay to solve connectivity issues, notably Network Address Translation (NAT), between players across different regions and networks. This topology works well for projects that require competitive client prediction, rollback, and a centralized authority – however, it comes at the cost of added latencies when communicating state changes from one client to another.
+
+With a distributed authority topology, a client's state change takes a single client-relative [round trip period of time (RTT)](../lagandpacketloss.md#round-trip-time-and-pings) (½ per client) to be updated on all connected clients. The distributed authority service is more efficient: messages are routed and then processed, whereas client-server topologies require messages to be processed and then, at a later time, conveyed via new messages to all connected clients.
+
+
+
+
+
+
+The distributed authority service is designed to quickly inspect messages, make any necessary changes (such as updating the destination address), forward the message, and then update any object state changes it's tracking. For certain operations like joining an in-progress session, the distributed authority service completely substitutes for a traditional host or server: it already has an up-to-date understanding of the state and can immediately transmit it to the joining client. Compared to a traditional client-server topology, this results in faster delivery of state changes, more balanced bandwidth utilization, and a smoother experience for all players.
+
+## More information about distributed authority
+
+For more information about how distributed authority works in Netcode for GameObjects, see the following pages in the documentation:
+
+- [Distributed authority quickstart](../learn/distributed-authority-quick-start.md)
+- [Understanding ownership and authority](../basics/ownership.md)
+- [Race conditions](../basics/race-conditions.md)
+- [Spawning synchronization](../basics/spawning-synchronization.md)
+- [Deferred despawning](../basics/deferred-despawning.md)
diff --git a/versioned_docs/version-2.0.0/terms-concepts/mutliplayer-terms.md b/versioned_docs/version-2.0.0/terms-concepts/mutliplayer-terms.md
new file mode 100644
index 000000000..7d0826733
--- /dev/null
+++ b/versioned_docs/version-2.0.0/terms-concepts/mutliplayer-terms.md
@@ -0,0 +1,10 @@
+---
+id: mtt-terms
+title: Multiplayer Networking Terminology
+---
+
+The following are essential, high-level terms used in multiplayer networking and Netcode for GameObjects:
+
+import MTTterms from '/static/shared/_terminology.md';
+
+
\ No newline at end of file
diff --git a/versioned_docs/version-2.0.0/terms-concepts/network-topologies.md b/versioned_docs/version-2.0.0/terms-concepts/network-topologies.md
new file mode 100644
index 000000000..88fa4f7c9
--- /dev/null
+++ b/versioned_docs/version-2.0.0/terms-concepts/network-topologies.md
@@ -0,0 +1,50 @@
+---
+id: network-topologies
+title: Network topologies
+---
+
+Network topology defines how a network is arranged. In the context of multiplayer games, this primarily relates to how clients, hosts, and servers are connected and communicate. Different network topologies have different benefits and drawbacks, depending on the type of game you want to make.
+
+The two primary network topologies that Netcode for GameObjects supports are [client-server](#client-server) and [distributed authority](#distributed-authority).
+
+## Client-server
+
+### Dedicated game server
+
+Dedicated servers run the main simulation and manage all aspects of running the networked game. Players connect to the server using separate client programs to see and interact with the game.
+
+Dedicated servers are often the most expensive network topology, but also offer the highest performance and can provide additional functionality such as competitive client prediction, rollback, and a centralized authority to manage any potential client conflicts. However, this comes at the cost of added latencies when communicating state changes from one client to another, as all state changes must be sent from client to server, processed, and then sent back out to other clients.
+
+This network topology is primarily used by performance-sensitive games, such as first-person shooters, or competitive games where having a central server authority is necessary to minimize cheating and the effects of bad actors.
+
+![Dedicated Server](/img/ded_server.png)
+
+### Client-hosted listen server
+
+Listen servers are similar to dedicated game servers, except that the server runs in the same process as a game client. This makes it a cheaper option, but with the disadvantage that the hosting client has to communicate updates over a residential internet connection. Server performance is also degraded because the machine running the server is also generating an output image for the user playing on that machine.
+
+![Client Hosted](/img/client-hosted.png)
+
+## Distributed authority
+
+In a distributed authority topology, game clients share responsibility for owning and tracking the state of objects in the network and have the authority to spawn and manage objects themselves, with additional options to configure ownership permissions. A small, lightweight central state service keeps track of changes in spawned object states and routes network traffic. There is no central server simulating the game: all clients run their own simulations and communicate their updates directly to other clients (via the central state service).
+
+Distributed authority topologies are useful for keeping costs down, and solve a lot of the input-related issues typically addressed using client prediction systems, although the lack of a central authority can make them more vulnerable to cheating and bad actors.
+
+For more details about distributed authority topologies, refer to the [Distributed authority page](distributed-authority.md).
+
+## Other network topologies
+
+### Local or couch multiplayer
+
+Local multiplayer games use a single client runtime instance that can be played by two or more people on the same screen in the same physical location.
+
+### Offline local area network (LAN)
+
+Local area network games aren't connected to the internet, but use a hosted server onsite to support a local network of clients in the same physical location.
+
+### Peer-to-peer (P2P)
+
+A peer-to-peer network is created when two or more computers are connected and share resources without going through a separate server.
+
+![Peer-to-Peer](/img/peer2peer1.png)
diff --git a/versioned_docs/version-2.0.0/troubleshooting/error-messages.md b/versioned_docs/version-2.0.0/troubleshooting/error-messages.md
new file mode 100644
index 000000000..91c551963
--- /dev/null
+++ b/versioned_docs/version-2.0.0/troubleshooting/error-messages.md
@@ -0,0 +1,31 @@
+---
+id: errormessages
+title: Netcode for GameObjects (Netcode) Error Messages
+---
+
+Learn more about Unity error messages, including error collecting, issues that cause them, and how to handle.
+
+## Error Capturing
+
+Error messages are captured and returned through Unity Editor Diagnostics (required) and Roslyn Analyzers.
+
+* Unity ILPP and Editor errors are the source of truth. ILPP occurs in Unity and returns error messages, which prevents you from building/playing your game (hard compile errors).
+* [Roslyn Analyzers](https://devblogs.microsoft.com/dotnet/write-better-code-faster-with-roslyn-analyzers/) provide immediate feedback within the IDE, without jumping back to Unity to let it compile with your new changes.
+
+## NetworkObject errors
+
+**Error:**
+* `Can't find pending soft sync object. Is the projects the same? UnityEngine.Debug:LogError(Object)`
+* `ArgumentNullException: Can't spawn null object Parameter name: netObject`
+
+This exception should only occur if your scenes aren't the same, for example if the scene of your server has a NetworkObject which isn't present in the client scene. Verify the scene objects work correctly by entering playmode in both editors.
+
+## ServerRPC errors
+
+**Error:**
+* Server: `[Netcode] Only owner can invoke ServerRPC that is marked to require ownership`
+* Host: `KeyNotFoundException: The given key wasn't present in the dictionary.`
+
+The ServerRPC should only be used on the server. Make sure to add `isServer` check before calling.
+
+If the call is added correctly but still returns a `nullreferenceexception`, `NetworkManager.Singleton` may be returning `null`. Verify you created the `GameObject` with a `NetworkManager` component, which handles all initialization. `NetworkManager.Singleton` is a reference to a instance of the `NetworkManager` component.
\ No newline at end of file
diff --git a/versioned_docs/version-2.0.0/troubleshooting/troubleshooting.md b/versioned_docs/version-2.0.0/troubleshooting/troubleshooting.md
new file mode 100644
index 000000000..6407a1d1e
--- /dev/null
+++ b/versioned_docs/version-2.0.0/troubleshooting/troubleshooting.md
@@ -0,0 +1,43 @@
+---
+id: troubleshooting
+title: Troubleshooting
+---
+
+See the following information for common troubleshooting for Netcode for GameObjects.
+
+## NullReferenceException when trying to start a server/host/client
+
+**Issue:** When trying to start a server, host, or client by executing one of these lines of code:
+
+```csharp
+NetworkManager.Singleton.StartServer()
+NetworkManager.Singleton.StartHost()
+NetworkManager.Singleton.StartClient()
+```
+
+The following exception is thrown:
+
+```csharp
+NullReferenceException: Object reference not set to an instance of an object
+```
+
+**Solution:** You most likely forgot to add the `NetworkManager` component to a game object in your scene.
+
+## NullReferenceException when trying to send an RPC to the server
+
+**Issue:** When the client tries to run `InvokeServerRpc`, the following exception is thrown:
+
+```csharp
+NullReferenceException: Object reference not set to an instance of an object
+```
+
+**Solution:** You most likely forgot to `Spawn()` your object. Run `Spawn()` on your NetworkObject component as the server to fix this issue.
+
+## Server build is using 100% CPU
+
+**Issue**: When running an MLAPI server created from a server build it has a cpu usage of 100% blocking all my other applications.
+
+**Solution**: Unity server builds try to push as many Updates per second as possible. On a server this is most often not necessary. You can limit the target frame rate to reduce the amounts of Updates with this:
+```csharp
+Application.targetFrameRate = 30;
+```
\ No newline at end of file
diff --git a/versioned_docs/version-2.0.0/tutorials/command-line-helper.md b/versioned_docs/version-2.0.0/tutorials/command-line-helper.md
new file mode 100644
index 000000000..bd503b85a
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/command-line-helper.md
@@ -0,0 +1,185 @@
+---
+id: command-line-helper
+title: Create a command-line helper for testing
+---
+
+This page walks you through how to create a command-line helper that launches your project outside the Unity Editor to make testing builds easier.
+
+Using a command-line helper script to launch multiple instances of a game build isn't the only way to test a multiplayer game. You can also use the Unity Editor or the [Multiplayer Play Mode package](https://docs-multiplayer.unity3d.com/mppm/current/about/).
+
+## Create the command-line helper
+
+1. Right-click the **Assets** folder in the **Projects** tab, then select **Create** > **Folder**.
+2. Name the new folder **Scripts**.
+3. Right-click the **Scripts** folder you created, then select **Create** > **C# Script**.
+4. Name the script **NetworkCommandLine**.
+5. Right-click on **NetworkManager** within the **Hierarchy** list, then select **Create Empty**.
+6. Name the new GameObject **NetworkCommandLine**.
+7. With the `NetworkCommandLine` GameObject selected, select **Add Component** from the **Inspector** tab.
+8. For the new component, select **Scripts** > **Network Command Line** (the `NetworkCommandLine.cs` script you created earlier).
+9. Double-click on the **NetworkCommandLine.cs** script from the **Project** tab to open it in a text editor.
+10. Edit the `NetworkCommandLine.cs` script to match the following code snippet:
+
+```csharp
+using System.Collections.Generic;
+using Unity.Netcode;
+using UnityEngine;
+
+public class NetworkCommandLine : MonoBehaviour
+{
+ private NetworkManager netManager;
+
+ void Start()
+ {
+ netManager = GetComponentInParent();
+
+ if (Application.isEditor) return;
+
+ var args = GetCommandlineArgs();
+
+ if (args.TryGetValue("-mode", out string mode))
+ {
+ switch (mode)
+ {
+ case "server":
+ netManager.StartServer();
+ break;
+ case "host":
+ netManager.StartHost();
+ break;
+ case "client":
+
+ netManager.StartClient();
+ break;
+ }
+ }
+ }
+
+ private Dictionary GetCommandlineArgs()
+ {
+ Dictionary argDictionary = new Dictionary();
+
+ var args = System.Environment.GetCommandLineArgs();
+
+ for (int i = 0; i < args.Length; ++i)
+ {
+ var arg = args[i].ToLower();
+ if (arg.StartsWith("-"))
+ {
+ var value = i < args.Length - 1 ? args[i + 1].ToLower() : null;
+ value = (value?.StartsWith("-") ?? false) ? null : value;
+
+ argDictionary.Add(arg, value);
+ }
+ }
+ return argDictionary;
+ }
+}
+```
+
+11. Save the file, then return to the Unity Editor.
+12. Open the Build Settings window by selecting **File** > **Build Settings**.
+13. Select **Player Settings…**.
+14. Beneath **Settings for PC, Mac, & Linux Standalone**, select **Resolution and Presentation** to open the section options.
+15. From **Resolution** > **Fullscreen Mode**, change **Fullscreen Window** to **Windowed**.
+16. Return to the Editor main window and save your scene.
+
+## Test the command-line helper
+
+Follow these instructions to test that the command-line helper script works.
+
+1. Select **File** > **Build and Run**.
+2. Create a new folder called `Build` inside your Hello World project folder.
+3. **Save As** the binary `HelloWorld`.
+
+Saving the project in this way causes the Unity Editor to build and launch the project in a new window. After it launches (and displays the plane), close the window you just launched.
+
+### Test on Windows
+
+To test on Windows:
+
+1. Open the Command Prompt.
+2. Use the following command to launch the server and the client. Make sure to replace the placeholder text within the angled brackets (`< >`) for all commands.
+ * You might get a [UAC prompt](https://learn.microsoft.com/windows/security/identity-protection/user-account-control/how-user-account-control-works) requesting permission to run the executable. Allow the executable to run to continue.
+
+Command to start the server:
+
+```cmd
+\HelloWorld.exe -mode server
+```
+
+Command to start the client:
+
+```cmd
+\HelloWorld.exe -mode client
+```
+
+To run these commands on a single line:
+
+```cmd
+\HelloWorld.exe -mode server & \HelloWorld.exe -mode client
+```
+
+Here's an example of what your command might look like when you replace the placeholder text in `< >`:
+
+```cmd
+\HelloWorld.exe -mode server & \HelloWorld.exe -mode client
+```
+
+:::important
+There's no standard out stream on Windows by default, so you need to view the `Debug.log` file for the outputs. You can find the `Debug.log` files in:
+
+```cmd
+C:\Users\username\AppData\LocalLow\CompanyName\ProductName\Player.log
+```
+
+Where the `CompanyName` defaults to `DefaultCompany` for a new project and `ProductName` equals to the project's name.
+
+You can also change the Windows commands to create a `log.txt` file in the same folder as your `HelloWorld` folder.
+
+Change the commands as follows:
+
+Server command:
+
+```cmd
+\HelloWorld.exe -logfile log-server.txt -mode server
+```
+
+Client command:
+
+```cmd
+\HelloWorld.exe -logfile log-client.txt -mode client
+```
+
+Example (Running as a single command line):
+
+```cmd
+C:\Users\sarao>HelloWorld\Build\HelloWorld.exe -logfile log-server.txt -mode server & HelloWorld\Build\HelloWorld.exe -logfile log-client.txt -mode client
+```
+
+:::
+
+### Test on macOS
+
+Use the following instructions if you're using macOS:
+
+1. Open the Terminal app.
+2. Use the following command to launch the server and the client. Make sure to replace the placeholder text within the angled brackets (`< >`) for all commands.
+
+Command to start the server:
+
+```shell
+/HelloWorld.app/Contents/MacOS/ -mode server -logfile -
+```
+
+Command to start the client:
+
+```shell
+/HelloWorld.app/Contents/MacOS/ -mode client -logfile -
+```
+
+To run both as a single command:
+
+```shell
+/HelloWorld.app/Contents/MacOS/ -mode server -logfile - & HelloWorld.app/Contents/MacOS/ -mode client -logfile -
+```
diff --git a/versioned_docs/version-2.0.0/tutorials/get-started-with-ngo.md b/versioned_docs/version-2.0.0/tutorials/get-started-with-ngo.md
new file mode 100644
index 000000000..4c202e35b
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/get-started-with-ngo.md
@@ -0,0 +1,587 @@
+---
+id: get-started-ngo
+title: Client-server quickstart for Netcode for GameObjects
+---
+
+Use this guide to learn how to create your first [client-server](../terms-concepts/client-server.md) Netcode for GameObjects project. It walks you through creating a simple Hello World project that implements the basic features of Netcode for GameObjects.
+
+Refer to [Testing the command line helper](command-line-helper.md) to learn how to test your builds with a command-line helper.
+
+## Prerequisites
+
+Before you begin, you need the following:
+
+- An active Unity account with a valid license.
+- The [Unity Hub](https://unity.com/download).
+- A supported version of the Unity Editor. Refer to the [Netcode for GameObjects requirements](https://docs-multiplayer.unity3d.com/netcode/current/installation).
+
+Before continuing, create a new project using Unity Editor version 2022.3 or later.
+
+### Create an `Assets/Scripts/` folder
+
+If you don't already have an `Assets/Scripts/` folder, create one now:
+
+1. Right-click the **Assets** folder in the **Projects** tab, then select **Create** > **Folder**.
+2. Name the new folder **Scripts**.
+
+This is where you'll keep all your scripts as part of this Hello World project.
+
+## Install Netcode for GameObjects
+
+Refer to [Install Netcode for GameObjects](https://docs-multiplayer.unity3d.com/netcode/current/installation).
+
+## Add the basic components
+
+This section guides you through adding the essential components of a networked game:
+
+- [A NetworkManager component](#create-the-networkmanager-component)
+- [A player object](#create-an-object-to-spawn-for-each-connected-player)
+- [A scene](#add-your-scene-to-the-build)
+
+### Create the NetworkManager component
+
+This section guides you through creating a NetworkManager component.
+
+First, create the NetworkManager component:
+
+1. Right-click in the **Hierarchy** tab, then select **Create Empty** to create an empty GameObject.
+
+![](/img/get-started-ngo/ngo-10.png)
+
+2. Rename the empty GameObject **NetworkManager**.
+
+![](/img/get-started-ngo/ngo-11.png)
+
+3. Select **NetworkManager**, then select **Add Component** from the **Inspector** tab.
+
+![](/img/get-started-ngo/ngo-6.png)
+
+4. Select **Netcode** > **NetworkManager** from the component list.
+
+![](/img/get-started-ngo/ngo-1.png)
+
+5. In the Inspector tab, locate the Unity Transport section, then select **UnityTransport** as the **Protocol type**.
+
+![](/img/get-started-ngo/ngo-13.png)
+
+![](/img/get-started-ngo/ngo-14.png)
+
+6. Save the scene by pressing **Ctrl/Cmd** + **S** (or by selecting **File** > **Save**).
+
+### Create an object to spawn for each connected player
+
+:::important
+
+When you drop the prefab into the **PlayerPrefab** slot, you're telling the library that when a client connects to the game, it automatically spawns this prefab as the character for the connecting client. Netcode for GameObjects won't spawn a player object if you don't have any prefab set as the **PlayerPrefab**. Refer to [Player Objects](../basics/networkobject.md#finding-playerobjects).
+
+:::
+
+This section guides you through creating an object that spawns for each connected player.
+
+1. In the Unity Editor, right-click within the **Hierarchy** tab, then select **3D Object** > **Capsule**.
+2. Name the Capsule Object **Player**.
+3. With Player selected, add a NetworkObject component in the **Inspector** tab by selecting **Add Component** > **Netcode** > **NetworkObject**.
+4. Right-click within the **Assets** folder under the **Project** tab, then select **Create** > **Folder**.
+5. Name the folder **Prefabs**.
+6. Make the **Player** object you created earlier into a prefab by dragging it from the **Hierarchy** tab into the **Prefabs** folder.
+
+![](/img/get-started-ngo/ngo-12.png)
+
+7. Delete the Player from the scene by selecting the Player capsule within the **Scene** tab, then pressing the **Delete** key (or **Cmd** + **Delete** for macOS).
+ * You can remove the Player GameObject from the scene because you assign this network prefab to the Player prefab property in the NetworkManager component. The library doesn't support defining a player object as an in-scene placed NetworkObject.
+8. Select **NetworkManager**.
+9. With NetworkManager selected, locate the **PlayerPrefab** field in the **Inspector** tab.
+
+![](/img/get-started-ngo/ngo-9.png)
+
+10. Drag the **Player** prefab from the **Project** tab into the **PlayerPrefab** slot within the **NetworkManager** component in the **Inspector** tab.
+
+![](/img/get-started-ngo/ngo-5.png)
+
+11. Add a 3D Plane (centered at 0,0,0) to the scene by right-clicking in the **Hierarchy** tab, then selecting **3D Object** > **Plane**.
+ * Adding the Plane adds a visual reference point to visualize the Player prefab's position, but it isn't necessary.
+![](/img/get-started-ngo/ngo-7.png)
+
+12. Save the scene by pressing **Ctrl/Cmd** + **S** (selecting **File** > **Save**).
+
+### Scene management and the scenes in build list
+
+Netcode for GameObjects comes with an integrated scene management solution that helps you synchronize what scenes should be loaded by all connected clients. The `NetworkManager` **Enable Scene Management** property, enabled by default, determines whether the integrated scene management solution will be used for your project (or not). In order for the integrated scene management solution to work properly, you must add any scene you want to be synchronized to the scenes in build list. This section guides you through adding your current scene to the scenes in build list.
+
+1. Open the Build Settings window by selecting **File** > **Build Settings**.
+2. Select **Add Open Scenes**.
+3. **Scenes/SampleScene** is listed under **Scenes In Build**. You can close the Build Settings window.
+
+## Test starting a host in the Unity Editor
+
+Now that you have a **NetworkManager**, assigned a **PlayerPrefab**, and added your current scene to the scenes in build test, you can quickly verify everything is functioning/configured correctly via entering play mode in the Unity Editor. By starting a host, you are starting `NetworkManager` as both a server and a client at the same time.
+
+You can test your Hello World project using the Unity Editor or a command-line helper. If you choose the latter, refer to [Create a command line helper](../tutorials/command-line-helper/). Otherwise, refer to the following instructions to test using the Unity Editor. Only the Plane appears on the server until the first client connects. Then, Netcode for GameObjects spawns a new Player prefab for each connected client; however, they overlap in the Game view.
+
+1. Select **Play** from the top of the Unity Editor to start the scene.
+
+![](/img/get-started-ngo/ngo-8.png)
+
+2. Select **NetworkManager** from the **Hierarchy** list.
+
+![](\img\get-started-ngo\ngo-2.png)
+
+3. With **NetworkManager** selected (in the Hierarchy tab), select **Start Host** from the **Inspector** tab. Alternatively, you can use the in-game GUI buttons.
+
+![](/img/get-started-ngo/ngo-3.png)
+
+If it works correctly, the option to **Stop Host** displays in the **Inspector** tab.
+
+
+### The `HelloWorldManager.cs` script
+
+Now that you have verified everything is configured correctly, you will want to have the ability to start the `NetworkManager` whether in play mode, as a stand alone build, or in another MPPM instance. This section will walk you through creating the `HelloWorldManager.cs` component script.
+
+1. Create a new script in the `Scripts` folder named `HelloWorldManager.cs`.
+2. Add this component to the `NetworkManager` `GameObject` in your scene.
+3. Copy the following code into the `HelloWorldManager.cs` script:
+
+```csharp
+using Unity.Netcode;
+using UnityEngine;
+
+namespace HelloWorld
+{
+ public class HelloWorldManager : MonoBehaviour
+ {
+ private NetworkManager m_NetworkManager;
+
+ void Awake()
+ {
+ m_NetworkManager = GetComponent();
+ }
+
+ void OnGUI()
+ {
+ GUILayout.BeginArea(new Rect(10, 10, 300, 300));
+ if (!m_NetworkManager.IsClient && !m_NetworkManager.IsServer)
+ {
+ StartButtons();
+ }
+ else
+ {
+ StatusLabels();
+
+ SubmitNewPosition();
+ }
+
+ GUILayout.EndArea();
+ }
+
+ static void StartButtons()
+ {
+ if (GUILayout.Button("Host")) m_NetworkManager.StartHost();
+ if (GUILayout.Button("Client")) m_NetworkManager.StartClient();
+ if (GUILayout.Button("Server")) m_NetworkManager.StartServer();
+ }
+
+ static void StatusLabels()
+ {
+ var mode = m_NetworkManager.IsHost ?
+ "Host" : m_NetworkManager.IsServer ? "Server" : "Client";
+
+ GUILayout.Label("Transport: " +
+ m_NetworkManager.NetworkConfig.NetworkTransport.GetType().Name);
+ GUILayout.Label("Mode: " + mode);
+ }
+
+ static void SubmitNewPosition()
+ {
+ if (GUILayout.Button(m_NetworkManager.IsServer ? "Move" : "Request Position Change"))
+ {
+ if (m_NetworkManager.IsServer && !m_NetworkManager.IsClient )
+ {
+ foreach (ulong uid in m_NetworkManager.ConnectedClientsIds)
+ m_NetworkManager.SpawnManager.GetPlayerNetworkObject(uid).GetComponent().Move();
+ }
+ else
+ {
+ var playerObject = m_NetworkManager.SpawnManager.GetLocalPlayerObject();
+ var player = playerObject.GetComponent();
+ player.Move();
+ }
+ }
+ }
+ }
+}
+```
+
+In your Hello World project, you created a NetworkManager by adding the pre-created NetworkManager component to a `GameObject`. This component allows you to start a Host, Client, or Server in Play Mode via the inspector view. The `HelloWorldManager.cs` script simplifies and extends this functionality by creating a runtime/play mode UI menu that allows you to select the three different `NetworkManager` modes you can start:
+
+- The **Host** starts the server and joins as a client.
+- The **Client** joins the server as a client player.
+- The **Server** starts the game as a server without instantiating a player.
+
+The `HelloWorldManager.cs` script accomplishes this menu within the `StartButtons().` After you select a button, the `StatusLabels()`method adds a label on-screen to display which mode you have selected. This helps distinguish Game view windows from each other when testing your multiplayer game.
+
+```csharp
+ static void StartButtons()
+ {
+ if (GUILayout.Button("Host")) m_NetworkManager.StartHost();
+ if (GUILayout.Button("Client")) m_NetworkManager.StartClient();
+ if (GUILayout.Button("Server")) m_NetworkManager.StartServer();
+ }
+
+ static void StatusLabels()
+ {
+ var mode = m_NetworkManager.IsHost ?
+ "Host" : m_NetworkManager.IsServer ? "Server" : "Client";
+
+ GUILayout.Label("Transport: " +
+ m_NetworkManager.NetworkConfig.NetworkTransport.GetType().Name);
+ GUILayout.Label("Mode: " + mode);
+ }
+```
+
+As seen in the earlier code snippet, the `HelloWorldManager.cs` script also uses the NetworkManager's instance via its singleton to grab properties like the `IsClient`, `IsServer`, and `IsLocalClient`. The `IsClient` and `IsServer` properties dictate the established connection state.
+
+The `HelloWorldManager.cs` script also introduces a new method called `SubmitNewPosition()` that the `HelloWorldPlayer` script uses to [create a simple RPC call](#add-simple-rpc-use).
+
+## Adding RPCs (Remote Procedure Calls)
+
+This section guides you through adding basic RPCs to the project. Save your scripts in your `Assets/Scripts/` folder. RPCs are used to call functions on remote clients or the server.
+
+Create a script named `RpcTest.cs`:
+
+1. In the **Project** tab, select **Assets** > **Scripts**.
+2. Right-click in the **Scripts** folder and select **Create** > **C# Script**.
+3. Name the script `RpcTest`.
+
+Add the `RpcTest.cs` script to the Player prefab:
+
+1. Select the **Player** prefab in **Assets** > **Prefabs**.
+2. In the **Inspector** tab (with the Player prefab selected), select **Add Component**.
+3. Select **Scripts** > **Rpc Test**.
+
+Edit the `RpcTest.cs` script:
+
+1. In the **Project** tab, select **Assets** > **Scripts** > **`RpcTest`**.
+2. In the **Inspector** tab (with the script selected), select **Open**. This opens this script in the default local text editor.
+3. Edit the `RpcTest.cs` script to match the following:
+
+```csharp
+using Unity.Netcode;
+using UnityEngine;
+
+public class RpcTest : NetworkBehaviour
+{
+ public override void OnNetworkSpawn()
+ {
+ if (!IsServer && IsOwner) //Only send an RPC to the server from the client that owns the NetworkObject of this NetworkBehaviour instance
+ {
+ ServerOnlyRpc(0, NetworkObjectId);
+ }
+ }
+
+ [Rpc(SendTo.ClientsAndHost)]
+ void ClientAndHostRpc(int value, ulong sourceNetworkObjectId)
+ {
+ Debug.Log($"Client Received the RPC #{value} on NetworkObject #{sourceNetworkObjectId}");
+ if (IsOwner) //Only send an RPC to the owner of the NetworkObject
+ {
+ ServerOnlyRpc(value + 1, sourceNetworkObjectId);
+ }
+ }
+
+ [Rpc(SendTo.Server)]
+ void ServerOnlyRpc(int value, ulong sourceNetworkObjectId)
+ {
+ Debug.Log($"Server Received the RPC #{value} on NetworkObject #{sourceNetworkObjectId}");
+ ClientAndHostRpc(value, sourceNetworkObjectId);
+ }
+}
+```
+
+4. Save the Scene by pressing **Ctrl/Cmd** + **S** (or by selecting **File** > **Save**).
+
+### Test the RPCs
+
+This section guides you through testing the RPCs you added in the earlier section.
+
+1. Select **File** > **Build Setting...**.
+2. In the **Build Setting** window, configure your build settings as needed.
+3. Click **Build** and choose a location to save your first build.
+4. After the first build is done, return to the **Build Setting** window.
+5. Click **Build** again and choose a different location to save your second build.
+ * Alternatively, you can run the builds by:
+ - Launching the client and server together in a terminal, as shown in [Testing the command line helper](command-line-helper.md).
+ - Using the Multiplayer Play Mode package, which lets you run multiple instances of the Unity Editor to test multiplayer functionality. Refer to [Multiplayer Play Mode](https://docs-multiplayer.unity3d.com/tools/current/mppm) to learn more.
+
+After the client and server spawn, a log displays in the **Console** of the client and server sending RPC messages to each other.
+
+The client kicks off the exchange in its `OnNetworkSpawn` call for the first time with a counter value of `0`. It then makes an RPC call to the server with the next value. The server receives this and calls the client. The Console displays the following for the server and client respectively.
+
+```log
+Server Received the RPC #0 on NetworkObject #1
+Server Received the RPC #1 on NetworkObject #1
+Server Received the RPC #2 on NetworkObject #1
+Server Received the RPC #3 on NetworkObject #1
+...
+```
+
+```log
+Client Received the RPC #0 on NetworkObject #1
+Client Received the RPC #1 on NetworkObject #1
+Client Received the RPC #2 on NetworkObject #1
+Client Received the RPC #3 on NetworkObject #1
+...
+```
+
+Only the client owning the NetworkObject owning the `RpcTest` script will send RPCs on the server, but they will all receive RPCs from the server. This means that if you test with multiple clients the consoles will log RPCs received once per NetworkObject per iteration on the server and all clients. If testing with a host and a client, you will see the following on the host's **Console**. This is because as a server it will receive the other client's server RPCs and as a client it will also receive its own client RPCs.
+
+```log
+Server Received the RPC #0 on NetworkObject #2
+Client Received the RPC #0 on NetworkObject #2
+Server Received the RPC #1 on NetworkObject #2
+Client Received the RPC #1 on NetworkObject #2
+Server Received the RPC #2 on NetworkObject #2
+Client Received the RPC #2 on NetworkObject #2
+Server Received the RPC #3 on NetworkObject #2
+Client Received the RPC #3 on NetworkObject #2
+...
+```
+
+:::note
+
+The `NetworkObjectId` here is `2` because the host also has a NetworkObject with the `RpcTest` script spawned for it, but it won't send the initial RPC starting the chain because it's a server.
+
+:::
+
+## Adding Netcode script to your player prefab
+
+At this point, you should have set up script and should have experimented with sending and receiving RPCs via the `RpcTest.cs` script above. This next step demonstrates how you can add additional netcode logic to your player prefab via the `HelloWorldPlayer.cs` script.
+
+1. Create a new script in the `Scripts` folder named `HelloWorldPlayer.cs`.
+2. Copy the following code into the `HelloWorldPlayer.cs` script and save it:
+
+```csharp
+using Unity.Netcode;
+using UnityEngine;
+
+namespace HelloWorld
+{
+ public class HelloWorldPlayer : NetworkBehaviour
+ {
+ public NetworkVariable Position = new NetworkVariable();
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsOwner)
+ {
+ Move();
+ }
+ }
+
+ public void Move()
+ {
+ SubmitPositionRequestRpc();
+ }
+
+ [Rpc(SendTo.Server)]
+ void SubmitPositionRequestRpc(RpcParams rpcParams = default)
+ {
+ var randomPosition = GetRandomPositionOnPlane();
+ transform.position = randomPosition;
+ Position.Value = randomPosition;
+ }
+
+ static Vector3 GetRandomPositionOnPlane()
+ {
+ return new Vector3(Random.Range(-3f, 3f), 1f, Random.Range(-3f, 3f));
+ }
+
+ void Update()
+ {
+ transform.position = Position.Value;
+ }
+ }
+}
+```
+
+#### A Review of the `HelloWorldPlayer.cs` script
+
+The `HelloWorldPlayer.cs` script adds some basic movement to the Hello World project player. Both the server player and the client player can start player movement. However, the movement occurs through the server's position NetworkVariable, which means the server player can move immediately, but the client player must request a movement from the server, wait for the server to update the position NetworkVariable, then replicate the change locally.
+
+The `HelloWorldPlayer` class inherits from `Unity.Netcode`'s `NetworkBehaviour` instead of `MonoBehaviour`. This allows you to customize the networking code as you override what happens when the Player spawns.
+
+```csharp
+public class HelloWorldPlayer : NetworkBehaviour
+```
+
+For multiplayer games, every object runs on at least two machines: player one and player two. Because of this, you need to ensure both machines have the same behavior and have the correct information about the object. One of the instances that come into play then is to understand how the Player moves. Only one player controls how the Player object moves. The following code enforces this by validating if the machine running the code is the player's owner.
+
+```csharp
+ public override void OnNetworkSpawn()
+ {
+ if (IsOwner)
+ {
+ Move();
+ }
+ }
+```
+
+Any `MonoBehaviour` implementing a NetworkBehaviour component can override the Netcode for GameObjects method `OnNetworkSpawn()`. The `OnNetworkSpawn()` method fires in response to the NetworkObject spawning. The `HelloWorldPlayer` class overrides `OnNetworkSpawn` because clients and the server run different logic. You can override this behavior on any NetworkBehaviour component.
+
+Because the server and client can be the same machine and the Player's owner (aka Host), you want further to differentiate the two and have different Move behavior for each.
+
+If the current player is the server, the code determines a random position to spawn the Player. You can't find the spawn location if the current player is the client. You have to get it from the server.
+
+```csharp
+ public void Move()
+ {
+ SubmitPositionRequestRpc();
+ }
+
+ [Rpc(SendTo.Server)]
+ void SubmitPositionRequestRpc(RpcParams rpcParams = default)
+ {
+ var randomPosition = GetRandomPositionOnPlane();
+ transform.position = randomPosition;
+ Position.Value = randomPosition;
+ }
+
+ void Update()
+ {
+ transform.position = Position.Value;
+ }
+```
+
+#### Positioning the player using an RPC
+
+This section walks you through the `HelloWorldPlayer.cs` portion of the script that declares the `SubmitPositionRequestRpc` RPC.
+
+If the player is a server-owned player at `OnNetworkSpawn()`, you can immediately move this player, as suggested in the following code.
+
+```csharp
+ SubmitPositionRequestRpc();
+```
+
+You can call this `Rpc` when the player is a client or a server. When you call an `Rpc` with `SendTo.Server` on the server side, it executes in the same way as a local function call by default.
+
+The `Rpc` sets the position NetworkVariable on the server's instance of the player by just picking a random point on the plane.
+
+```csharp
+ [Rpc(SendTo.Server)]
+ void SubmitPositionRequestRpc(RpcParams rpcParams = default)
+ {
+ var randomPosition = GetRandomPositionOnPlane();
+ transform.position = randomPosition;
+ Position.Value = randomPosition;
+ }
+```
+
+The server instance of the player modifies the `Position` `NetworkVariable` through the `Rpc`. If the player is a client, it must apply the position locally inside the `Update` loop. (Since the two values are the same on the server, the server can run the same logic with no side effects, but you could also add `if(IsClient)` here.)
+
+```csharp
+ void Update()
+ {
+ transform.position = Position.Value;
+ }
+```
+
+Because the `HelloWorldPlayer.cs` script handles the position NetworkVariable, the `HelloWorldManager.cs` script can define the contents of `SubmitNewPosition()`.
+
+```csharp
+ static void SubmitNewPosition()
+ {
+ if (GUILayout.Button(m_NetworkManager.IsServer ? "Move" : "Request Position Change"))
+ {
+ var playerObject = m_NetworkManager.SpawnManager.GetLocalPlayerObject();
+ var player = playerObject.GetComponent();
+ player.Move();
+ }
+ }
+```
+
+The method in the code block above adds a contextual button that changes depending on whether the client is a server or a client. When you press the button this method creates, it finds your local player and calls `Move()`.
+
+You can now create a build that shows the concepts outlined above.
+
+Create two build instances: one for the host and the other for the client (to join the host's game).
+
+Both build instances can move the player with the GUI button. The server moves the player immediately and replicates the movement on the client.
+
+The client can request a new position, instructing the server to change that instance's position `NetworkVariable`. After the server updates the position `NetworkVariable`, the client applies that `NetworkVariable` position inside its `Update()` method.
+
+## Add the `HelloWorldPlayer.cs` script to the Player prefab
+
+This section guides you through adding the `HelloWorldPlayer.cs` script to the Player prefab.
+
+Select the Player prefab:
+
+1. From the **Project** tab, select **Assets** > **Prefabs**.
+2. Select **Player**.
+
+Add the `HelloWorldPlayer.cs` script to the Player prefab as a component:
+
+1. With the Player prefab selected, select **Add Component** from the Inspector tab.
+2. Select **Scripts** > **Hello World** > **Hello World Player**.
+
+
+## Add a NetworkTransform
+
+This section guides you through adding a `NetworkTransform` component that moves the player. `NetworkTransform` is a component used to synchronize the position, rotation, and scale of objects across the network.
+
+Add a NetworkTransform component to the Player prefab:
+
+1. Select the **Player** prefab in Assets > Prefabs.
+2. In the **Inspector** tab (with the Player prefab selected), select **Add Component**.
+3. Select **Netcode** > **NetworkTransform**.
+
+Create a script named `NetworkTransformTest.cs`.
+
+1. In the **Project** tab, go to **Assets** > **Scripts**.
+2. Right-click, then select **Create** > **C# Script**.
+3. Name it `NetworkTransformTest`.
+
+Add the `NetworkTransformTest` script to the Player prefab:
+
+1. Select the **Player** prefab in **Assets** > **Prefabs**.
+2. In the **Inspector** tab (with the Player prefab selected), select **Add Component**.
+3. Select **Scripts** > **Network Transform Test**.
+
+Edit the `NetworkTransformTest.cs` script:
+
+1. In the **Project** tab, select **Assets** > **Scripts** > **`NetworkTransformTest`**.
+2. In the **Inspector** tab (with the script selected), select **Open**. This opens this script in the default local text editor.
+3. Edit the `NetworkTransformTest.cs` script to match the following:
+
+```csharp
+using System;
+using Unity.Netcode;
+using UnityEngine;
+
+public class NetworkTransformTest : NetworkBehaviour
+{
+ void Update()
+ {
+ if (IsServer)
+ {
+ float theta = Time.frameCount / 10.0f;
+ transform.position = new Vector3((float) Math.Cos(theta), 0.0f, (float) Math.Sin(theta));
+ }
+ }
+}
+```
+
+4. Save the scene by pressing **Ctrl/Cmd** + **S** (or by selecting **File** > **Save**).
+
+### Test the NetworkTransform
+
+This section guides you through testing the NetworkTransform you added in the earlier section.
+
+1. Select **File** > **Build Setting...**.
+2. In the **Build Setting** window, configure your build settings as needed.
+3. Click **Build** and choose a location to save your first build.
+4. After the first build is done, return to the **Build Setting** window.
+5. Click **Build** again and choose a different location to save your second build.
+ * Alternatively, you can run the builds by:
+ - Launching the client and server together in a terminal, as shown in [Testing the command line helper](command-line-helper.md).
+ - Using the Multiplayer Play Mode package, which lets you run multiple instances of the Unity Editor to test multiplayer functionality. Refer to [Multiplayer Play Mode](https://docs-multiplayer.unity3d.com/tools/current/mppm) to learn more.
+
+After the client and server spawn, the player capsule moves in a circle on both the client and the server.
diff --git a/versioned_docs/version-2.0.0/tutorials/goldenpath_series/gp_intro.md b/versioned_docs/version-2.0.0/tutorials/goldenpath_series/gp_intro.md
new file mode 100644
index 000000000..13b7da158
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/goldenpath_series/gp_intro.md
@@ -0,0 +1,31 @@
+---
+id: gp_intro
+title: Learning with Golden Path
+description: Introduction to the Golden Path series, explaining the aim of the series
+---
+
+The Hello World/Golden Path series is meant to guide you through the Netcode installation and implement some of the basic features of Netcode. They also provide a way to test if your installation and feature implementations are correct.
+
+You should start with the [Hello World guide](../helloworld.md) as the base before moving to [Golden Path One](gp_module_one.md) and [Golden Path Two](gp_module_two.md).
+
+:::important Future plans for Hello World and Golden Paths
+We are planning to revamp the Hello World and Golden Paths series to be far more useful. For users that have used these docs in the past may have noticed a lot of repetition between the Golden Paths and Hello World tutorials, this first phase was to make the Hello World and Golden Paths more cohesive and remove the repetition.
+
+Next steps will likely involve the existing Golden Path series to be completely part of Hello World as a series, and the Golden Path series become a completely different experience that is more use case focused and more relatable to the game building experience.
+:::
+
+
+
+
+|
Hello World
|
Golden Path One
|
+| --- | --- |
+| [Creating a new project](../helloworld.md#create-a-new-project-in-unity) [Installing Netcode](../helloworld.md#install-netcode) [Creating and testing the basic networking building blocks](../helloworld.md#create-the-basic-components) | [Editor modes (Host Server and Client)](gp_module_one.md#adding-editor-modes-to-hello-world) [Basic player movement](gp_module_one.md#adding-basic-movement-to-the-player-object) [Basic RPC and Network variable use](gp_module_one.md#some-simple-rpc-use) |
+
diff --git a/versioned_docs/version-2.0.0/tutorials/goldenpath_series/gp_module_one.md b/versioned_docs/version-2.0.0/tutorials/goldenpath_series/gp_module_one.md
new file mode 100644
index 000000000..9ebc0c291
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/goldenpath_series/gp_module_one.md
@@ -0,0 +1,458 @@
+---
+id: goldenpath_one
+title: Golden Path Module One
+description: Tutorial that explains adding scripts to objects, editor modes (Host Server and Client), basic player movement and basic RPC use.
+---
+
+Golden Path One continues on the work from [Hello World](../helloworld.md) to add a few more features.
+
+This guide covers:
+
+- Adding scripts to your objects
+- Adding editor modes inside your game (Host, Server, and Client)
+- Basic Player Movement
+- Permissions
+- Basic RPC use
+
+:::note
+The videos on this page were removed because they were out-of-date and caused more confusion than help. All videos in the Hello World and Golden Path series will be recreated and added back at a later time.
+:::
+
+## Prerequisites
+
+You should have completed the [Hello World project](../helloworld.md) before starting this tutorial. We use Hello World as the base for this and other Golden Path modules.
+
+## Open your Hello World project
+
+1. Open Unity Hub.
+1. Select `Hello World` from the list of projects displayed.
+
+## Adding Editor Modes to Hello World
+
+In the HelloWorld project, you created a **NetworkManager** by adding the pre-created **NetworkManager** component. In Play Mode, the NetworkManager shows Editor buttons labeled `Start Host`, `Start Client`, and `Start Server` in its inspector. These call the `StartHost`, `StartClient` and `StartServer` methods of the **NetworkManager** respectively, to initiate a networking session. Inside the `HelloWorldManager.cs` script, we define two methods which mimic this functionality via UI buttons and status labels.
+
+1. Create an empty `GameObject` rename it **HelloWorldManager**.
+2. Open the **Scripts** Folder.
+3. Create a script called `HelloWorldManager`.
+4. Open the `HelloWorldManager.cs` script.
+5. Edit the `HelloWorldManager.cs` script to match the following.
+
+:::tip
+You can copy the script from here and paste it into your file.
+ 1. Select the code sample.
+ 1. Click **Copy** in the top right corner.
+ 1. Paste it into your code editor.
+:::
+
+
+Click to show/hide the Code.
+
+
+```csharp
+
+using Unity.Netcode;
+using UnityEngine;
+
+namespace HelloWorld
+{
+ public class HelloWorldManager : MonoBehaviour
+ {
+ void OnGUI()
+ {
+ GUILayout.BeginArea(new Rect(10, 10, 300, 300));
+ if (!NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer)
+ {
+ StartButtons();
+ }
+ else
+ {
+ StatusLabels();
+
+ SubmitNewPosition();
+ }
+
+ GUILayout.EndArea();
+ }
+
+ static void StartButtons()
+ {
+ if (GUILayout.Button("Host")) NetworkManager.Singleton.StartHost();
+ if (GUILayout.Button("Client")) NetworkManager.Singleton.StartClient();
+ if (GUILayout.Button("Server")) NetworkManager.Singleton.StartServer();
+ }
+
+ static void StatusLabels()
+ {
+ var mode = NetworkManager.Singleton.IsHost ?
+ "Host" : NetworkManager.Singleton.IsServer ? "Server" : "Client";
+
+ GUILayout.Label("Transport: " +
+ NetworkManager.Singleton.NetworkConfig.NetworkTransport.GetType().Name);
+ GUILayout.Label("Mode: " + mode);
+ }
+
+ static void SubmitNewPosition()
+ {
+ if (GUILayout.Button(NetworkManager.Singleton.IsServer ? "Move" : "Request Position Change"))
+ {
+ if (NetworkManager.Singleton.IsServer && !NetworkManager.Singleton.IsClient )
+ {
+ foreach (ulong uid in NetworkManager.Singleton.ConnectedClientsIds)
+ NetworkManager.Singleton.SpawnManager.GetPlayerNetworkObject(uid).GetComponent().Move();
+ }
+ else
+ {
+ var playerObject = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
+ var player = playerObject.GetComponent();
+ player.Move();
+ }
+ }
+ }
+ }
+}
+```
+
+
+
+1. Add the `HelloWorldManager` script component to the `HelloWorldManager` `GameObject`.
+
+
+Click to show/hide the Code.
+
+
+```csharp
+ static void StartButtons()
+ {
+ if (GUILayout.Button("Host")) NetworkManager.Singleton.StartHost();
+ if (GUILayout.Button("Client")) NetworkManager.Singleton.StartClient();
+ if (GUILayout.Button("Server")) NetworkManager.Singleton.StartServer();
+ }
+
+ static void StatusLabels()
+ {
+ var mode = NetworkManager.Singleton.IsHost ?
+ "Host" : NetworkManager.Singleton.IsServer ? "Server" : "Client";
+
+ GUILayout.Label("Transport: " +
+ NetworkManager.Singleton.NetworkConfig.NetworkTransport.GetType().Name);
+ GUILayout.Label("Mode: " + mode);
+ }
+```
+
+
+You can statically access the `NetworkManager` instance from any other scripts via its singleton named `Singleton`. This is defined when the `MonoBehaviour` is enabled. This component also has useful properties, such as `IsClient`, `IsServer`, and `IsLocalClient`. The `IsClient` and `IsServer` properties dictate the connection state we have currently established that you will use shortly.
+
+We call these methods inside of `OnGUI()`.
+
+
+Click to show/hide the Code.
+
+
+```csharp
+
+ void OnGUI()
+ {
+ GUILayout.BeginArea(new Rect(10, 10, 300, 300));
+ if (!NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer)
+ {
+ StartButtons();
+ }
+ else
+ {
+ StatusLabels();
+
+ SubmitNewPosition();
+ }
+
+ GUILayout.EndArea();
+ }
+
+```
+
+
+:::note
+You might notice the introduction of a new method, `SubmitNewPosition()`. This is used later.
+:::
+
+## Adding basic movement to the Player object
+
+Here we will create a `HelloWorldPlayer.cs` script that adds some basic movement to the Hello World player.
+
+1. Open the **Scripts** Folder.
+1. Create a new script called `HelloWorldPlayer`.
+1. Open the `HelloWorldPlayer.cs` script.
+1. Edit the `HelloWorldPlayer.cs` script to match the following.
+
+
+Click to show/hide the Code.
+
+```csharp
+using Unity.Netcode;
+using UnityEngine;
+
+namespace HelloWorld
+{
+ public class HelloWorldPlayer : NetworkBehaviour
+ {
+ public NetworkVariable Position = new NetworkVariable();
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsOwner)
+ {
+ Move();
+ }
+ }
+
+ public void Move()
+ {
+ if (NetworkManager.Singleton.IsServer)
+ {
+ var randomPosition = GetRandomPositionOnPlane();
+ transform.position = randomPosition;
+ Position.Value = randomPosition;
+ }
+ else
+ {
+ SubmitPositionRequestServerRpc();
+ }
+ }
+
+ [Rpc(SendTo.Server)]
+ void SubmitPositionRequestServerRpc(RpcParams rpcParams = default)
+ {
+ Position.Value = GetRandomPositionOnPlane();
+ }
+
+ static Vector3 GetRandomPositionOnPlane()
+ {
+ return new Vector3(Random.Range(-3f, 3f), 1f, Random.Range(-3f, 3f));
+ }
+
+ void Update()
+ {
+ transform.position = Position.Value;
+ }
+ }
+}
+```
+
+
+
+1. Select the **Player** prefab.
+1. Add the script `HelloWorldPlayer` script as a component.
+This class will inherit from `NetworkBehaviour` instead of `MonoBehaviour`.
+
+
+Click to show/hide the Code.
+
+
+
+
+```csharp
+ public class HelloWorldPlayer : NetworkBehaviour
+
+```
+
+
+Inside this class we now define a `NetworkVariable` to represent this player's networked position.
+
+
+Click to show/hide the Code.
+
+
+
+
+```csharp
+ public NetworkVariable Position = new NetworkVariable();
+```
+
+
+`HelloWorldPlayer` overrides `OnNetworkSpawn`.
+
+
+Click to show/hide the Code.
+
+
+
+
+```csharp
+ public override void OnNetworkSpawn()
+ {
+ if (IsOwner)
+ {
+ Move();
+ }
+ }
+```
+
+
+In a networked game, the dedicated server (or host) might need to run different functions than the networked player (the client). For example, in a server-authoritative game, the client would handle the player inputs, but the server would handle the movement. All instances of this script in the game, whether running on a server/host or a client, call the `OnNetworkSpawn` method when the NetworkObject to which this script is attached has spawned, but only its owner will call the `Move` method. In the case of a [Player Object](../../basics/networkobject#player-objects), Netcode spawns an instance of the player object for every client and host (for which they're the owner). Each of these player objects contain this script. Calling the `Move` method in OnNetworkSpawn instead of, for example, in `Awake` ensures that the NetworkObject has finished spawning, so the check to see whether the player is a server/host or client is valid. The `Move` method can then implement different logic depending on the answer (so that servers do one thing, and clients do another).
+
+
+Click to show/hide the Code.
+
+
+
+
+```csharp
+ public void Move()
+ {
+ if (NetworkManager.Singleton.IsServer)
+ {
+ var randomPosition = GetRandomPositionOnPlane();
+ transform.position = randomPosition;
+ Position.Value = randomPosition;
+ }
+ else
+ {
+ SubmitPositionRequestServerRpc();
+ }
+ }
+```
+
+
+### Some simple RPC use
+
+If this player is a server-owned player, at `OnNetworkSpawn()` we can immediately move this player, as suggested in the following code.
+
+
+Click to show/hide the Code.
+
+
+
+
+```csharp
+ if (NetworkManager.Singleton.IsServer)
+ {
+ var randomPosition = GetRandomPositionOnPlane();
+ transform.position = randomPosition;
+ Position.Value = randomPosition;
+ }
+```
+
+
+
+If we are a client, we call an `Rpc` with the parameter `SendTo.Server`. An `Rpc` with this parameter can be invoked by anyone (client, host, or server) to be executed on the server.
+
+
+Click to show/hide the Code.
+
+
+
+
+```csharp
+ else
+ {
+ SubmitPositionRequestServerRpc();
+ }
+
+```
+
+
+This `Rpc` simply sets the position `NetworkVariable` on the server's instance of this player by just picking a random point on the plane.
+
+
+Click to show/hide the Code.
+
+
+
+```csharp
+ [Rpc(SendTo.Server)]
+ void SubmitPositionRequestServerRpc(RpcParams rpcParams = default)
+ {
+ Position.Value = GetRandomPositionOnPlane();
+ }
+```
+
+
+The server instance of this player has just modified the Position `NetworkVariable`, meaning that if we are a client, we need to apply this position locally inside of our Update loop.
+
+
+Click to show/hide the Code.
+
+
+
+```csharp
+ void Update()
+ {
+ transform.position = Position.Value;
+ }
+```
+
+
+We can now go back to `HelloWorldManager.cs` and define the contents of `SubmitNewPosition()`.
+
+
+Click to show/hide the Code.
+
+
+
+```csharp
+ static void SubmitNewPosition()
+ {
+ if (GUILayout.Button(NetworkManager.Singleton.IsServer ? "Move" : "Request Position Change"))
+ {
+ var playerObject = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
+ var player = playerObject.GetComponent();
+ player.Move();
+ }
+ }
+```
+
+
+Whenever you press the GUI button (which is contextual depending on if you are server or a client), you find your local player and simply call `Move()`.
+
+You can now create a build which will show the concepts outlined above.
+
+:::tip
+Make sure **SampleScene** is included in **BuildSettings** > **Scenes in Build** list.
+:::
+
+One build instance can create a host. Another client can join the host's game. Both are able to press a GUI button to move. Server will move immediately and be replicated on client. Client can request a new position, which will instruct the server to modify that server instance's position `NetworkVariable`. That client will apply that `NetworkVariable` position inside of it's Update() method.
+
+## Next Steps
+
+See the following content to continue your journey using Netcode:
+
+* Build on the your growing Hello World project to continue learning about different features of Netcode with [Golden Path Two](gp_module_two.md)
+* Check out the educational samples to further explore Netcode and its abilities:
+ * [Boss Room](../../learn/bossroom/getting-started-boss-room.md)
+ * [2D Spaceshooter Bitesize Sample](../../learn/bitesize/bitesize-spaceshooter.md)
+ * [Invaders Bitesize Sample](../../learn/bitesize/bitesize-invaders.md)
+ * [Client-Driven Bitesize Sample](../../learn/bitesize/bitesize-clientdriven.md)
diff --git a/versioned_docs/version-2.0.0/tutorials/goldenpath_series/gp_module_two.md b/versioned_docs/version-2.0.0/tutorials/goldenpath_series/gp_module_two.md
new file mode 100644
index 000000000..487dff7fc
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/goldenpath_series/gp_module_two.md
@@ -0,0 +1,239 @@
+---
+id: goldenpath_two
+title: Golden Path Module Two
+description: Tutorial covering, Network variables (client and server-controlled), Network transforms, and RPCs.
+---
+
+Golden Path Two continues on the work from [Hello World](../helloworld.md) and [Golden Path One](gp_module_one.md) to add a few more features.
+
+This guide covers:
+
+- Network variables (client and server-controlled)
+- Network transforms
+- RPCs
+
+:::note
+The videos on this page were removed because they were out-of-date and caused more confusion than help. All videos in the Hello World and Golden Path series will be recreated and added back at a later time.
+:::
+
+## Prerequisites
+
+You should have completed the [Hello World project](../helloworld.md) and [Golden Path One](gp_module_one.md) before starting this tutorial.
+
+## Open your Hello World project
+
+1. Open Unity Hub.
+1. Select `Hello World` from the list of projects displayed.
+
+## Introducing a Server-controlled Network Variable
+
+This section adds a Server-controlled Network Variable to the project.
+
+1. Open the **Scripts** Folder.
+1. Create a script called `NetworkVariableTest`.
+1. Click the **Player** prefab.
+1. In the **Player** Prefab Inspector tab, click **Add Component**.
+1. Click **Scripts**, and add the `NetworkVariableTest.cs` script you created earlier.
+1. Open the `NetworkVariableTest.cs` script.
+1. Edit the `NetworkVariableTest.cs` script to match the following.
+
+
+
+Click to show/hide the Code.
+
+
+
+``` csharp
+using Unity.Netcode;
+using UnityEngine;
+
+public class NetworkVariableTest : NetworkBehaviour
+{
+ private NetworkVariable ServerUptimeNetworkVariable = new NetworkVariable();
+ private float last_t = 0.0f;
+
+ public override void OnNetworkSpawn()
+ {
+ if (IsServer)
+ {
+ ServerUptimeNetworkVariable.Value = 0.0f;
+ Debug.Log("Server's uptime var initialized to: " + ServerUptimeNetworkVariable.Value);
+ }
+ }
+
+ void Update()
+ {
+ var t_now = Time.time;
+ if (IsServer)
+ {
+ ServerUptimeNetworkVariable.Value = ServerUptimeNetworkVariable.Value + 0.1f;
+ if (t_now - last_t > 0.5f)
+ {
+ last_t = t_now;
+ Debug.Log("Server uptime var has been updated to: " + ServerUptimeNetworkVariable.Value);
+ }
+ }
+ }
+}
+```
+
+
+8. Save your scene.
+
+### Testing Server-controlled Network Variables
+
+Now we will test the Server-controlled Network Variable works as we intended.
+
+1. Select **File > Build and Run**.
+1. Stop the player.
+2. Launch the client and server together in a terminal as shown in [Testing the command line helper](../helloworld.md#testing-the-command-line-helper).
+3. After a brief delay, the client and server will spawn.
+4. You should see the following in the console, showing that the server and client are sharing the variable:
+
+
+```
+Server's var initialized to: 0
+Server set its var to: 0.1
+Server set its var to: 3.099999
+Server set its var to: 6.099997
+```
+:::note
+Since the printing to the terminal does not happen on every tick, the numbers won't match up perfectly.
+:::
+
+## Introducing Network Transform
+
+This section adds a Network Transform component that will move the player.
+
+1. Click **Player** prefab.
+1. Click **Add Component** in the Inspector Tab.
+1. Select **Netcode** from the list shown.
+1. Select the **Network Transform** component from the list shown.
+1. Open the **Scripts** Folder.
+1. Create a script called `NetworkTransformTest`.
+1. Click the **Player** prefab.
+1. In the **Player** Prefab Inspector tab, click **Add Component**
+1. Click **Scripts**, and add the `NetworkTransformTest.cs` script you created earlier.
+1. Open the `NetworkTransformTest.cs` script.
+1. Edit the `NetworkTransformTest.cs` script to match the following.
+
+
+Click to show/hide the Code.
+
+
+
+```csharp
+using System;
+using Unity.Netcode;
+using UnityEngine;
+
+public class NetworkTransformTest : NetworkBehaviour
+{
+ void Update()
+ {
+ if (IsServer)
+ {
+ float theta = Time.frameCount / 10.0f;
+ transform.position = new Vector3((float) Math.Cos(theta), 0.0f, (float) Math.Sin(theta));
+ }
+ }
+}
+```
+
+
+12. Save your scene.
+
+### Testing Network Transform
+
+Now we check that the Network Transform functions correctly.
+
+1. Select **File** > **Build and Run**.
+1. Stop the player.
+1. Launch the client and server together in a terminal as shown in [Testing the command line helper](../helloworld.md#testing-the-command-line-helper).
+1. After a brief delay, the client and server will spawn.
+1. You should see the player capsule moving in a circle on both the client and the server.
+
+## Introducing RPCs
+
+This section adds some basic RPCs to the project.
+
+1. Open the **Scripts** Folder.
+1. Create a script called `RpcTest`.
+1. Click the **Player** prefab.
+1. In the **Player** Prefab Inspector tab, click **Add Component**.
+1. Click **Scripts**, and add the `RpcTest.cs` script you created earlier.
+2. Open the `RpcTest.cs` script.
+3. Edit the `RpcTest.cs` script to match the following.
+
+
+Click to show/hide the Code.
+
+
+
+```csharp
+using Unity.Netcode;
+using UnityEngine;
+
+public class RpcTest : NetworkBehaviour
+{
+ public override void OnNetworkSpawn()
+ {
+ if (!IsServer)
+ {
+ TestServerRpc(0);
+ }
+ }
+
+ [Rpc(SendTo.ClientsAndHost)]
+ void TestClientRpc(int value)
+ {
+ if (IsClient)
+ {
+ Debug.Log("Client Received the RPC #" + value);
+ TestServerRpc(value + 1);
+ }
+ }
+
+ [Rpc(SendTo.Server)]
+ void TestServerRpc(int value)
+ {
+ Debug.Log("Server Received the RPC #" + value);
+ TestClientRpc(value);
+ }
+}
+```
+
+
+9. Save your scene.
+
+### Testing RPCs
+
+Now we will test that the client and server are both recieving the RPCs correctly.
+
+1. Select **File** > **Build and Run**.
+1. Stop the player.
+1. Launch the client and server together in a terminal as shown in [Testing the command line helper](../helloworld.md#testing-the-command-line-helper).
+1. After a brief delay, the client and server will spawn.
+1. In the console, you should expect to see the client and server sending RPC messages to each other.
+1. The client kicks off the exchange in its `Update` call the first time with a counter value of 0.
+1. It then makes an RPC call to the server with the next value. The server receives this and calls the client. In the console view, you will see:
+
+```
+Server Received the RPC #1
+Client Received the RPC #1
+Server Received the RPC #2
+Client Received the RPC #2
+Server Received the RPC #3
+Client Received the RPC #3
+...
+```
+
+## Next Steps
+
+See the following content to continue your journey using Netcode:
+
+* Check out the educational samples to further explore Netcode and its abilities:
+ * [Boss Room](../../learn/bossroom/getting-started-boss-room.md)
+ * [2D Spaceshooter Bitesize Sample](../../learn/bitesize/bitesize-spaceshooter.md)
+ * [Invaders Bitesize Sample](../../learn/bitesize/bitesize-invaders.md)
+ * [Client-Driven Bitesize Sample](../../learn/bitesize/bitesize-clientdriven.md)
diff --git a/versioned_docs/version-2.0.0/tutorials/helloworld.md b/versioned_docs/version-2.0.0/tutorials/helloworld.md
new file mode 100644
index 000000000..f1f9eadfd
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/helloworld.md
@@ -0,0 +1,312 @@
+---
+id: helloworld
+title: Your Netcode "Hello World" Project
+description: Tutorial that explains creating a project, installing the Netcode for GameObjects package, and creating the basic components for your first networked game.
+---
+
+A "Hello World" program is a computer program that outputs or displays the message "Hello, World!". Normally it's the first program written by people learning to code. it's also used as a sanity test to make sure that a computer language is correctly installed and that the operator understands how to use it.
+
+This "Hello World" tutorial walks you through creating a project, installing Netcode for GameObjects (Netcode), and creating the basic components for your first networked game. it's also the base for the [Golden Path series](goldenpath_series/gp_intro.md).
+
+:::note
+The videos on this page were removed because they were out-of-date and caused more confusion than help. All videos in the Hello World and Golden Path series will be recreated and added back at a later time.
+:::
+
+## Create a new project in Unity
+
+1. Open the **Unity Hub**.
+1. Click **New**.
+1. Select type '3D'
+1. Name the project *Hello World*.
+1. Select the location you want to save the project.
+
+## Install Netcode
+
+See the [install Netcode guide](../installation/installation.md) to install the Netcode package.
+
+## Create the Basic Components
+
+In this section we will create the basic building blocks of a multiplayer game.
+
+### Creating Network Manager and selecting the Transport
+
+In this section we add a Network Manager and add Unity Transport to our project. The [NetworkManager](../components/networkmanager.md) is the component that has all your project's netcode-related settings. Unity Transport is the transport layer that Netcode uses for communication between the server and the clients. See [here](../advanced-topics/transports.md) for more.
+
+1. Right-click in the **Hierarchy** tab of the main Unity Window.
+1. Select **Create Empty**.
+1. Rename the `GameObject` **NetworkManager**.
+
+ :::tip
+ We renamed the `GameObject` because:
+ * It makes it easier to refer to later.
+ * There should only be one **NetworkManager**, this is the object that has the `NetworkManager` component. You may get unexpected results if you create more than one **NetworkManager**.
+ :::
+
+2. Select **NetworkManager**.
+3. Click **Add Component** in the Inspector Tab.
+4. Select **Netcode** from the list shown.
+5. Select `NetworkManager` Component from the list displayed.
+6. Inside the `NetworkManager` component tab, locate the `NetworkTransport` field.
+7. Click "Select Transport".
+8. Select `UnityTransport`.
+9. Save your scene.
+
+## Creating an object to spawn for each connected player
+
+This section adds in a player object and spawns it for each connected player.
+
+1. Right-click in the **Hierarchy** tab of the Unity Window to create a **3D Object > Capsule**
+1. Rename it **Player**.
+1. While **Player** is selected, add a **Netcode** > NetworkObject component in the Inspector Tab.
+1. Click the **Assets** folder under the **Project** tab.
+2. Right-click inside the **Assets** folder to **Create** > **Folder** and call it **Prefabs**.
+3. Make **Player** a Prefab by dragging it to **Prefabs** folder you just created.
+4. Delete **Player** from scene.
+
+ :::tip
+ We remove the **Player** object from the scene because we assign this network Prefab to the `Player Prefab` property in the `NetworkManager` component. The library does not support defining a player object as an in-scene placed NetworkObject.
+ :::
+
+5. Select `NetworkManager`.
+6. Inside the `NetworkManager` component tab, locate the `Player Prefab` field.
+7. Drag this player Prefab from above into this field.
+
+ :::important
+ When you drop the Prefab into the `Player Prefab` slot, you are telling the library that when a client connects to the game, automatically spawn this Prefab as the character for the connecting client. If you don't have any Prefab set as the `Player Prefab` no player object will be spawned.
+ :::
+
+1. Create a **3D Object->Plane**, centered at (0,0,0).
+1. Save your scene
+
+### Adding your scene to the build
+:::important
+When 'Enable Scene Management' is enabled for the NetworkManager (allowing the server to control which scenes should be loaded for the clients), we must ensure that the current scene has been added to the build, otherwise, we will be unable to enter play mode. This option is enabled by default.
+:::
+
+1. Click **File** > **Build Settings**, in the upper-left corner of the Unity window
+2. Click **Add Open Scenes**
+3. Close the `Build Settings` window.
+
+## Creating a command line helper
+
+This command line helper will allow us to launch builds with a command line argument that will start a networking session, either as a server, host, or client. This can make testing builds easier.
+
+1. Right-click the **Assets** folder and create a new folder by hovering over **Create** and selecting **Folder**. Name it **Scripts**.
+2. Create a script called `NetworkCommandLine` by right-clicking on your **Scripts** folder, hovering over **Create** and selecting **C# Script**.
+3. In the **Hierarchy** menu, right-click on the `NetworkManager` and choose **Create Empty**.
+
+ This will create an empty `GameObject` with `NetworkManager` as its parent.
+
+4. Rename this child `GameObject` `NetworkCommandLine`.
+5. With the new `NetworkCommandLine` object selected, click **Add Component** from the **Inspector** tab.
+6. Select **Scripts** from the drop-down and click on the `NetworkCommandLine.cs` script you created earlier.
+7. Open the `NetworkCommandLine.cs` script by double-clicking from the **Project** tab > **Assets** > **Scripts**. It will open in your text editor
+8. Edit the `NetworkCommandLine.cs` script to match the following:
+
+
+Click to show/hide the Code.
+
+
+
+``` csharp
+using System.Collections.Generic;
+using Unity.Netcode;
+using UnityEngine;
+
+public class NetworkCommandLine : MonoBehaviour
+{
+ private NetworkManager netManager;
+
+ void Start()
+ {
+ netManager = GetComponentInParent();
+
+ if (Application.isEditor) return;
+
+ var args = GetCommandlineArgs();
+
+ if (args.TryGetValue("-mode", out string mode))
+ {
+ switch (mode)
+ {
+ case "server":
+ netManager.StartServer();
+ break;
+ case "host":
+ netManager.StartHost();
+ break;
+ case "client":
+
+ netManager.StartClient();
+ break;
+ }
+ }
+ }
+
+ private Dictionary GetCommandlineArgs()
+ {
+ Dictionary argDictionary = new Dictionary();
+
+ var args = System.Environment.GetCommandLineArgs();
+
+ for (int i = 0; i < args.Length; ++i)
+ {
+ var arg = args[i].ToLower();
+ if (arg.StartsWith("-"))
+ {
+ var value = i < args.Length - 1 ? args[i + 1].ToLower() : null;
+ value = (value?.StartsWith("-") ?? false) ? null : value;
+
+ argDictionary.Add(arg, value);
+ }
+ }
+ return argDictionary;
+ }
+}
+```
+
+
+
+9. Paste the copied code into your code editor.
+1. Save your changes. Your script will reload in the Unity Editor.
+1. Back in the Editor, open **Edit** -> **Project Settings**
+1. Select the **Player tab**.
+1. Expand the **Resolution and Presentation**.
+1. From **Resolution** > **Fullscreen Mode**, change `Fullscreen Window` to `Windowed`.
+1. Back to the Editor main window, save your scene.
+
+
+:::tip
+ If you are using a Pro Unity license, you may want to disable the splash screen by unchecking **Splash Image** > **Splash Screen** > **Show Splash Screen**.
+:::
+
+### Testing the command line helper
+
+Now we will test that the command line helper script works.
+
+1. Select **File** > **Build and Run**.
+1. Create a new folder called `Build` inside your Hello World project folder.
+1. **Save As** the binary `HelloWorld`.
+1. Your project will build and launch in a new window, and you should see the plane.
+1. Quit your app.
+1. Now to launch from the command line.
+
+
+
+
+
+
+For Windows you should do the following:
+
+
+1. Open your Command Prompt.
+1. Enter the following. Be sure to change the noted section `< >` of **both** commands to your project.
+
+:::note
+You may get a UAC prompt requesting permission for the binary to run you should allow it.
+:::
+
+ Server:
+ ```
+ \Build\HelloWorld.exe -mode server
+ ```
+
+ Client:
+ ```
+ \Build\HelloWorld.exe -mode client
+ ```
+
+ To run these commands on a single line:
+ ```
+ HelloWorld\Build\HelloWorld.exe -mode server & HelloWorld\Build\HelloWorld.exe -mode client
+ ```
+
+ Example:
+ ```
+ C:\Users\sarao>HelloWorld\Build\HelloWorld.exe -mode server & HelloWorld\Build\HelloWorld.exe -mode client
+ ```
+
+:::important
+On Windows, no standard out stream exists by default, so you will need to view the Debug.log file to see the outputs. You can find the Debug.log files in:
+
+`C:\Users\username\AppData\LocalLow\CompanyName\ProductName\Player.log`
+
+Where the `CompanyName` should default to `DefaultCompany` for a new project and `ProductName` should be equal to the project's name.
+
+Alternatively you can modify the Windows commands to create a log.txt file in the same folder as your **HelloWorld** folder.
+
+Modify the commands as follows:
+
+ Server:
+ ```
+ \Build\HelloWorld.exe -logfile log-server.txt -mode server
+ ```
+
+ Client:
+ ```
+ \Build\HelloWorld.exe -logfile log-client.txt -mode client
+ ```
+
+ Example (Running as a single command line):
+ ```
+ C:\Users\sarao>HelloWorld\Build\HelloWorld.exe -logfile -log-server.txt -mode server & HelloWorld\Build\HelloWorld.exe -logfile log-client.txt -mode client
+ ```
+:::
+
+
+
+
+
+For Mac you should do the following:
+
+1. Open Terminal.
+2. Enter the following. Be sure to change the noted section `< >` of **both** commands to your project.
+
+Server
+```
+/Build/HelloWorld.app/Contents/MacOS/ -mode server -logfile -
+```
+
+Client
+```
+/Build/HelloWorld.app/Contents/MacOS/ -mode client -logfile -
+```
+
+Run both as a single command:
+```
+/Build/HelloWorld.app/Contents/MacOS/ -mode server -logfile - & ; ~ /Build/HelloWorld.app/Contents/MacOS/ -mode client -logfile -
+```
+
+
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Testing Hello World
+
+### Route 1 - Editor
+Now, to see if everything works as expected we can test starting a host in the editor. A host plays the role of a server and a client at the same time.
+
+1. Click **Play**.
+1. Click the **Start Host** button in the **NetworkManager** GameObject's inspector.
+1. You should now see your scene with your Player Prefab spawned.
+
+### Route 2 - Command Line
+You can also use the command line helper to launch a server and one or more clients to connect to the server. You should see just the plane on the server until the first client connects. Then, a new Player Prefab will be spawned by Netcode for each connected client; however, they will be overlapped in the game view.
+
+## Next Steps
+
+See the following content to continue your journey using Netcode:
+
+* Build on the Hello World project to continue learning about different features of Netcode with the [Golden Path series](goldenpath_series/gp_intro.md).
+* Check out the educational samples to further explore Netcode and its abilities:
+ * [Boss Room](../learn/bossroom/getting-started-boss-room.md)
+ * [2D Spaceshooter Bitesize Sample](../learn/bitesize/bitesize-spaceshooter.md)
+ * [Invaders Bitesize Sample](../learn/bitesize/bitesize-invaders.md)
+ * [Client-Driven Bitesize Sample](../learn/bitesize/bitesize-clientdriven.md)
diff --git a/versioned_docs/version-2.0.0/tutorials/testing/techniques_and_tricks_for_debugging_multiplayer_games.md b/versioned_docs/version-2.0.0/tutorials/testing/techniques_and_tricks_for_debugging_multiplayer_games.md
new file mode 100644
index 000000000..971ffeca7
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/testing/techniques_and_tricks_for_debugging_multiplayer_games.md
@@ -0,0 +1,180 @@
+---
+id: techniques_and_tricks_for_debugging_multiplayer_games
+title: Techniques and tricks for debugging multiplayer games
+description: Guide covering some of the techniques that are either specific to or are useful when debugging multiplayer games.
+---
+
+When debugging games, multiplayer games included, it helps to know the toolbag that we have at our disposal.
+
+All the conventional game development wisdom applies, however certain scenarios that are typical to multiplayer game development call for special tricks and approaches.
+
+Below is a list of practices and techniques that we use daily when working on the Boss Room sample. These recommendations, we find, compound into a more comfortable working experience when developing multiplayer games with Unity.
+
+## Debugging tricks for multiplayer games
+
+### Use ParrelSync clone-based workflow during development.
+
+[ParrelSync workflow](testing_locally.md#parrelsync) is faster than creating builds and it allows you to debug the separate editor instances via separate IDE debuggers.
+
+Use ParrelSync to run separate editor instances for your Host/Server and Client.
+
+### Use debug drawing techniques extensively
+
+Unity engine has two debug rendering APIs that are useful for the purposes of multiplayer game debugging:
+ - [Debug.DrawRay](https://docs.unity3d.com/ScriptReference/Debug.DrawRay.html)
+ - [Debug.DrawLine](https://docs.unity3d.com/ScriptReference/Debug.DrawLine.html)
+
+Both of these functions allow us to draw arbitrary debug lines that would be visible in the Scene view and in the Game view, provided Gizmo rendering is enabled (to enable Gizmo rendering in Game view you need to click on the `Gizmos` menu at the top of the Game view).
+
+The key trick here is to use different colors for different kinds of information and to make the lines stay long enough for visual inspection by setting `duration` parameter. This technique shines when it's combined with [screen recordings](#7-recording-the-video-of-gameplay) of [multiple peers running side by side in separate editor instances via ParrelSync](#1-use-parrelsync-workflow-during-development).
+
+The code below would render a green debug line that's 2 units tall at the position of the transform, and this line would stay on screen for 4 seconds:
+`Debug.DrawLine(this.transform.position, this.transform.position + Vector3.UP * 2f, Color.green, duration: 4f);`
+
+When working on Boss Room we found it valuable to draw debug lines for the following items:
+ - Visual position
+ - Network position
+ - Movement intention
+ - Object interactions
+
+### A Netcode Enabled Line Renderer
+Sometimes it's useful to have visual feedback that shows a specific direction, value, or any other useful debug metric pertinent to your project. Below is a fully working example of a netcode enabled line renderer that can be used for visual debugging purposes:
+```csharp
+using UnityEngine;
+using Unity.Netcode;
+public class NetcodeEnabledLineRenderer : NetworkBehaviour
+{
+ private LineRenderer m_LineRenderer;
+ private Vector3[] m_Positions;
+ private Material m_LineMaterial;
+
+ [Tooltip("The default state of the netcode debug render lines")]
+ [SerializeField]
+ private bool m_EnableDebugLines = true;
+
+ [Tooltip("The length of the line")]
+ public float LineLength = 4.0f;
+
+ [Tooltip("The width of the line")]
+ public float LineWidth = 0.3f;
+
+ private void Awake()
+ {
+ // Add a line renderer component
+ m_LineRenderer = gameObject.AddComponent();
+
+ // Switch to a legacy built-in shader that will work with just colors and/or a color gradient
+ m_LineMaterial = new Material(Shader.Find("Legacy Shaders/Particles/Alpha Blended Premultiply"));
+
+ // Assign this new material to the line renderer
+ m_LineRenderer.material = m_LineMaterial;
+
+ // Create our start color for the gradient
+ var colorKeyStart = new GradientColorKey();
+ colorKeyStart.color = Color.red;
+ // The "start" should be 0.0f
+ colorKeyStart.time = 0.0f;
+
+ // Create our end color for the gradient
+ var colorKeyEnd = new GradientColorKey();
+ colorKeyEnd.color = Color.blue;
+ // The "end" should be 1.0f
+ colorKeyEnd.time = 1.0f;
+
+ // Now create and apply the gradient
+ m_LineRenderer.colorGradient = new Gradient() { colorKeys =
+ new GradientColorKey[2] { colorKeyStart, colorKeyEnd },
+ mode = GradientMode.Blend };
+
+ //declare two positions for the start and end of the line
+ m_Positions = new Vector3[2];
+
+ //Ensure that the line renderer knows to draw in world space
+ m_LineRenderer.useWorldSpace = true;
+
+ //set the beginning and ending width of the line in units
+ m_LineRenderer.startWidth = 0.3f;
+ m_LineRenderer.endWidth = 0.3f;
+ }
+
+ public override void OnDestroy()
+ {
+ // With NetworkBehaviours, always make sure to invoke the
+ // base.OnDestroy method
+ base.OnDestroy();
+
+ // We should always destroy any runtime materials we create
+ if (m_LineMaterial != null)
+ {
+ Destroy(m_LineMaterial);
+ }
+ }
+
+ ///
+ /// Update the position of the line
+ ///
+ private void Update()
+ {
+ if (IsSpawned && m_EnableDebugLines)
+ {
+ //set the start and end positions of our line
+ m_Positions[0] = transform.position;
+ m_Positions[1] = transform.position + Vector3.up * LineLength;
+
+ //feed the values to the line renderer
+ m_LineRenderer.SetPositions(m_Positions);
+ }
+ }
+
+ ///
+ /// Example for having netcode debug render lines
+ ///
+ [Rpc(SendTo.ClientsAndHost)]
+ private void ToggleDebugLinesClientRpc(bool drawDebugLines)
+ {
+ m_EnableDebugLines = drawDebugLines;
+ }
+
+ ///
+ /// Server-Side only
+ /// Enables/Disables the debug line rendering
+ ///
+ public void DebugLinesEnabled(bool enableDebugLines)
+ {
+ if (IsSpawned && IsServer)
+ {
+ m_EnableDebugLines = enableDebugLines;
+ ToggleDebugLinesClientRpc(m_EnableDebugLines);
+ }
+ }
+}
+```
+
+### Use debug logging for situations where visual debugging isn't appropriate.
+
+Text-based logging is valuable for tracking down non-visual events (such as RPCs) and information.
+It is a good idea to include network tick and client id in log messages so that it's easier to build a timeline when reading the logs.
+
+### Use the artificial network conditioning tools.
+
+The options that are currently available to us are covered in the related [article on artificial network conditioning tools](testing_with_artificial_conditions.md).
+
+Of particular interest to us is the application-level network conditioning provided by [Network Simulator tools](https://docs-multiplayer.unity3d.com/tools/current/tools-network-simulator/), as it allows us to easily specify conditions for our individual peers that live within separate editors by means of ParrelSync.
+
+Artificial network conditions allow the errors and oddities that are hidden by nigh-absence of lag when running your instances locally to show up, and it's a good thing!
+
+### Capturing screen recordings of the game instances.
+
+First of all, it's valuable to record both your Client and Server at the same time - it allows you to compare what is happening on either peer in realtime.
+
+When recording your screen, sometimes it's hard to see if we are legitimately missing an update in our game or if it's just our recording refresh rate isn't synced with Unity's refresh calls.
+
+In debug builds it's a great idea to show the Peer ID and the current frame number somewhere in the corner of the screen - this way there is a visual reference to the number of the frame we're currently observing on the recording.
+
+Sometimes, despite us using good debug rendering and logging it's still hard to understand what's going on even when going through the frames one by one. Increasing our FixedTimeStep setting to a ridiculous value (something as high as `0.2`) helps to have more time to see what's going on.
+
+The same applies to high latencies (1000ms) - these stress the lag hiding techniques, allowing us to visualize what the different lag hiding techniques are doing.
+
+### Using breakpoints to debug a Client or Server
+
+You can use breakpoints to debug a game, but your connection may time out if you stay too long in this mode. Since it pauses your game, you can temporarily increase the timeout value to avoid disconnecting.
diff --git a/versioned_docs/version-2.0.0/tutorials/testing/testing_client_connection_management.md b/versioned_docs/version-2.0.0/tutorials/testing/testing_client_connection_management.md
new file mode 100644
index 000000000..a8cf4cc4b
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/testing/testing_client_connection_management.md
@@ -0,0 +1,60 @@
+---
+id: testing_client_connection_management
+title: Testing Client Connection Management
+description: Guide covering the test cases to handle when managing client connection and common pitfalls to avoid
+---
+
+Managing client connections in a networked game can lead to many unexpected edge-cases which if not properly tested and handled may cause bugs. Here is a non-exhaustive list of test cases that should be handled, depending on what features a game provides, and things to look out for.
+
+### Clients connecting
+- test cases:
+ - Client connecting to a new game session
+ - Client connecting to a new game session after leaving a previous game session
+ - in the case of a client-hosted game, after ending a previous game as a host
+ - Client connecting to an ongoing game session (late-joining)
+ - Client reconnecting to an ongoing game session (see [Session Management](../../advanced-topics/session-management.md#Reconnection))
+ - Client failing to connect due to approval denied (see [Connection Approval](../../basics/connection-approval.md))
+- things to look out for:
+ - Client-Side:
+ - Does the state of the client before connecting have an impact (that is, if connecting after disconnecting from another game or hosting one)
+ - Does the game state get properly replicated from the server when connecting?
+ - Server-Side:
+ - Does the server properly handle reconnections or late-joining, if the game supports it, or does it deny approval if not?
+
+
+### Clients disconnecting
+- test cases:
+ - Client disconnecting gracefully by shutting down NetworkManager
+ - Client disconnecting by closing the application
+ - Client timing out when losing connection to the host/server
+ - By disabling internet on client
+ - By disabling it on the host/server
+- things to look out for:
+ - Client-side:
+ - Is the state of every object tied to the game session properly reset if not destroyed? (for example, if a NetworkBehaviour isn't destroyed when despawning, is its state properly reset via OnNetworkDespawn and OnNetworkSpawn?)
+ - Is the client brought back to a state from which it can try to connect to a new game?
+ - Server-Side:
+ - Is the server notified of this disconnection and does it handle it properly?
+ - If using outside services, are they notified of this? (for example if using a lobby service, is the client removed from the lobby?)
+
+### Host / Server starting the session
+- test cases:
+ - Host/Server starting a new game session
+ - Host/Server starting a new game session after shutting down a previous game session
+ - in the case of a client-hosted game, after disconnecting from a preivious game as a client
+- things to look out for:
+ - Server-side:
+ - Does the state of the application before starting a new session have an impact (that is, if starting after shutting down another game or disconnecting from one as a client)
+
+### Host / Server shutting down
+- test cases:
+ - Host/Server disconnecting gracefully by shutting down NetworkManager
+ - Host/Server disconnecting by closing the application
+ - If requiring services (i.e Unity Game Services or other services) to function:
+ - Host/Server timing out when losing connection to services
+- things to look out for:
+ - Client-side:
+ - Are clients notified of this shut down, and do they handle it?
+ - Server-side:
+ - Are the services used notified of this? (for example if using a lobby service, does the game properly close the lobby when shutting down the game session?)
+ - Is the state of every object tied to the game session properly reset if not destroyed? (for example, if a NetworkBehaviour isn't destroyed when despawning, is its state properly reset via OnNetworkDespawn and OnNetworkSpawn?)
diff --git a/versioned_docs/version-2.0.0/tutorials/testing/testing_locally.md b/versioned_docs/version-2.0.0/tutorials/testing/testing_locally.md
new file mode 100644
index 000000000..b163f0147
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/testing/testing_locally.md
@@ -0,0 +1,40 @@
+---
+id: testing_locally
+title: Testing multiplayer games locally
+description: Guide covering the available workflows for testing multiplayer games locally.
+---
+
+Testing a multiplayer game presents unique challenges:
+
+- You need to run multiple instances of the game to test multiplayer scenarios.
+- You also need to iterate quickly on custom code and asset changes and validate work in a multiplayer scenario.
+- You need to be able to debug work in a multiplayer scenario using Editor tools.
+
+There are several different ways you can test multiplayer games locally:
+
+- Using [player builds](#player-builds) to validate work on a target distribution platform, although player builds can be slow for local iteration.
+- Using the [Multiplayer Play Mode package](#multiplayer-play-mode) to simulate up to four players simultaneously on the same development device.
+- Using third-party tools such as [ParrelSync](https://github.com/VeriorPies/ParrelSync).
+
+## Player builds
+
+Player builds are best used to verify that your game works on target platforms or with a wider group of testers. Start by building an executable to distribute.
+
+1. Navigate to **File** > **Build Settings** in the menu bar.
+1. Click **Build**.
+
+### Local iteration using player builds
+
+After the executable build completes, you can distribute it to testers and launch several instances of the built executable to both host and join a game. You can also run the build alongside the Editor that produced it, which can be useful during iterative development.
+
+Though functional, this approach can be somewhat slow for the purposes of local iteration. You can use [Multiplayer Play Mode](#multiplayer-play-mode) to iterate locally at speed.
+
+:::unity For Mac
+To run multiple instances of the same app, you need to use the command line on MacOS. Run `open -n YourAppName.app`.
+:::
+
+## Multiplayer Play Mode
+
+Multiplayer Play Mode is a Unity package you can use to simulate up to four players simultaneously on the same development device while using the same source assets on disk. It allows you to reduce project build times, run your game locally, and test the server-client relationship, all from within the Unity Editor.
+
+For more details, refer to the [Multiplayer Play Mode documentation](https://docs-multiplayer.unity3d.com/mppm/current/about/).
diff --git a/versioned_docs/version-2.0.0/tutorials/testing/testing_with_artificial_conditions.md b/versioned_docs/version-2.0.0/tutorials/testing/testing_with_artificial_conditions.md
new file mode 100644
index 000000000..b9774ac92
--- /dev/null
+++ b/versioned_docs/version-2.0.0/tutorials/testing/testing_with_artificial_conditions.md
@@ -0,0 +1,226 @@
+---
+id: testing_with_artificial_conditions
+title: Testing multiplayer games with artificial network conditions
+description: Guide covering the available tools for local testing of multiplayer games with artificial latency, jitter and packet loss .
+---
+
+When we are developing a multiplayer game that is intended to operate over the internet we inevitably have to deal with the reality of poor network conditions.
+
+Adverse network factors, such as latency, jitter, and packet loss all have to be taken into account during development and the tolerance thresholds for these should not be an afterthought or something relegated to an "optimization pass".
+
+:::warning
+Not testing with artificial network conditions makes it significantly more likely to have unexpected behaviors when the game is running over the internet.
+:::
+
+This is challenging when we are [iterating on our game locally](testing_locally.md) - after all, all of the game instances are still running on the same network interface. It's reasonable to expect that there will be little to no latency between the clients, which is no good for our purposes - we want the network to **misbehave**.
+
+Thankfully there are a number of tools that can simulate adverse network conditions.
+
+For testing locally within the Editor, you can use the [Network Simulator tool](https://docs-multiplayer.unity3d.com/tools/current/tools-network-simulator/) along with [clone-based workflow via ParrelSync](testing_locally.md#parrelsync).
+
+For testing development builds with built-in artificial latency we suggest using [Network Simulator tools with some custom code to inject artificial conditions into the build](#debug-builds).
+
+For testing release builds we suggest using [Clumsy](#clumsy-windows) if you're on Windows and Network Link Conditioner if you're on [macOS](#network-link-conditioner-mac-os) or [iOS](#network-link-conditioner-ios). A scriptable alternative to Network Link Conditioner on macOS is [dummynet](#dummynet-dnctl-and-pftcl-mac-os), which offers great control and comes packaged with the operating system.
+
+:::important
+While artificial latency is great for simulating network conditions during development - it won't accurately emulate real world conditions. We recommend to test your game often on the targeted platforms and real live networking conditions.
+:::
+
+## How much lag/packet loss/jitter should we use?
+
+It's not immediately obvious what the values and options we should enable in our network conditioning tools. All of them allow us to alter various aspects of network conditions such as latency, jitter and packet loss, though the names for concepts and the specific functionality varies between tools.
+
+Determining which network conditions to test with is about what your users will encounter while playing your game, which will vary by region and by platform.
+
+However, deciding what experience degradation is acceptable is dependent on game genre and on your game design decisions and other requirements. It's up to you to determine what's acceptable, there's no single rule for this.
+
+What latency value to use for general development?
+
+To test Boss Room, we used around 100ms-150ms for desktop platforms and around 200ms-300ms for mobile platforms and 5%-10% packet loss. These are just the values we used, the actual values you should test with will depend on your target platform and region.
+
+:::important
+It's valuable to test at 100ms, 200ms, 500ms, even 1000ms and potentially higher to make sure that we don't have weird race conditions that present at different latency ranges. The users in the wild WILL have those latencies.
+:::
+
+Next we should determine how much chaos we want to introduce - that's largely based on the target platform and the typical network conditions that our users would experience:
+ - Is the game meant to be played from a good broadband internet connection?
+ - Is the game meant to run on mobile networks?
+
+This question tells us if our users are likely to experience more jitter and packet loss - mobile networks are notorious for having widely varying quality of connection. Mobile users also can experience frequent network changes during active application usage, and even though [Unity Transport has reconnection mechanism](https://github.com/Unity-Technologies/com.unity.multiplayer.rfcs/blob/rfc/device-reconnection/text/0000-device-reconnection.md), it still requires our application to factor in the possibility of an occasional lag burst.
+
+What's important here is that testing purely with added delay and no packet loss and jitter is unrealistic. These values shouldn't be high - the baseline scenario isn't what we would call stress-testing, but they should be non-zero.
+
+Adding jitter to the base delay value adds a layer of chaotic unreliability that would make our peers behave in a more natural way, allowing us to tweak our interpolation, buffering and other techniques to compensate for these instabilities.
+
+Adding packet loss, apart from introducing even more effective delay to our system can also wreak havoc on our unreliable messages, thus allowing us to explore if we need more defensive logic surrounding our unreliable messages or if we should opt for a reliable message instead.
+
+### Different network conditions for different peers
+
+:::important
+[Clumsy](#clumsy-on-windows), [Network Link Conditioner](#network-link-conditioner-mac-os) and [dummynet](#dummynet-dnctl-and-pftcl-mac-os) are introducing changes on OS level, thus all the instances of the game that we open on our local machine would run under the same network conditions.
+
+Don't forget to disable it once you're done debugging, else your network connection will feel slow!
+
+QA teams run playtests with multiple people, each with their own system-wide conditioning settings. We can imitate this workflow locally by setting different per-peer network conditions. This approach isn't as reflective of reality as good QA tests on different machines, but it allows us to test these more peculiar scenarios locally.
+:::
+
+There is a group of scenarios where we would want to test how the game behaves when a player with a different baseline connection quality from most of our other peers joins the game - an example of such case can be someone playing from a significantly remote location or connecting from a device that's on a mobile network.
+
+In this case we would want to have an ability to set artificial conditions on a per-peer basis, which is possible with the [Network Simulator tool](https://docs-multiplayer.unity3d.com/tools/current/tools-network-simulator/).
+
+### Clone-based workflow (ParrelSync)
+
+:::caution
+
+ParallelSync is **not** supported by Unity. More information on its usage is available [here](https://github.com/VeriorPies/ParrelSync). Troubleshooting information can be found [here](https://github.com/VeriorPies/ParrelSync/wiki/Troubleshooting-&-FAQs)
+
+:::
+
+
+Simulator Tools effects only apply to editor instances and to [debug builds](#debug-builds), as such it matches well with [clone-based workflow via ParrelSync](testing_locally.md#parrelsync).
+
+Other tools should be used when testing release builds locally.
+
+To combine the benefits of Simulator Tools Window with ParrelSync - create or open a clone of your project, open up the simulator tools window in both the main project and the clone and play with the settings to alter how network behaves for each individual peer. Remember to re-launch your game if you change the values in the tools window - the effects only take place when the Unity Transport driver is being created.
+
+:::important
+With Simulator Tools we can't specify if inbound packets and outbound packets would experience different conditions - artificial latency, jitter and packet loss are bi-directional.
+:::
+
+:::important
+Simulator Tools window settings won't be committed to version control and need to be set up manually on different editor instances.
+:::
+
+### Debug Builds
+
+Debug builds do allow for the possibility of applying artificial network conditions to the Unity Transport driver, but the Simulator Tools window itself only sets these values in the Editor.
+
+To set the latency, jitter and packet-loss percentage values for develop builds we need the following code to execute before `NetworkManager` attempts to connect (changing the values of the parameters as desired):
+
+```
+#if DEVELOPMENT_BUILD && !UNITY_EDITOR
+ NetworkManager.Singleton.GetComponent().SetDebugSimulatorParameters(
+ packetDelay: 120,
+ packetJitter: 5,
+ dropRate: 3);
+#endif
+```
+
+## System-wide network conditioners
+
+These tools are useful when we want to test builds as opposed to running multiple editor instances. It's also an option that works for **release** builds.
+
+:::important
+The solutions described below share some common features:
+ - They don't support latency variability over time, so in effect we can't imitate artificial jitter with them.
+ - They're system-wide, thus all the local instances of our game would run under the same network conditions.
+ - They allow to control the settings for sending and receiving separately.
+:::
+
+There are some inherent limitations that come with the system-wide level of application of these tools - they're not ideal for local testing of more than two peers because we can't have peers with different network conditions between them (if that is important for the test of course).
+
+:::important
+Some consoles offer similar functionality at the native SDK level. Check their documentation for details.
+:::
+
+### Clumsy (Windows)
+
+:::note
+dummynet is another option that can be used on Windows, however there are known issues when running it on Windows 10 related to signed driver enforcement setting. As such we found Clumsy to be a good default option on Windows.
+:::
+
+Follow the installation instructions on the official [Clumsy Webpage](https://jagt.github.io/clumsy/).
+
+To test the builds with Clumsy:
+ - Run Clumsy
+ - Run instance 1
+ - Run instance 2
+ - At any point you can adjust Clumsy settings and observe the changes in gameplay fidelity
+
+#### Settings quickstart
+
+ - Lag - that's our primary lever to control artificial latency
+ - Drop - that's our packet loss
+ - Throttle, Out of Order, Duplicate, Tamper - these will manifest as additional latency but should be automatically handled for us by Netcode.
+ - Since Clumsy doesn't have Jitter functionality - we can emulate jitter (inconsistent latency over time) by playing with these parameters. Their cumulative effect would produce artificial latency fluctuations.
+
+For further reading please refer to the Details section of the [Clumsy Webpage](https://jagt.github.io/clumsy/) - the settings explanation there goes more into the actual mechanics of each individual setting.
+
+
+### Network Link Conditioner (macOS)
+
+Apple's Network Link Conditioner can be downloaded from the [Additional Tools for XCode page](https://developer.apple.com/download/all/?q=Additional%20Tools). This page requires logging in with Apple developer account.
+Download the version that's appropriate for your XCode version and then run the .dmg file. Navigate to the `Hardware` folder and install the Network Link Conditioner panel.
+
+After that you will be able to find Network Link Conditioner in the System Preferences panel of your Mac:
+![nlc-in-system-preferences](/img/nlc-in-system-preferences.png)
+
+To test the builds with Network Link Conditioner:
+ - Run Network Link Conditioner
+ - Run instance 1
+ - Run instance 2
+ - At any point you can adjust Network Link Conditioner settings and observe the changes in gameplay fidelity
+
+#### Settings quickstart
+
+In order to get to the settings we need to go into the `Manage Profiles` menu and either pick one or create our own.
+
+ - Downlink and Uplink Bandwidth are useful for testing how our game would behave if it's starved for bandwidth, but generally tightening it too much would gradually degrade any networked game.
+ - Downlink and Uplink Packets Dropped % is exactly what it seems - packet loss percentage.
+ - Downlink and Uplink Delay are our levers for controlling artificial latency
+
+### Network Link Conditioner (iOS)
+
+Apple's iOS also has it's version of Network Link Conditioner.
+
+Your iOS device needs to be enabled for development, then you'd be able to find Network Link Conditioner in Settings > Developer > Network Link Conditioner.
+
+### dummynet, dnctl and pftcl (macOS)
+
+**[dummynet](https://manpagez.com/man/8/dnctl/)** is a traffic shaper, delay and bandwidth manager utility that comes standard with the macOS.
+
+ - **dnctl** is the command-line interface to operate the `dummynet` utiity.
+ - **pfctl** is the control interface for the internal firewall, which we can make obey dummynet rules, thus creating artificial network conditions on our host.
+
+To enable artificial conditions we need to create a `pf.conf` file in our user home directory with the following contents:
+```
+#Testing udp, such as most realtime games and audio-video calls
+dummynet in proto udp from any to any pipe 1
+dummynet out proto udp from any to any pipe 1
+```
+
+Then we need to run the following commands in the console:
+```
+sudo dnctl pipe 1 config delay 40 plr 0.1
+sudo dnctl show
+
+sudo pfctl -e
+sudo pfctl -f pf.conf
+```
+
+:::warning
+This set of commands enables dummynet, but when we are done testing - we should disable it, otherwise our system would continue to experience these artificial network conditions!
+:::
+
+To disable dummynet execute the following:
+
+```
+sudo dnctl -q flush
+sudo dnctl show
+
+sudo pfctl -e
+sudo pfctl -f /etc/pf.conf
+```
+
+After you start dummynet, testing the builds is as easy as launching several instances of your game.
+
+#### Settings quickstart
+ - `bw` - this parameter controls bandwidth.
+ - `dnctl pipe 1 config bw 40Kbit/s` will set our bandwidth to 40 Kbit per second.
+ - `delay` - this parameter is our artificial latency.
+ - `dnctl pipe 1 config delay 100` will set our artificial latecny to 100 ms.
+ - `plr` - this parameter is our packet loss percentage.
+ - `dnctl pipe 1 config plr 0.1` will set our packet loss percetage to 10%
+
+You can chain these parameters to achieve a combination of these settings that will apply all of them at once:
+`dnctl pipe 1 config bw 40Kbit/s delay 100 plr 0.1`
diff --git a/versioned_sidebars/version-2.0.0-sidebars.json b/versioned_sidebars/version-2.0.0-sidebars.json
new file mode 100644
index 000000000..78c51268b
--- /dev/null
+++ b/versioned_sidebars/version-2.0.0-sidebars.json
@@ -0,0 +1,613 @@
+{
+ "netcode": [
+ {
+ "type": "doc",
+ "id": "about"
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Release notes",
+ "items": [
+ {
+ "type": "doc",
+ "id": "release-notes/ngo-changelog",
+ "label": "Netcode for GameObjects"
+ },
+ {
+ "type": "doc",
+ "id": "samples/release-notes/bossroom-changelog",
+ "label": "Boss Room"
+ },
+ {
+ "type": "doc",
+ "id": "samples/release-notes/bitesize-changelog",
+ "label": "Bitesize"
+ }
+ ]
+ },
+ {
+ "type": "link",
+ "label": "API reference",
+ "href": "https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.0/api/index.html"
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Get started",
+ "items": [
+ {
+ "type": "doc",
+ "id": "installation/install"
+ },
+ {
+ "type": "doc",
+ "id": "tutorials/get-started-ngo"
+ },
+ {
+ "type": "doc",
+ "id": "learn/distributed-authority-quick-start"
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Migrating",
+ "items": [
+ {
+ "type": "doc",
+ "id": "installation/upgrade_from_UNet"
+ },
+ {
+ "type": "doc",
+ "id": "installation/upgrade_from_mlapi"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Configuration",
+ "items": [
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Network topologies",
+ "items": [
+ {
+ "type": "doc",
+ "id": "terms-concepts/network-topologies"
+ },
+ {
+ "type": "doc",
+ "id": "terms-concepts/client-server"
+ },
+ {
+ "type": "doc",
+ "id": "learn/listen-server-host-architecture"
+ },
+ {
+ "type": "doc",
+ "id": "terms-concepts/distributed-authority"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Configuring connections",
+ "items": [
+ {
+ "type": "doc",
+ "id": "basics/connection-approval"
+ },
+ {
+ "type": "doc",
+ "id": "basics/max-players"
+ }
+ ]
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/transports"
+ },
+ {
+ "type": "doc",
+ "id": "relay/relay"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Networking components",
+ "items": [
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "NetworkObject",
+ "items": [
+ {
+ "type": "doc",
+ "id": "basics/networkobject"
+ },
+ {
+ "type": "doc",
+ "id": "basics/playerobjects"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/networkobject-parenting"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "NetworkBehaviour",
+ "items": [
+ {
+ "type": "doc",
+ "id": "basics/networkbehavior"
+ },
+ {
+ "type": "doc",
+ "id": "basics/networkbehavior-synchronize"
+ }
+ ]
+ },
+ {
+ "type": "doc",
+ "id": "components/networkmanager"
+ },
+ {
+ "type": "doc",
+ "id": "components/networktransform"
+ },
+ {
+ "type": "doc",
+ "label": "NetworkAnimator",
+ "id": "components/networkanimator"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/physics"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Ownership and authority",
+ "items": [
+ {
+ "type": "doc",
+ "id": "basics/ownership"
+ },
+ {
+ "type": "doc",
+ "id": "basics/race-conditions"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Spawning and despawning",
+ "items": [
+ {
+ "type": "doc",
+ "id": "basics/object-spawning"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/object-pooling"
+ },
+ {
+ "type": "doc",
+ "id": "basics/object-visibility"
+ },
+ {
+ "type": "doc",
+ "id": "basics/spawning-synchronization"
+ },
+ {
+ "type": "doc",
+ "id": "basics/deferred-despawning"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Latency and performance",
+ "items": [
+ {
+ "type": "doc",
+ "id": "learn/lagandpacketloss"
+ },
+ {
+ "type": "doc",
+ "id": "learn/ticks-and-update-rates"
+ },
+ {
+ "type": "doc",
+ "id": "learn/clientside_interpolation"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/client-anticipation"
+ },
+ {
+ "type": "doc",
+ "id": "learn/dealing-with-latency"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Network synchronization",
+ "items": [
+ {
+ "type": "doc",
+ "id": "advanced-topics/ways-synchronize"
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "NetworkVariables",
+ "items": [
+ {
+ "type": "doc",
+ "id": "basics/networkvariable"
+ },
+ {
+ "type": "doc",
+ "id": "basics/custom-networkvariables"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Remote procedure calls (RPCs)",
+ "items": [
+ {
+ "type": "doc",
+ "id": "advanced-topics/messaging-system"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/message-system/rpc"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/message-system/reliability"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/message-system/rpc-params"
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "RPCs vs NetworkVariables",
+ "items": [
+ {
+ "type": "doc",
+ "id": "learn/rpcvnetvar"
+ },
+ {
+ "type": "doc",
+ "id": "learn/rpcnetvarexamples"
+ }
+ ]
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/message-system/rpc-compatibility"
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Legacy RPC options",
+ "items": [
+ {
+ "type": "doc",
+ "id": "advanced-topics/message-system/clientrpc"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/message-system/serverrpc"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/message-system/execution-table"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/message-system/custom-messages"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/connection-events"
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Network update loop",
+ "items": [
+ {
+ "type": "doc",
+ "id": "advanced-topics/network-update-loop-system/about-network-update-loop"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/network-update-loop-system/network-update-loop-reference"
+ }
+ ]
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/networktime-ticks"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Serialization",
+ "items": [
+ {
+ "type": "doc",
+ "id": "advanced-topics/serialization/serialization-intro"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/serialization/cprimitives"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/serialization/unity-primitives"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/serialization/enum_types"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/serialization/arrays"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/serialization/inetworkserializable"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/custom-serialization"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/serialization/networkobject-serialization"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/fastbufferwriter-fastbufferreader"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Scene management",
+ "items": [
+ {
+ "type": "doc",
+ "id": "basics/scenemanagement/scene-management-overview"
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Integrated management",
+ "items": [
+ {
+ "type": "doc",
+ "id": "basics/scenemanagement/using-networkscenemanager"
+ },
+ {
+ "type": "doc",
+ "id": "basics/scenemanagement/scene-events"
+ },
+ {
+ "type": "doc",
+ "id": "basics/scenemanagement/client-synchronization-mode"
+ },
+ {
+ "type": "doc",
+ "id": "basics/scenemanagement/timing-considerations"
+ },
+ {
+ "type": "doc",
+ "id": "basics/scenemanagement/inscene-placed-networkobjects"
+ }
+ ]
+ },
+ {
+ "type": "doc",
+ "id": "basics/scenemanagement/custom-management"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Session management",
+ "items": [
+ {
+ "type": "doc",
+ "id": "advanced-topics/session-management"
+ },
+ {
+ "type": "doc",
+ "id": "advanced-topics/reconnecting-mid-game"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Testing and debugging",
+ "items": [
+ {
+ "type": "doc",
+ "id": "tutorials/testing/testing_locally"
+ },
+ {
+ "type": "doc",
+ "id": "tutorials/testing/testing_with_artificial_conditions"
+ },
+ {
+ "type": "doc",
+ "id": "tutorials/testing/testing_client_connection_management"
+ },
+ {
+ "type": "doc",
+ "id": "basics/logging"
+ },
+ {
+ "type": "doc",
+ "id": "tutorials/testing/techniques_and_tricks_for_debugging_multiplayer_games"
+ },
+ {
+ "type": "doc",
+ "id": "tutorials/command-line-helper"
+ },
+ {
+ "type": "doc",
+ "id": "troubleshooting/troubleshooting"
+ },
+ {
+ "type": "doc",
+ "id": "troubleshooting/errormessages"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Educational samples",
+ "items": [
+ {
+ "type": "doc",
+ "id": "learn/sample-dedicated-server"
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Boss Room",
+ "items": [
+ {
+ "type": "doc",
+ "id": "learn/bossroom/bossroom"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bossroom/bossroom-architecture"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bossroom/bossroom-actions"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bossroom/networkobject-parenting"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bossroom/optimizing-bossroom"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bossroom/networkrigidbody"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bossroom/spawn-networkobjects"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Bitesize samples",
+ "items": [
+ {
+ "type": "doc",
+ "id": "learn/bitesize/bitesize-usecases"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bitesize/bitesize-introduction"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bitesize/bitesize-spaceshooter"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bitesize/bitesize-clientdriven"
+ },
+ {
+ "type": "doc",
+ "id": "learn/bitesize/bitesize-dynamicPrefabs"
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Deprecated samples",
+ "items": [
+ {
+ "type": "doc",
+ "id": "learn/bitesize/bitesize-invaders"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "collapsed": true,
+ "type": "category",
+ "label": "Community contributions",
+ "items": [
+ {
+ "type": "doc",
+ "id": "community-contributions/codemonkey"
+ },
+ {
+ "type": "doc",
+ "id": "community-contributions/dilmer"
+ },
+ {
+ "type": "doc",
+ "id": "community-contributions/dapper"
+ }
+ ]
+ },
+ {
+ "type": "doc",
+ "id": "learn/faq"
+ },
+ {
+ "type": "doc",
+ "id": "terms-concepts/mtt-terms"
+ }
+ ]
+}
diff --git a/versions.json b/versions.json
index f4df0f42d..15061fc09 100644
--- a/versions.json
+++ b/versions.json
@@ -1,5 +1,6 @@
[
"current",
+ "2.0.0",
"1.11.0",
"1.10.0",
"1.9.1",