Skip to content

Commit 85d6845

Browse files
committed
Update object spawning page to be distributed authority compatible
1 parent f5a3b7d commit 85d6845

File tree

1 file changed

+31
-22
lines changed

1 file changed

+31
-22
lines changed

com.unity.netcode.gameobjects/Documentation~/basics/object-spawning.md

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Object spawning
22

3-
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.
3+
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 game clients.
44

55
## Network Prefabs
66

@@ -26,14 +26,16 @@ There are four steps to registering a network Prefab with a `NetworkManager`:
2626

2727
### Spawning a Network Prefab (Overview)
2828

29-
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.
29+
When using a [server authoritative networking model](../terms-concepts/authority/#server-authority) only the server or host can spawn netcode objects. Under a [distributed authority networking model](..terms-concepts/authority/#distributed-authority), any game client can spawn netcode objects. The game client that spawned the network object then becomes the [authority](../terms-concepts/authority.md) of that object.
30+
31+
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.
3032
_In most cases, you will want to keep the `NetworkObject` component attached to the root `GameObject` of the network prefab._
3133

32-
By default a newly spawned network Prefab instance is owned by the server unless otherwise specified.
34+
By default a newly spawned network Prefab instance is owned by the authority unless otherwise specified.
3335

3436
See [Ownership](networkobject.md#ownership) for more information.
3537

36-
The following is a basic example of how to spawn a network Prefab instance (with the default server ownership):
38+
The following is a basic example of how to spawn a network Prefab instance:
3739

3840
```csharp
3941
var instance = Instantiate(myPrefab);
@@ -42,6 +44,7 @@ instanceNetworkObject.Spawn();
4244
```
4345

4446
The `NetworkObject.Spawn` method takes 1 optional parameter that defaults to `true`:
47+
4548
```csharp
4649
public void Spawn(bool destroyWithScene = true);
4750
```
@@ -54,27 +57,32 @@ When you set the destroyWithScene property to `false` it will be treated the sam
5457
> 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.
5558
5659
### Taking Prefab Overrides Into Consideration
57-
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.
60+
61+
Sometimes, you might want to use a different prefab instance on the authority compare to other 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.
5862

5963
There are two ways you can accomplish this, as explained below.
6064

6165
#### Get The Network Prefab Override First
66+
6267
This option provides you with the overall view of getting the network prefab override, instantiating it, and then spawning it.
6368

6469
```csharp
6570
var instance = Instantiate(NetworkManager.GetNetworkPrefabOverride(myPrefab));
6671
var instanceNetworkObject = instance.GetComponent<NetworkObject>();
6772
instanceNetworkObject.Spawn();
6873
```
74+
6975
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`.
7076

7177
#### Using InstantiateAndSpawn
78+
7279
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`.
7380

7481
```csharp
7582
var networkObject = NetworkManager.SpawnManager.InstantiateAndSpawn(myPrefab, ownerId);
7683
```
77-
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.
84+
85+
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 original source prefab if running as a server and the override otherwise.
7886

7987
`InstantiateAndSpawn` has several parameters to provide more control over this process:
8088

@@ -84,14 +92,15 @@ InstantiateAndSpawn(NetworkObject networkPrefab, ulong ownerClientId = NetworkMa
8492

8593
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`.
8694

87-
The `forceOverride` parameter, when set to true, will use the override whether you're running as either server or host.
95+
The `forceOverride` parameter, when set to true, will always use the override.
8896

97+
To override prefabs on non-authority game clients, see the [Network prefab handler](./network-prefab-handler.md).
8998

9099
## Destroying / Despawning
91100

92-
By default, a spawned network Prefab instance that is destroyed on the server/host will be automatically destroyed on all clients.
101+
By default, a spawned network Prefab instance that is destroyed on the authority will be automatically destroyed on all clients.
93102

94-
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.
103+
When a client disconnects, all network Prefab instances dynamically 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.
95104

96105
To do this at runtime:
97106

@@ -108,9 +117,9 @@ As an alternative way, you can make the `NetworkObject.DontDestroyWithOwner` pro
108117

109118
### Despawning
110119

111-
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.
120+
Only the authority 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. Non-authority clients will always be notified and will mirror the despawn behavior. If you despawn and destroy on the authority then all other connected clients will despawn and then destroy the `GameObject` that the `NetworkObjet` component is attached to.
112121

113-
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.
122+
On the non-authority 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). To allow non-authority clients to destroy objects they do not own, have the relevant client invoke an RPC to defer the despawning on the authority side.
114123

115124
The only way to despawn `NetworkObject` for a specific client is to use `NetworkObject.NetworkHide`.
116125
See: [Object Visibility](object-visibility.md) for more information on this.
@@ -136,8 +145,8 @@ This type of dynamically spawned `NetworkObject` typically is a simple wrapper c
136145

137146
public override void OnNetworkSpawn()
138147
{
139-
// Only the server spawns, clients will disable this component on their side
140-
enabled = IsServer;
148+
// Only the authority spawns, other clients will disable this component on their side
149+
enabled = HasAuthority;
141150
if (!enabled || PrefabToSpawn == null)
142151
{
143152
return;
@@ -156,7 +165,7 @@ This type of dynamically spawned `NetworkObject` typically is a simple wrapper c
156165

157166
public override void OnNetworkDespawn()
158167
{
159-
if (IsServer && DestroyWithSpawner && m_SpawnedNetworkObject != null && m_SpawnedNetworkObject.IsSpawned)
168+
if (HasAuthority && DestroyWithSpawner && m_SpawnedNetworkObject != null && m_SpawnedNetworkObject.IsSpawned)
160169
{
161170
m_SpawnedNetworkObject.Despawn();
162171
}
@@ -171,11 +180,11 @@ Consumable and/or items that can be picked up by a player or NPC(that is, a weap
171180
> 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).
172181
173182
> [!NOTE]
174-
> 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.
183+
> 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 all game clients each time an instance is spawned.
175184
176185
### Pooled Dynamic Spawning
177186

178-
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.
187+
Pooled dynamic spawning is when netcode objects (`GameObject` with one `NetworkObject` component) aren't destroyed on game clients 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.
179188

180189
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.
181190

@@ -193,7 +202,7 @@ public class SinglePooledDynamicSpawner : NetworkBehaviour, INetworkPrefabInstan
193202

194203
private void Start()
195204
{
196-
// Instantiate our instance when we start (for both clients and server)
205+
// Instantiate our instance when we start (for all connected game clients)
197206
m_PrefabInstance = Instantiate(PrefabToSpawn);
198207

199208
// Get the NetworkObject component assigned to the Prefab instance
@@ -219,7 +228,7 @@ public class SinglePooledDynamicSpawner : NetworkBehaviour, INetworkPrefabInstan
219228
}
220229

221230
/// <summary>
222-
/// Invoked only on clients and not server or host
231+
/// Invoked only on non-authority clients
223232
/// INetworkPrefabInstanceHandler.Instantiate implementation
224233
/// Called when Netcode for GameObjects need an instance to be spawned
225234
/// </summary>
@@ -232,7 +241,7 @@ public class SinglePooledDynamicSpawner : NetworkBehaviour, INetworkPrefabInstan
232241
}
233242

234243
/// <summary>
235-
/// Client and Server side
244+
/// Called on all game clients
236245
/// INetworkPrefabInstanceHandler.Destroy implementation
237246
/// </summary>
238247
public void Destroy(NetworkObject networkObject)
@@ -242,7 +251,7 @@ public class SinglePooledDynamicSpawner : NetworkBehaviour, INetworkPrefabInstan
242251

243252
public void SpawnInstance()
244253
{
245-
if (!IsServer)
254+
if (!HasAuthority)
246255
{
247256
return;
248257
}
@@ -261,7 +270,7 @@ public class SinglePooledDynamicSpawner : NetworkBehaviour, INetworkPrefabInstan
261270
// INetworkPrefabInstanceHandler interface with the Prefab handler
262271
NetworkManager.PrefabHandler.AddHandler(PrefabToSpawn, this);
263272

264-
if (!IsServer || !SpawnPrefabAutomatically)
273+
if (!HasAuthority || !SpawnPrefabAutomatically)
265274
{
266275
return;
267276
}
@@ -318,7 +327,7 @@ This reduces the complexity down to setting the SpawnedComponents `GameObject` t
318327
319328
## In-Scene Placed `NetworkObject`
320329

321-
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.
330+
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 authority-side and synchronized with other clients once they finish loading the same scene.
322331

323332
[Learn more about In-Scene Placed `NetworkObjects`](scenemanagement/inscene-placed-networkobjects.md)
324333

0 commit comments

Comments
 (0)