Skip to content

Commit 9260d94

Browse files
doc: update
Adding OnNetworkPreDespawn documentation. Adjusted the NetworkBehaviour documentation to include some best practices information.
1 parent 48bc4c0 commit 9260d94

File tree

4 files changed

+97
-28
lines changed

4 files changed

+97
-28
lines changed

com.unity.netcode.gameobjects/Documentation~/components/core/networkbehaviour-synchronize.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ OnNetworkSpawn | NetworkObject | During spawn initializ
2323
OnNetworkPostSpawn | NetworkObject | Post-spawn actions | Client and server
2424
OnNetworkSessionSynchronized | All NetworkObjects | New client finished synchronizing | Client-side only
2525
OnInSceneObjectsSpawned | In-scene NetworkObjects | New client finished synchronizing or a scene is loaded | Client and server
26+
OnNetworkPreDespawn | NetworkObject | Invoked before de-spawning NetworkObject | Client and server
2627

2728
In addition to the methods above, there are two special case convenience methods:
2829

com.unity.netcode.gameobjects/Documentation~/components/core/networkbehaviour.md

Lines changed: 96 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,40 @@ Dynamically spawned | In-scene placed
2525
`OnNetworkSpawn` | `Start`
2626
`Start` | `OnNetworkSpawn`
2727

