Skip to content

Commit a049f82

Browse files
committed
chore: Add NetworkObject ownership docs and update related docs
1 parent 454d04f commit a049f82

File tree

8 files changed

+225
-97
lines changed

8 files changed

+225
-97
lines changed

com.unity.netcode.gameobjects/Documentation~/TableOfContents.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
* [Distributed authority WebGL quickstart](learn/distributed-authority-webgl.md)
88
* [Networking concepts](networking-concepts.md)
99
* [Authority](terms-concepts/authority.md)
10-
* [Ownership](terms-concepts/ownership.md)
1110
* [Network topologies](network-topologies.md)
1211
* [Network topologies](terms-concepts/network-topologies.md)
1312
* [Client-server](terms-concepts/client-server.md)
1413
* [Listen server host architecture](learn/listenserverhostarchitecture.md)
1514
* [Distributed authority topologies](terms-concepts/distributed-authority.md)
15+
* [Ownership](terms-concepts/ownership.md)
1616
* [Configuration](configuration.md)
1717
* [Configuring connections](configure-connections.md)
1818
* [Connection approval](basics/connection-approval.md)
@@ -23,6 +23,7 @@
2323
* [Network components](network-components.md)
2424
* [Core components](components/core/corecomponents.md)
2525
* [NetworkObject](components/core/networkobject.md)
26+
* [NetworkObject ownership](advanced-topics/networkobject-ownership.md)
2627
* [NetworkObject parenting](advanced-topics/networkobject-parenting.md)
2728
* [NetworkBehaviour](components/core/networkbehaviour.md)
2829
* [Synchronizing & Order of Operations](components/core/networkbehaviour-synchronize.md)
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# NetworkObject ownership
2+
3+
Before reading these docs, familiarize yourself with the concepts of [ownership](../terms-concepts/ownership.md) and [authority](../terms-concepts/authority.md) within Netcode for GameObjects. It's also recommended to read the documentation on the [NetworkObject](../components/core/networkobject.md).
4+
5+
To see if the local client is the owner of a NetworkObject, you can check the[`NetworkObject.IsOwner`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.IsOwner.html) or the [`NetworkBehaviour.IsOwner`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.IsOwner.html) property.
6+
7+
To see if the server owns a NetworkObject, you can check the [`NetworkObject.IsOwnedByServer`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.IsOwnedByServer.html) or the [`NetworkBehaviour.IsOwnedByServer`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.IsOwnedByServer.html) property.
8+
9+
> [!NOTE]
10+
> When you want a specific NetworkObject to keep existing after the owner leaves the session, you can set the `NetworkObject.DontDestroyWithOwner` property to `true`. This ensures that the owned NetworkObject isn't destroyed as the owner leaves.
11+
12+
## Authority ownership
13+
14+
If you're creating a client-server game and you want a client to control more than one NetworkObject, or if you're creating a distributed authority game and the authority/current owner of the object would like to change ownership, use the following ownership methods.
15+
16+
The default `NetworkObject.Spawn` method will set server-side ownership when using a client-server topology. When using a distributed authority topology, this method will set the client who calls the method as the owner.
17+
18+
```csharp
19+
GetComponent<NetworkObject>().Spawn();
20+
```
21+
22+
To change ownership, the authority uses the `ChangeOwnership` method:
23+
24+
```csharp
25+
GetComponent<NetworkObject>().ChangeOwnership(clientId);
26+
```
27+
28+
## Client-server ownership
29+
30+
In a client-server game, to give ownership back to the server use the `RemoveOwnership` method:
31+
32+
```csharp
33+
GetComponent<NetworkObject>().RemoveOwnership();
34+
```
35+
36+
> [!NOTE]
37+
> `RemoveOwnership` isn't supported when using a [distributed authority network topology](../../terms-concepts/distributed-authority.md).
38+
39+
## Distributed authority ownership
40+
41+
When building a distributed authority game, it is important to remember that owner of an object is always the authority for that object. As the simulation is shared between clients, it is important that ownership can be easily passed between game clients. This enables:
42+
43+
1. Evenly sharing the load of the game simulation via redistributing objects whenever a player joins or leaves.
44+
2. Allowing ownership to be transferred immediately to a client in situations where a client is interacting with that object and so wants to remove lag from those interactions.
45+
3. Controlling when and object is safe and/or valid to be transferred.
46+
47+
The authority of any object can always change ownership as outlined in [authority ownership](#authority-ownership).
48+
49+
### Ownership permissions settings
50+
51+
The following ownership permission settings, defined by [`NetworkObject.OwnershipStatus`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.OwnershipStatus.html), control how ownership of objects can be changed during a distributed authority session:
52+
53+
| **Ownership setting** | **Description** |
54+
|-------------------|-------------|
55+
| `None` | Ownership of this NetworkObject can't be redistributed, requested, or transferred (a Player might have this, for example). |
56+
| `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. |
57+
| `Transferable` | Any client can change ownership of this NetworkObject at any time, as long as ownership is not locked or a request is pending. |
58+
| `RequestRequired` | Ownership of this NetworkObject must be requested before ownership can be changed. |
59+
| `SessionOwner` | This NetworkObject is always owned by the [session owner](distributed-authority.md#session-ownership) and can't be transferred or distributed. If the session owner changes, this NetworkObject is automatically transferred to the new session owner. |
60+
61+
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.
62+
63+
```csharp
64+
// To lock an object from any ownership changes
65+
GetComponent<NetworkObject>().SetOwnershipLock(true);
66+
67+
// To unlock an object so that the underlying ownership permissions apply again
68+
GetComponent<NetworkObject>().SetOwnershipLock(false);
69+
```
70+
71+
### Changing ownership in distributed authority
72+
73+
When a NetworkObject is set with `OwnershipPermissions.Transferable` any client can change ownership to any other client using the `ChangeOwnership` method:
74+
75+
```csharp
76+
GetComponent<NetworkObject>().ChangeOwnership(clientId);
77+
78+
// To change ownership to self
79+
GetComponent<NetworkObject>().ChangeOwnership(NetworkManager.Singleton.LocalClientId);
80+
```
81+
82+
When a non-authoritative game client calls `ChangeOwnership`, the ownership change can fail. On a failed attempt to change ownership, the `OnOwnershipPermissionsFailure` callback will be invoked with a [`NetworkObject.OwnershipPermissionsFailureStatus`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.OwnershipPermissionsFailureStatus.html) to give information on the failure.
83+
84+
```csharp
85+
internal class MyTransferrableBehaviour : NetworkBehaviour
86+
{
87+
public override void OnNetworkSpawn()
88+
{
89+
NetworkObject.OnOwnershipPermissionsFailure = OnOwnershipPermissionsFailure;
90+
base.OnNetworkSpawn();
91+
}
92+
93+
private void OnOwnershipPermissionsFailure(NetworkObject.OwnershipPermissionsFailureStatus ownershipPermissionsFailureStatus)
94+
{
95+
// Called on the calling client when NetworkObject.ChangeOwnership() has failed
96+
}
97+
98+
public override void OnNetworkDespawn()
99+
{
100+
NetworkObject.OnOwnershipPermissionsFailure = null;
101+
base.OnNetworkDespawn();
102+
}
103+
}
104+
```
105+
106+
### Requesting ownership in distributed authority
107+
108+
When a NetworkObject is set with `OwnershipPermissions.RequestRequired` any client can request the ownership for themselves using the `RequestOwnership` method:
109+
110+
```csharp
111+
var requestStatus = GetComponent<NetworkObject>().RequestOwnership();
112+
```
113+
114+
The `RequestOwnership` will return an [`OwnershipRequestStatus`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.OwnershipRequestStatus.html) to indicate the initial status of the request. To view the result of the request, `OnOwnershipRequestResponse` callback will be invoked with a [`NetworkObject.OwnershipRequestResponseStatus`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.OwnershipRequestResponseStatus.html).
115+
116+
```csharp
117+
internal class MyRequestableBehaviour : NetworkBehaviour
118+
{
119+
public override void OnNetworkSpawn()
120+
{
121+
NetworkObject.OnOwnershipRequestResponse = OnOwnershipRequestResponse;
122+
base.OnNetworkSpawn();
123+
}
124+
125+
private void OnOwnershipRequestResponse(NetworkObject.OwnershipRequestResponseStatus ownershipRequestResponseStatus)
126+
{
127+
// Called when the requesting client has gotten a response to their request
128+
}
129+
130+
public override void OnNetworkDespawn()
131+
{
132+
NetworkObject.OnOwnershipRequestResponse = null;
133+
base.OnNetworkDespawn();
134+
}
135+
}
136+
```
137+
138+
## Spawn with ownership
139+
140+
To spawn a `NetworkObject` that is [owned](../../terms-concepts/ownership.md) by a different game client than the one doing the spawning, use the following:
141+
142+
```csharp
143+
GetComponent<NetworkObject>().SpawnWithOwnership(clientId);
144+
```
145+
146+
> [!NOTE]
147+
> Using `SpawnWithOwnership` can result in unexpected behaviour when the spawning game client makes any other changes on the object immediately after spawning.
148+
149+
Using `SpawnWithOwnership` and then editing the object locally will mean the client doing the spawning will behave as the "spawn authority". The spawn authority will have limited local [authority](../terms-concepts/authority.md) over the object, but will not have [ownership](../terms-concepts/ownership.md) of the object that is spawned. This means any owner-specific checks during the spawn sequence will not be invoked on the spawn authority side.
150+
151+
Any time you would like to spawn an object for another client and then immediately make adjustments on that object, it's instead recommended to use `Spawn`. After adjusting, the spawn authority can immediately follow with a call to `ChangeOwnership`.
152+
153+
```csharp
154+
[Rpc(SendTo.Authority)]
155+
void SpawnForRequestingPlayer(RpcParams rpcParams = default) {
156+
var instance = Instantiate(myprefab).GetComponent<NetworkObject>();
157+
instance.Spawn();
158+
instance.transform.position = transform.position;
159+
instance.GetComponent<MyNetworkBehaviour>.MyNetworkVar.Value = initialValue;
160+
instance.ChangeOwnership(rpcParams.Receive.SenderClientId)
161+
}
162+
```
163+
164+
This flow allows the spawning client to completely spawn and finish initializing the object locally before transferring the ownership to another game client.

com.unity.netcode.gameobjects/Documentation~/advanced-topics/networkobject-parenting.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# NetworkObject parenting
22

3-
### Overview
3+
## Overview
44

5-
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.
5+
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. Otherwise, you can use the [AttachableBehaviour](../components/helper/attachablebehaviour.md) and [AttachableNode](../components/helper/attachablenode.md) helper components to synchronize other types of parenting.
66

7-
### Parenting rules
7+
## Parenting rules
88

99
- Setting the parent of a child's `Transform` directly (that is, `transform.parent = childTransform;`) always uses the default `WorldPositionStays` value of `true`.
1010
- It's recommended to always use the `NetworkObject.TrySetParent` method when parenting if you plan on changing the `WorldPositionStays` default value.
1111
- Likewise, it's also recommended to use the `NetworkObject.TryRemoveParent` method to remove a parent from a child.
12-
- 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.
12+
- When an [authority](../terms-concepts/authority.md) 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.
1313
- 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.
1414
- During runtime, this parent-child hierarchy remains true unless the user code removes the GameObject parent from the child NetworkObject component.
1515
- **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.
@@ -38,12 +38,16 @@ virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObject) { }
3838
> [!NOTE] Multi-generation children and scale
3939
> 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.
4040
41-
### Only a server (or a host) can parent NetworkObjects
41+
### Who can parent NetworkObjects
4242

43-
Similar to [Ownership](../basics/networkobject#ownership), only the server (or host) can control NetworkObject component parenting.
43+
By default, only the [authority](../terms-concepts/authority.md) of an object can change the parenting of the object. This means in a client-server game, only the server (or host) can control NetworkObject component parenting. In a distributed authority game the owner of the object can always parent the object.
44+
45+
To allow the [owner](../terms-concepts/ownership.md) to parent their owned object in a client-server game, use the [`NetworkObject.AllowOwnerToParent`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_AllowOwnerToParent) property.
46+
47+
![image](../images/networkobject/allowOwnerToParent.png)
4448

4549
> [!NOTE]
46-
> 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.
50+
> 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 authority. Upon receiving the RPC message, the authority then handles parenting the NetworkObject component.
4751
4852
### Only parent under a NetworkObject Or nothing (root or null)
4953

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ When using a [server authoritative networking model](../terms-concepts/authority
3030

3131
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.
3232

33-
By default, a newly spawned network prefab instance is owned by the authority unless otherwise specified.
34-
35-
See [Ownership](networkobject.md#ownership) for more information.
33+
See [NetworkObject ownership](../advanced-topics/networkobject-ownership.md) for more information.
3634

3735
The following is a basic example of how to spawn a network prefab instance:
3836

0 commit comments

Comments
 (0)