28-
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.
28+
### Spawn process & invocation order
29+
30+
If you are familiar with the [event function execution order](https://docs.unity3d.com/6000.0/Documentation/Manual/execution-order.html) and/or the [script execution order](https://docs.unity3d.com/6000.0/Documentation/Manual/script-execution-order.html), then you already know that the execution order dictates the order of operations for your component scripts and you might have already had to adjust execution order of one component relative to another because your component scripts' order of operations required it. If you are not familiar with event function or script execution order, then it is recommended to read/review over the above two links.
31+
32+
When you make the decision to add a multiplayer element to your project, you will inevitably end up adding netcode scripts. Netcode scripts add an additional dimension to the over-all order of operations and script execution order that you need to consider prior to designing any complex netcode system comprised of several netcode scripts.
33+
34+
`NetworkBehaviour` includes several virtual methods that are invoked at different spawn stages of a `NetworkObject` as seen in the diagram below:
35+
36+
![NetwrokBehaviour Spawn Process & Method Invocation Order](../../images/NetworkBehaviour/NetworkBehaviourSpawnOrder.png)
37+
38+
After having looked over the diagram above, we can see that "NetworkBehaviour1" always invokes its methods before "NetworkBehaviour2". The order of `NetworkBehaviour` components is determined by their placement/position, within the inspector view of the editor, relative to the `NetworkObject`. So, it would be safe to assume that "NetworkBehaviour1" was placed somewhere above "NetworkBehaviour2". Looking at the above diagram, we can also determine that a `NetworkObject` goes through three states during the spawn process:
39+
40+
**Spawn states**
41+
- Pre-Spawning: Before any netcode relative property has been set.
42+
- Spawning: Netcode properties have been set.
43+
- Spawned: All `NetworkBehaviour` components have run through their spawn logic.
44+
45+
For each spawn state there is a corresponding `NetworkBehaviour` virtual method:
46+
47+
**Spawn state related methods**
48+
- Pre-Spawning --> `NetworkBehaviour.OnNetworkPreSpawn`.
49+
- Spawning --> `NetworkBehaviour.OnNetworkSpawn`
50+
- Spawned --> `NetworkBehaviour.OnNetworkPostSpawn`
51+
52+
If you read over the above diagram's notes to the right, you would notice that it provides additional information about what kind of script logic might be pertinent for each specific spawn state. The general rules of thumb for each spawn state method:
53+
54+
- `NetworkBehaviour.OnNetworkPreSpawn`: Used for any post serialization configuration needs that has no dependencies on any of the netcode properties. As an example, you wouldn't know the execution context since `NetworkBehaviour.IsServer` and `NetworkBehaviour.IsClient` have yet to be set (along with any other netcode related property). This is why a reference to the `NetworkManager` is passed into this virtual method.
55+
56+
- `NetworkBehaviour.OnNetworkSpawn`: Used to handle any `NetworkBehaviour` relative configurations based off if any serialized states that might have been passed in (or the like). Since we know each `NetworkBehaviour` component's `OnNetworkSpawn` method has a distinct order of operations relative to the other `NetworkBehaviour` components, we can look at the above diagram and come to the conclusion that trying to access some field/property of "NetworkBehavior2", if configured/set in the `OnNetworkSpawn` method, during the invocation of the `OnNetworkSpawn` method of "NetworkBehaviour1" would lead to an order of operations issue since "NetworkBehaviour2" configures the field/property during its `OnNetworkSpawn` method.
57+
58+
- `NetworkBehaviour.OnNetworkPostSpawn`: Any script logic added here can assume that all fields/properties configured during `OnNetworkSpawn` has completed. Accessing any field/property of "NetworkBehavior2" within `OnNetworkPostSpawn` script in "NetworkBehaviour1" would pose no order of operations issues since we know that "NetworkBehavior2" had already set those values during `OnNetworkSpawn`.
59+
60+
61+
*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.*
2962

3063
### Disabling NetworkBehaviours when spawning
3164

@@ -43,6 +76,34 @@ Dynamically spawned | In-scene placed (disabled NetworkBehaviour components)
4376
> 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.
4477
> It's recommended to disable a NetworkBehaviour component rather than the GameObject itself.
4578
79+
### Pre-spawn and MonoBehaviour methods
80+
81+
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.
82+
83+
- When active: `Awake`, `Start`, `FixedUpdate`, `Update`, and `LateUpdate` are invoked.
84+
- When not active: `Awake`, `Start`, `FixedUpdate`, `Update`, and `LateUpdate` are not invoked.
85+
86+
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.
87+
88+
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.
89+
90+
Additionally, the `FixedUpdate`, `Update`, and `LateUpdate` methods, if defined and the GameObject is active in the hierarchy, will still be invoked on NetworkBehaviours 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:
91+
92+
```csharp
93+
private void Update()
94+
{
95+
// If the NetworkObject is not yet spawned, exit early.
96+
if (!IsSpawned)
97+
{
98+
return;
99+
}
100+
// Netcode specific logic executed when spawned.
101+
}
102+
```
103+
104+
Alternately, you could leverage from the [NetworkUpdateLoop](../../advanced-topics/network-update-loop-system/index.md) system by making a NetworkBehaviour implement the `INetworkUpdateSystem` interface and register each instance for a specific `NetworkUpdateStage` during the `OnNetworkSpawn` or `OnNetworkPreSpawn` invocations and then use your own script logic to determine which instance should be updating.
105+
106+
_This can be useful when you want only the owner, authority, or non-authority to be updating and can help to remove checks like the above. It can also reduce the performance cost of all instances that do not register for the update stage (depending upon how many instances are spawned)._
46107

47108
### Dynamically spawned NetworkObjects
48109

@@ -79,49 +140,56 @@ public class MyNetworkBehaviour : NetworkBehaviour
79140

80141
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.
81142

82-
## Despawning
143+
## De-spawning
144+
145+
When a NetworkObject is de-spawned, it will first iterate over and invoke `NetworkBehaviour.OnNetworkPreDespawn` and then `NetworkBehaviour.OnNetworkDespawn`for each of its assigned NetworkBehaviours.
83146

84-
`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`.
147+
- `NetworkBehaviour.OnNetworkPreDespawn`: This is invoked by the associated `NetworkObject` instance at the very start of the de-spawn process. The associated `NetworkObject` is still considered "spawned" when `OnNetworkPreDespawn` is invoked.
148+
- `NetworkBehaviour.OnNetworkDespawn`: This is invoked while the `NetworkObject` instance is in the middle of the de-spawn process. The associated `NetworkObject` should not be considered spawned and there is no guarantee that other `NetworkBehaviour` components associated with the `NetworkObject` have valid netcode related state ([see the "De-spawn process & invocation order" section for more information](#de-spawn-process--invocation-order)).
85149

86-
### Destroying
150+
### De-spawning but not destroying
151+
152+
When de-spawned and not destroyed, the associated `GameObject` instance, and all children of that `GameObject`, will persist until it is destroyed. Under this scenario (_de-spawn but not destroy_), the would de-spawn but not destroy the `NetworkObject` instance with the intention of re-using/re-spawning the instance. In order to de-spawn and not destroy, you must invoke `NetworkObject.Despawn` while passing in `false` to not destroy the associated root `GameObject`.
153+
154+
### De-spawning and destroying
155+
156+
There are two scenarios where the object instance will be de-spawned and the GameObject destroyed:
157+
158+
- When invoking `NetworkObject.Despawn` and either not passing any parameters (_it defaults to destroy_) or passing in `true` for the `destroy` parameter.
159+
- When invoking `GameObject.Destroy` on the `GameObject` that the `NetworkObject` component belongs to.
160+
- _This will result in `NetworkObject.Despawn` to be invoked first (internally) and then `NetworkObject.OnDestroy`_ is invoked after that.
87161

88162
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.
89163

90-
If you override the virtual `OnDestroy` method it's important to always invoke the base like such:
164+
_NetworkBehaviour handles other internal destroy related clean up tasks and requires that you invoke the base `OnDestroy` method to operate properly._
165+
166+
If you override the virtual `OnDestroy` method it's important to always invoke the base `OnDestroy` method at the end of your script like such:
91167

92168
```csharp
93169
public override void OnDestroy()
94170
{
95-
// Clean up your NetworkBehaviour
171+
// Local NetworkBehaviour clean up script here:
96172
97-
// Always invoked the base
173+
// Invoke the base after local NetworkBehaviour clean up script (last).
98174
base.OnDestroy();
99175
}
100176
```
101177

102-
NetworkBehaviour handles other destroy clean up tasks and requires that you invoke the base `OnDestroy` method to operate properly.
103-
104-
## Pre-spawn and MonoBehaviour methods
105-
106-
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.
178+
> [!NOTE] Destroying the GameObject
179+
> When destroying a NetworkObject from within an associated `NetworkBehaviour` component script, you always want to destroy the `NetworkObject.gameObject` and not the `NetworkBehaviour.gameObject` in the event the NetworkBehaviour is located on a child GameObject nested under the NetworkObject's GameObject.
107180
108-
- When active: `Awake`, `Start`, `FixedUpdate`, `Update`, and `LateUpdate` are invoked.
109-
- When not active: `Awake`, `Start`, `FixedUpdate`, `Update`, and `LateUpdate` are not invoked.
181+
### De-spawn process & invocation order
110182

111-
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.
183+
![NetwrokBehaviour Spawn Process & Method Invocation Order](../../images/NetworkBehaviour/NetworkBehaviourDeSpawnOrder.png)
112184

113-
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.
185+
Similar to the [spawn process & invocation order section above](#spawn-process--invocation-order), the NetworkBehaviour breaks up the de-spawn process into three states:
114186

115-
Additionally, the `FixedUpdate`, `Update`, and `LateUpdate` methods, if defined and the GameObject is active in the hierarchy, will still be invoked on NetworkBehaviours 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:
187+
**De-spawn states**
188+
- Spawned: This state exists on the frame that the `NetworkObject` is being de-spawned, but before any internal de-spawn script has been invoked. The de-spawn is inevitable but the NetworkObject and all `NetworkBehaviour` components have their netcode related states intact.
189+
- De-spawning: The `NetworkObject` has begun the de-spawn process. `NetworkBehaviour` components might have reset or disposed of certain fields and/or properties. Upon the last `NetworkBehaviour` component having invoked its `OnNetworkDespawn` method, the `NetworkObject` is considered de-spawned. If the `NetworkObject` was de-spawned but not destroyed then the instance would persist and if de-spawned to destroy then the `GameObject` instance and all components would be destroyed.
190+
- De-spawned: The `NetworkObject` has finished the de-spawn process. `NetworkBehaviour` components might have reset or disposed of certain fields and/or properties. Local instance can be re-spawned if de-spawn was not while it was being destroyed.
116191

117-
```csharp
118-
private void Update()
119-
{
120-
// If the NetworkObject is not yet spawned, exit early.
121-
if (!IsSpawned)
122-
{
123-
return;
124-
}
125-
// Netcode specific logic executed when spawned.
126-
}
127-
```
192+
**De-spawn state related methods**
193+
- Spawned --> `NetworkBehaviour.OnNetworkPreDespawn`.
194+
- De-spawning --> `NetworkBehaviour.OnNetworkDespawn`
195+
- De-spawned --> *No state related method*
276 KB
Loading
211 KB
Loading

0 commit comments

Comments
 (0)