diff --git a/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md b/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md index 3b683f8770..e78e7192f6 100644 --- a/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md +++ b/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md @@ -7,12 +7,12 @@ * [Distributed authority WebGL quickstart](learn/distributed-authority-webgl.md) * [Networking concepts](networking-concepts.md) * [Authority](terms-concepts/authority.md) - * [Ownership](terms-concepts/ownership.md) * [Network topologies](network-topologies.md) * [Network topologies](terms-concepts/network-topologies.md) * [Client-server](terms-concepts/client-server.md) * [Listen server host architecture](learn/listenserverhostarchitecture.md) * [Distributed authority topologies](terms-concepts/distributed-authority.md) + * [Ownership](terms-concepts/ownership.md) * [Configuration](configuration.md) * [Configuring connections](configure-connections.md) * [Connection approval](basics/connection-approval.md) @@ -23,9 +23,11 @@ * [Network components](network-components.md) * [Core components](components/core/corecomponents.md) * [NetworkObject](components/core/networkobject.md) + * [NetworkObject ownership](components/core/networkobject-ownership.md) * [NetworkObject parenting](advanced-topics/networkobject-parenting.md) * [NetworkBehaviour](components/core/networkbehaviour.md) * [Synchronizing & Order of Operations](components/core/networkbehaviour-synchronize.md) + * [NetworkBehaviour ownership](components/core/networkbehaviour-ownership.md) * [NetworkManager](components/core/networkmanager.md) * [PlayerObjects and player prefabs](components/core/playerobjects.md) * [Helper Components](components/helper/helpercomponents.md) diff --git a/com.unity.netcode.gameobjects/Documentation~/advanced-topics/message-system/rpc-compatibility.md b/com.unity.netcode.gameobjects/Documentation~/advanced-topics/message-system/rpc-compatibility.md index 74947a825f..81fb63e696 100644 --- a/com.unity.netcode.gameobjects/Documentation~/advanced-topics/message-system/rpc-compatibility.md +++ b/com.unity.netcode.gameobjects/Documentation~/advanced-topics/message-system/rpc-compatibility.md @@ -36,11 +36,11 @@ However, the RPC signature hash doesn't change when the names of the parameters 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. | +| Compatibility | | Description | +| -- | -- | -- | +| Cross-Build Compatibility | **Yes** | As long as the RPC method signature is kept the same, it will be compatible between different builds. | +| Cross-Version Compatibility | **Yes** | As long as the RPC method signature is kept the same, it will be compatible between different versions. | +| Cross-Project Compatibility | No | 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 diff --git a/com.unity.netcode.gameobjects/Documentation~/advanced-topics/networkobject-parenting.md b/com.unity.netcode.gameobjects/Documentation~/advanced-topics/networkobject-parenting.md index 5c630b60ed..97ef1a0538 100644 --- a/com.unity.netcode.gameobjects/Documentation~/advanced-topics/networkobject-parenting.md +++ b/com.unity.netcode.gameobjects/Documentation~/advanced-topics/networkobject-parenting.md @@ -1,15 +1,15 @@ # NetworkObject parenting -### Overview +## 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. +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. -### Parenting rules +## 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. +- 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. - 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. @@ -35,15 +35,26 @@ If you aren't completely familiar with transform parenting in Unity, then it's h virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObject) { } ``` -> [!NOTE] Multi-generation children and scale +> [!NOTE] +> 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 +### Who can parent NetworkObjects + +#### Under a spawned NetworkObject + +The [owner](../terms-concepts/ownership.md) of a NetworkObject can always parent that NetworkObject under any other spawned NetworkObject. This works regardless of who owns the other NetworkObject. + +#### Under other GameObjects + +By default, only the [authority](../terms-concepts/authority.md) of a NetworkObject can parent a NetworkObject under a non-networked 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](../terms-concepts/ownership.md) of the object can always parent the object. + +To allow the owner 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. -Similar to [Ownership](../basics/networkobject#ownership), only the server (or host) can control NetworkObject component parenting. +![image](../images/networkobject/allowOwnerToParent.png) > [!NOTE] -> 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. +> 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. ### Only parent under a NetworkObject Or nothing (root or null) diff --git a/com.unity.netcode.gameobjects/Documentation~/basics/object-spawning.md b/com.unity.netcode.gameobjects/Documentation~/basics/object-spawning.md index 56202b919f..da84833493 100644 --- a/com.unity.netcode.gameobjects/Documentation~/basics/object-spawning.md +++ b/com.unity.netcode.gameobjects/Documentation~/basics/object-spawning.md @@ -30,9 +30,7 @@ When using a [server authoritative networking model](../terms-concepts/authority 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 authority unless otherwise specified. - -See [Ownership](networkobject.md#ownership) for more information. +See [NetworkObject ownership](../components/core/networkobject-ownership.md) for more information. The following is a basic example of how to spawn a network prefab instance: diff --git a/com.unity.netcode.gameobjects/Documentation~/components/core/networkbehaviour-ownership.md b/com.unity.netcode.gameobjects/Documentation~/components/core/networkbehaviour-ownership.md new file mode 100644 index 0000000000..4136165022 --- /dev/null +++ b/com.unity.netcode.gameobjects/Documentation~/components/core/networkbehaviour-ownership.md @@ -0,0 +1,68 @@ +# NetworkBehaviour ownership + +Before reading these docs, ensure you understand the concepts of [ownership](../terms-concepts/ownership.md) and [NetworkObject ownership](./networkobject-ownership.md). It's also important to be familiar with the [NetworkBehaviour](./networkbehaviour.md) + +The owner of each NetworkBehaviour in your game is decided by the owner of that NetworkBehaviour's NetworkObject. The NetworkObject is found as a property on the NetworkBehaviour: [`NetworkBehaviour.NetworkObject`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html#Unity_Netcode_NetworkBehaviour_NetworkObject). + +## Helpful properties + +> [!NOTE] +> The following properties are only valid if the NetworkBehaviour has been spawned. Use [`NetworkBehaviour.IsSpawned`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html#Unity_Netcode_NetworkBehaviour_IsSpawned) to check the spawned status of the NetworkBehaviour + +To see if the local client is the owner of a NetworkBehaviour, you can check the[`NetworkBehaviour.IsOwner`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html#Unity_Netcode_NetworkBehaviour_IsOwner) property. + +To see if the server owns a NetworkBehaviour, you can check the [`NetworkBehaviour.IsOwnedByServer`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html#Unity_Netcode_NetworkBehaviour_IsOwnedByServer) property. + +To see if the local client has authority of a NetworkBehaviour, you can check the[`NetworkBehaviour.HasAuthority`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html#Unity_Netcode_NetworkBehaviour_HasAuthority) property. + +## Detecting ownership changes + +There are three functions that can be implemented to detect ownership changes on a NetworkBehaviour. These functions are invoked in the order they are listed here. + +### [OnLostOwnership](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html#Unity_Netcode_NetworkBehaviour_OnLostOwnership) + +When using a [client-server network topology](../../terms-concepts/client-server.md) `OnLostOwnership` is invoked on both the server any time a connected client loses ownership of this NetworkBehaviour. It is also invoked on the game client who just lost ownership. + +In a [distributed authority network topology](../../terms-concepts/distributed-authority.md) `OnLostOwnership` is invoked on all connected game clients. + +```csharp +void OnLostOwnership() +{ + var newOwner = OwnerClientId; + + // Take action on lost ownership here +} +``` + +### [OnGainedOwnership](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html#Unity_Netcode_NetworkBehaviour_OnGainedOwnership) + +When using a client-server network topology `OnGainedOwnership` is invoked on the server any time ownership is gained. It is also be invoked on the game client who just gained ownership. + +In a distributed authority network topology `OnGainedOwnership` is invoked on all connected game clients. + +`OnGainedOwnership` is invoked after `OnLostOwnership`. + +```csharp +void OnGainedOwnership() +{ + var newOwner = OwnerClientId; + var newOwnerIsMe = IsOwner; + + // Take action on ownership gain here +} +``` + +### [OnOwnershipChanged](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.html#Unity_Netcode_NetworkBehaviour_OnOwnershipChanged_System_UInt64_System_UInt64_) + +Whenever you want notification on any and all ownership changes, implement the `OnOwnershipChanged` method. `OnOwnershipChanged` is invoked on all connected game clients whenever the ownership of the NetworkBehaviour it is implemented on changes. + +`OnOwnershipChanged` is invoked after `OnLostOwnership` and `OnGainedOwnership`. + +```csharp +void OnOwnershipChanged(ulong previousOwnerId, ulong currentOwnerId) +{ + var newOwnerIsMe = IsOwner; + + // Take action on ownership change here +} +``` diff --git a/com.unity.netcode.gameobjects/Documentation~/components/core/networkbehaviour.md b/com.unity.netcode.gameobjects/Documentation~/components/core/networkbehaviour.md index 0e6c21f5fa..0922a6d35a 100644 --- a/com.unity.netcode.gameobjects/Documentation~/components/core/networkbehaviour.md +++ b/com.unity.netcode.gameobjects/Documentation~/components/core/networkbehaviour.md @@ -1,4 +1,4 @@ -# NetworkBehaviour spawning and despawning +# NetworkBehaviour [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. @@ -38,6 +38,7 @@ The diagram above represents how the spawn process works for two NetworkBehaviou NetworkObjects go through three states during the spawn process: **Spawn states** + - Prespawning: Before any netcode-related properties have been set. - Spawning: Netcode-related properties have been set. - Spawned: All NetworkBehaviour components have completed their spawn logic. @@ -98,7 +99,7 @@ private void Update() Alternatively, you can leverage 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. -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). +This can be useful when you want only the [owner](../../terms-concepts/ownership.md), [authority](../../terms-concepts/authority.md), 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). ### Dynamically spawned NetworkObjects @@ -189,4 +190,4 @@ Similar to the [spawn process and invocation order section above](#spawn-process ## Additional resources - [NetworkObjects](networkobject.md) -- [NetworkBehaviour synchronization](networkbehaviour-synchronize.md) \ No newline at end of file +- [NetworkBehaviour synchronization](networkbehaviour-synchronize.md) diff --git a/com.unity.netcode.gameobjects/Documentation~/components/core/networkobject-ownership.md b/com.unity.netcode.gameobjects/Documentation~/components/core/networkobject-ownership.md new file mode 100644 index 0000000000..dfd93e9a52 --- /dev/null +++ b/com.unity.netcode.gameobjects/Documentation~/components/core/networkobject-ownership.md @@ -0,0 +1,268 @@ +# NetworkObject ownership + +Before reading these docs, ensure you understand the concepts of [ownership](../../terms-concepts/ownership.md) and [authority](../../terms-concepts/authority.md) within Netcode for GameObjects. It's also recommended to be familiar with the [NetworkObject](./networkobject.md) and [NetworkBehaviour](./networkbehaviour.md). Ownership behaves slightly differently based on your game's chosen [network topology](../../terms-concepts/network-topologies.md). + +Read more about how to detect when ownership has changed in [NetworkBehaviour ownership](./networkbehaviour-ownership.md). + +## Helpful properties + +> [!NOTE] +> All NetworkObject properties are only valid while the NetworkObject is spawned. Use [`NetworkObject.IsSpawned`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_IsSpawned) to check the spawned status of the NetworkObject. + +To test 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.html#Unity_Netcode_NetworkObject_IsOwner) property. The [`HasAuthority`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_HasAuthority) property can also be used to test whether the current client has authority over the current object. + +To test 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.html#Unity_Netcode_NetworkObject_IsOwnedByServer) property. + +> [!NOTE] +> To assure a spawned NetworkObject persists after the owner leaves a session, set the `NetworkObject.DontDestroyWithOwner` property to true. This assures the client-owned NetworkObject doesn't get destroyed when the owning client leaves. + +## Ownership on spawn + +When building a [client-server game](../../terms-concepts/client-server.md), only the server has the authority to spawn objects. In a [distributed authority game](../../terms-concepts/distributed-authority.md), any connected client can spawn objects. + +The default `NetworkObject.Spawn` method sets the owner of the newly spawned object to the game client who called the spawn method. + +```csharp +var NetworkObject = GetComponent.Spawn(); +``` + +## Spawn with ownership + +To spawn a NetworkObject that is owned by a different game client than the one doing the spawning, use the following: + +```csharp +NetworkObject.SpawnWithOwnership(clientId); +``` + +> [!NOTE] +> Using `SpawnWithOwnership` can result in unexpected behaviour when the spawning game client makes any other changes on the object immediately after spawning. + +Using `SpawnWithOwnership` and then editing the object locally will mean the client doing the spawning will behave as a "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. + +Any time you would like to spawn an object for another client and then immediately make adjustments on that object, it's recommended to use `Spawn`. After adjusting, the spawn authority can immediately follow with a call to `ChangeOwnership`. + +```csharp +public class BreakableSpawner : NetworkBehaviour +{ + private GameObject breakablePrefab; + + [Rpc(SendTo.Authority)] + public void SpawnNewBreakableRpc(RpcParams rpcParams = default) { + var instance = Instantiate(breakablePrefab).GetComponent(); + instance.Spawn(); + + // Here we can set the initial values despite the object being owner authoritative. + instance.transform.position = transform.position; + instance.GetComponent().RemainingHealth.Value = 20; + + instance.ChangeOwnership(rpcParams.Receive.SenderClientId); + } +} + +public class Breakable : NetworkBehaviour +{ + // Note: This NetworkVariable is owner authoritative + public NetworkVariable RemainingHealth = new NetworkVariable(writePerm: NetworkVariableWritePermission.Owner); + + public override void OnNetworkSpawn() + { + if (IsOwner) + { + // SpawnWithOwnership() will not invoke this code on initial spawn. + } + base.OnNetworkSpawn(); + } +} +``` + +This flow allows the spawning client to completely spawn and finish initializing the object locally before transferring the ownership to another game client. + +## Authority ownership + +If you're creating a [client-server](../../terms-concepts/client-server.md) game and you want a client to control more than one NetworkObject, or if you're creating a [distributed authority](../../terms-concepts/distributed-authority.md) game and the authority/current owner of the object would like to change ownership, use the following ownership methods. + +To change ownership, the authority uses the `ChangeOwnership` method: + +```csharp +NetworkObject.ChangeOwnership(clientId); +``` + +Use [spawn with ownership](#spawn-with-ownership) to spawn objects for other game clients. + +## Client-server ownership + +In a client-server game, the server is always the authority of ownership changes. Clients cannot change ownership, the server can interact with ownership as outlined above in [authority ownership](#authority-ownership). Additionally in a client-server game, ownership can be given back to the server using the `RemoveOwnership` method: + +```csharp +NetworkObject.RemoveOwnership(); +``` + +## Distributed authority ownership + +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: + +1. Evenly sharing the load of the game simulation via redistributing objects whenever a player joins or leaves. +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. +3. Controlling when and object is safe and/or valid to be transferred. + +The authority of any object changes ownership as outlined in [authority ownership](#authority-ownership). + +### Ownership permissions settings + +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: + +|**Ownership setting**|Description|Related Property|Multi-select| +|-----|-----|-----|-----| +|`None`|Ownership of this NetworkObject can't be redistributed, requested, or transferred (a Player might have this, for example).||No| +|`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.|[`IsOwnershipDistributable`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_IsOwnershipDistributable)|**Yes**| +|`Transferable`|Any client can change ownership of this NetworkObject at any time, as long as ownership is not locked or a request is pending.|[`IsOwnershipTransferable`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_IsOwnershipTransferable)|**Yes**| +|`RequestRequired`|Ownership of this NetworkObject must be requested before ownership can be changed.|[`IsOwnershipRequestRequired`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_IsOwnershipRequestRequired), [`IsRequestInProgress`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_IsRequestInProgress)|**Yes**| +|`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.|[`IsOwnershipSessionOwner`](Unity_Netcode_NetworkObject_IsOwnershipSessionOwner)|No| + +Ownership permissions can be set in the editor using the **Ownership** dropdown. + +![image](../../images/networkobject/ownershipPermissions.png) + +They can also be set in script using + +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. The [`IsOwnershipLocked`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_IsOwnershipLocked) property can be used to detect if an object has locked ownership. + +```csharp +// To lock an object from any ownership changes +NetworkObject.SetOwnershipLock(true); + +// To unlock an object so that the underlying ownership permissions apply again +NetworkObject.SetOwnershipLock(false); +``` + +### Changing ownership in distributed authority + +When a NetworkObject is set with `OwnershipPermissions.Transferable` any client can change ownership to any other client using the `ChangeOwnership` method: + +```csharp +NetworkObject.ChangeOwnership(clientId); + +// To change ownership to self +NetworkObject.ChangeOwnership(NetworkManager.LocalClientId); +``` + +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. + +```csharp +/* +* When the NetworkObject's permissions includes the OwnershipPermissions.Transferrable flag. +*/ +public class ChangeOwnershipBehaviour : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + NetworkObject.OnOwnershipPermissionsFailure += OnOwnershipPermissionsFailure; + base.OnNetworkSpawn(); + } + + public void TakeOwnership() + { + if (!IsOwner) { + NetworkObject.ChangeOwnership(NetworkManager.LocalClientId); + } + } + + // Override this method on the NetworkBehaviour to detect ownership changes + protected override void OnOwnershipChanged(ulong previous, ulong current) + { + if (IsOwner) + { + // If this is invoked, then the ownership change succeeded! + } + base.OnOwnershipChanged(previous, current); + } + + private void OnOwnershipPermissionsFailure(NetworkObject.OwnershipPermissionsFailureStatus ownershipPermissionsFailureStatus) + { + // If this is invoked then the ownership change failed. + } + + public override void OnNetworkDespawn() + { + NetworkObject.OnOwnershipPermissionsFailure += OnOwnershipPermissionsFailure; + base.OnNetworkDespawn(); + } +} +``` + +### Requesting ownership in distributed authority + +When a NetworkObject is set with `OwnershipPermissions.RequestRequired` any client can request the ownership for themselves using the `RequestOwnership` method: + +```csharp +var requestStatus = NetworkObject.RequestOwnership(); +``` + +The `RequestOwnership` method 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`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_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). + +By default, any requests for ownership will automatically be approved. To control which client is approved for ownership, use the [`OnOwnershipRequested`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_OnOwnershipRequested) callback + +```csharp +/* +* When the NetworkObject's permissions includes the OwnershipPermissions.RequestRequired flag. +*/ +public class RequestableOwnershipBehaviour : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + NetworkObject.OnOwnershipRequested += OnOwnershipRequested; + NetworkObject.OnOwnershipRequestResponse += OnOwnershipRequestResponse; + base.OnNetworkSpawn(); + } + + public void TakeOwnership() + { + if (IsOwner) + { + return; + } + + var requestStatus = NetworkObject.RequestOwnership(); + if (requestStatus == NetworkObject.OwnershipRequestStatus.RequestSent) + { + // Request was sent to the owning client! + } + else + { + // Request failed to send. Use the requestStatus variable to investigate the failure to send. + } + } + + private bool OnOwnershipRequested(ulong requestingClientId) + { + // The existing owner of the object can use this callback to choose whether the request is accepted. + return true; + } + + private void OnOwnershipRequestResponse(NetworkObject.OwnershipRequestResponseStatus ownershipRequestResponseStatus) + { + if (ownershipRequestResponseStatus == NetworkObject.OwnershipRequestResponseStatus.Approved) + { + // The ownership request was approved and current client now owns this object! + } + else + { + // The ownership request either failed or was denied. Use the ownershipRequestResponseStatus variable to investigate the failure. + } + } + + public override void OnNetworkDespawn() + { + NetworkObject.OnOwnershipRequested -= OnOwnershipRequested; + NetworkObject.OnOwnershipRequestResponse -= OnOwnershipRequestResponse; + base.OnNetworkDespawn(); + } +} +``` + +## Additional resources + +* [Ownership](../../terms-concepts/ownership.md) +* [NetworkObject](./networkobject.md) +* [NetworkBehaviour](./networkbehaviour.md) +* [NetworkBehaviour ownership](./networkbehaviour-ownership.md) diff --git a/com.unity.netcode.gameobjects/Documentation~/components/core/networkobject.md b/com.unity.netcode.gameobjects/Documentation~/components/core/networkobject.md index 371a942222..56730e4c71 100644 --- a/com.unity.netcode.gameobjects/Documentation~/components/core/networkobject.md +++ b/com.unity.netcode.gameobjects/Documentation~/components/core/networkobject.md @@ -29,49 +29,6 @@ The order in which NetworkBehaviour components are presented in the **Inspector* 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 a `NetworkObject` that is [owned](../../terms-concepts/ownership.md) by a different game client than the one doing the spawning, use the following: - -```csharp -GetComponent().SpawnWithOwnership(clientId); -``` -> [!NOTE] -> The `SpawnWithOwnership` method allows a game client to spawn an object that it doesn't own. This means any owner-specific checks during the spawn sequence will not be invoked on the spawn authority side. Using `SpawnWithOwnership` can result in unexpected behavior if the spawn authority makes any additional post-spawn adjustments within the same frame. -> To avoid potential issues, it's recommended to use `Spawn` if the spawn authority needs to make any adjustments post-spawn. After adjusting, the spawn authority can immediately follow with a call to `ChangeOwnership`. - -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(); -``` -> [!NOTE] -> `RemoveOwnership` isn't supported when using a [distributed authority network topology](../../terms-concepts/distributed-authority.md). - - -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. @@ -115,8 +72,10 @@ Similar to [`NetworkObject.ActiveSceneSynchronization`](#active-scene-synchroniz > [!NOTE] > The `NetworkObject.SceneMigrationSynchronization` field is enabled by default. If your project can have many (600-1000+) spawned objects at any given time, this setting can cause performance issues. Scene migration synchronization only provides the ability to automatically synchronize the scene a NetworkObject is migrated to while it is spawned. If your NetworkObject doesn't change scenes and you have no need for automatic scene migration synchronization (_only applies when the integration scene management is enabled_), then it's recommended to disable this property to avoid additional processing overheads. - ## Additional resources +- [NetworkObject parenting](../../advanced-topics/networkobject-parenting.md) +- [NetworkObject ownership](./networkobject-ownership.md) +- [In-scene placed NetworkObjects](../../basics/scenemanagement/inscene-placed-networkobjects.md) - [NetworkBehaviour](networkbehaviour.md) - [NetworkVariable](../../basics/networkvariable.md) diff --git a/com.unity.netcode.gameobjects/Documentation~/components/helper/networktransform.md b/com.unity.netcode.gameobjects/Documentation~/components/helper/networktransform.md index b0bca748fe..f23bf9bea4 100644 --- a/com.unity.netcode.gameobjects/Documentation~/components/helper/networktransform.md +++ b/com.unity.netcode.gameobjects/Documentation~/components/helper/networktransform.md @@ -94,7 +94,7 @@ Fortunately, the authority of the NetworkTransform instance can make changes to When disabling an axis to be synchronized for performance purposes, you should always consider that NetworkTransform won't send updates as long as the axis in question doesn't have a change that exceeds its [threshold](#thresholds) value. So, taking the scale example into consideration, it can be simpler to leave those axes enabled if you only ever plan on changing them once or twice because the CPU cost for checking that change isn't as expensive as the serialization and state update sending process. The associated axis threshold values can make the biggest impact on frequency of sending state updates that, in turn, will reduce the number of state updates sent per second at the cost of losing some motion resolution. > [!NOTE] -> The __Axis to Synchronize__ properties that determine which axes are synchronized don't get synchronized with other instances. If you change ownership and there have been any adjustments to these values that are different from the network prefab's original settings, you'll need to keep those values synchronized and apply them upon the notification that ownership has changed. +> The __Axis to Synchronize__ properties that determine which axes are synchronized don't get synchronized with other instances. If you change [ownership](../../terms-concepts/ownership.md) and there have been any adjustments to these values that are different from the network prefab's original settings, you'll need to keep those values synchronized and apply them upon the notification that ownership has changed. ### Authority diff --git a/com.unity.netcode.gameobjects/Documentation~/images/diagrams/README.md b/com.unity.netcode.gameobjects/Documentation~/images/diagrams/README.md new file mode 100644 index 0000000000..2001449ae3 --- /dev/null +++ b/com.unity.netcode.gameobjects/Documentation~/images/diagrams/README.md @@ -0,0 +1,3 @@ +# Diagrams + +All diagrams in this folder are screenshots from [NGO docs diagrams](https://miro.com/app/board/uXjVG58zYCc=/). diff --git a/com.unity.netcode.gameobjects/Documentation~/images/diagrams/clientServerOwnership.png b/com.unity.netcode.gameobjects/Documentation~/images/diagrams/clientServerOwnership.png new file mode 100644 index 0000000000..15e5ae345c Binary files /dev/null and b/com.unity.netcode.gameobjects/Documentation~/images/diagrams/clientServerOwnership.png differ diff --git a/com.unity.netcode.gameobjects/Documentation~/images/diagrams/distributedAuthorityOwnership.png b/com.unity.netcode.gameobjects/Documentation~/images/diagrams/distributedAuthorityOwnership.png new file mode 100644 index 0000000000..e208fa2097 Binary files /dev/null and b/com.unity.netcode.gameobjects/Documentation~/images/diagrams/distributedAuthorityOwnership.png differ diff --git a/com.unity.netcode.gameobjects/Documentation~/images/networkobject/allowOwnerToParent.png b/com.unity.netcode.gameobjects/Documentation~/images/networkobject/allowOwnerToParent.png new file mode 100644 index 0000000000..036d279166 Binary files /dev/null and b/com.unity.netcode.gameobjects/Documentation~/images/networkobject/allowOwnerToParent.png differ diff --git a/com.unity.netcode.gameobjects/Documentation~/images/networkobject/ownershipPermissions.png b/com.unity.netcode.gameobjects/Documentation~/images/networkobject/ownershipPermissions.png new file mode 100644 index 0000000000..0f2b66b2c5 Binary files /dev/null and b/com.unity.netcode.gameobjects/Documentation~/images/networkobject/ownershipPermissions.png differ diff --git a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/authority.md b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/authority.md index 2971a25cfb..59138964a4 100644 --- a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/authority.md +++ b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/authority.md @@ -1,6 +1,6 @@ # Authority -Multiplayer games are games that are played between many different game instances. Each game instance has their own copy of the game world and behaviors within that game world. To have a shared game experience, each networked object is required to have an **authority**. +Multiplayer games are games that are played between many different game instances. Each game instance has their own copy of the game world and behaviors within that game world. To have a shared game experience, each part of the game simulation is required to have an **authority**. The authority runs the game simulation, takes actions on the game world, and synchronizes the simulation to all other connected clients. When clients who are not the authority (non-authority clients) want to interact or change the world, they must communicate with the authority and request the authority to make changes on their behalf. The authority of a networked object has the ultimate power to make definitive decisions about that object. Each object must have one and only one authority. The authority has the final control over all state and behavior of that object. @@ -12,7 +12,7 @@ Netcode for GameObjects provides two authority models: [server authority](#serve ### Server authority -The server authority model has a single game instance that is defined as the server. That game instance is responsible for running the main simulation and managing all aspects of running the networked game. Server authority is the authority model used for [client-server games](client-server.md). +The server authority model has a single game instance that is defined as the server. That game instance is responsible for running the main simulation and managing all aspects of running the networked game. Server authority is the authority model used for [client-server games](client-server.md). In a client-server game all actions that only the server can take are referred to as **server authoritative** actions. The server authority model has the strength of providing a centralized authority to manage any potential game state conflicts. This allows the implementation of systems such as game state rollback and competitive client prediction. However, this can come at the expense of adding latencies, because all state changes must be sent to the server game instance, processed, and then sent out to other game instances. diff --git a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/distributed-authority.md b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/distributed-authority.md index 74861dd7e8..ce3fba6236 100644 --- a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/distributed-authority.md +++ b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/distributed-authority.md @@ -1,4 +1,4 @@ -# Distributed authority topologies +# Distributed authority topologies The [distributed authority network topology](network-topologies.md#distributed-authority) is one possible [network topology](network-topologies.md) available within Netcode for GameObjects. Distributed authority games use the [distributed authority model](authority.md#distributed-authority). @@ -11,7 +11,7 @@ The traditional [client-server network topology](network-topologies.md#client-se 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: -* Because 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. +* Because [authority](./authority.md) 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 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. ## Session ownership @@ -20,6 +20,8 @@ When using the distributed authority topology, it's necessary to have a single d The initial session owner is the first client that joins when the session is created. If this client disconnects during the game, a new session owner is automatically selected and promoted from within the clients that are currently connected. +The session owner is the client responsible for loading and unloading scenes, and they will synchronize all existing game state to any newly joining client. Other connected clients synchronize any objects where the session owner doesn't have [visibility](../basics/object-visibility.md). + ### `IsSessionOwner` To determine if the current client is the session owner, use the `IsSessionOwner` property provided by Netcode for GameObjects. This property is available on the `NetworkManager.Singleton` instance and returns `true` if the local client is the session owner. @@ -50,10 +52,27 @@ public class MonsterAI : NetworkBehaviour You can use this property to conditionally execute logic that should only run on the session owner, such as managing global game state or handling session-wide events. +### Session owner objects + +For any game systems that should always be [owned](./ownership.md) by the session owner, you can set the object to have the `OwnershipStatus.SessionOwner` [ownership permission](../components/core/networkobject-ownership.md#ownership-permissions-settings). This will ensure the object always belongs to the current session owner. If that session owner disconnects or leaves the game, the ownership of that object will be automatically moved to the newly selected session owner. + +## Object distribution + +In a distributed authority setting, authority over the game simulation isn't bound to a single server, but distributed across clients based on setting [ownership permission settings](../components/core/networkobject-ownership.md#ownership-permissions-settings). Any object with the `OwnershipStatus.Distributable` permission set are automatically distributed amongst clients as clients connect and disconnect. + +For example, when a client starts a distributed authority session it spawns its player with `OwnershipStatus.None` so that no other client can take ownership. , Then the client spawns some objects for the game that are set with `OwnershipStatus.Distributable`. At this point, Client-A has full authority over the `OwnershipStatus.Distributable` spawned objects and its player object. + +![Distributed authority start](../images/distributed-authority-start.jpg) + +When another player joins, as in the following diagram, authority over distributable objects is split between both clients. Distributing the objects in this way reduces the 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](../images/distributed-authority-new-client.jpg) + ## Additional resources - [Distributed authority quickstart](../learn/distributed-authority-quick-start.md) -- [Understanding ownership and authority](./ownership.md) +- [Understanding authority](./authority.md) +- [Understanding ownership](./ownership.md) - [Spawning synchronization](../basics/spawning-synchronization.md) - [Deferred despawning](../basics/deferred-despawning.md) - [Distributed Authority Social Hub sample](../samples/bitesize/bitesize-socialhub.md) diff --git a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/ownership.md b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/ownership.md index d87c2eb96a..76be38a93c 100644 --- a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/ownership.md +++ b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/ownership.md @@ -1,61 +1,51 @@ # Ownership -Understand how ownership works in Netcode for GameObjects as a precursor to [authority](./authority.md). +Along with [authority](./authority.md), ownership is a core concept within Netcode for GameObjects. Ownership is a way to provide client-side reactivity while building a game. This means that the game client who owns an object can make changes to that object that are networked to all other game clients. -By default, Netcode for GameObjects assumes a [client-server topology](./client-server.md), in which the server owns all NetworkObjects (with [some exceptions](../components/core/networkobject.md#ownership)) and has ultimate authority over [spawning and despawning](../basics/object-spawning.md). +By giving individual clients ownership over actions that are important for their gameplay, clients can locally control some parts of their game. For example, this allows clients to avoid lag in their player controller, while leaving the server as the final game authority. -Netcode for GameObjects also supports building games with a [distributed authority topology](./distributed-authority.md), which provides more options for ownership and authority over NetworkObjects. +In Netcode for GameObjects, the owner of an object receives a subset of authority over that object. When a feature is being controlled by the owner, we refer to the feature as being **owner authoritative**. -## Ownership in client-server - -In a client-server topology, the server has ultimate authority over all NetworkObjects. Clients can request ownership of [specific objects](../components/core/networkobject.md#ownership), but the server has the final say in whether to grant or deny these requests. +Ownership behaves slightly differently for each [network topology](network-topologies.md). -## Ownership in distributed authority +## Ownership in client-server -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-distributed-authority-only). NetworkObjects with the distributable permission set are automatically distributed amongst clients as they connect and disconnect. +[Client-server](client-server.md) games are referred to as [server authoritative](./authority.md#server-authority). By default, the server always has authority on all aspects of the gameplay and clients must send requests to the server for the server to take actions on behalf of the client. This approach means that the client will always have some lag as they wait for actions to be taken on their behalf. -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. +Ownership allows for clients to take actions on their own, essentially loaning some authority from the server. Giving . Giving a client ownership of an object will only have effects if that feature is configured to be owner authoritative. -![Distributed authority start](../images/distributed-authority-start.jpg) +![venn diagram of client-server authority vs ownership](../images/diagrams/clientServerOwnership.png) -When another player joins, as in the following diagram, authority over distributable objects is split between both clients. Distributing the NetworkObjects in this way reduces the 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. +Here's a table showing what actions the authority vs the owner can do in a client-server game, and how to configure features to be owner authoritative: -![Distributed authority new client](../images/distributed-authority-new-client.jpg) +|Action|Authority*|Owner|Feature| +|-----|-----|-----|-----| +|Spawn/Despawn objects|**Yes**|No|| +|Synchronize late joining clients|**Yes**|No|| +|Change Ownership|**Yes**|No|| +|Move transform|By default|Configurable|[Owner authoritative `NetworkTransform`](../components/helper/networktransform.md)| +|Update object parenting|By default|Configurable|[`NetworkObject.AllowOwnerToParent`](../advanced-topics/networkobject-parenting.md#who-can-parent-networkobjects)| +|Update NetworkVariables|By default|Configurable|[`NetworkVariableWritePermission.Owner`](../basics/networkvariable.md#write-permissions)| -### Ownership permission settings (distributed authority only) +*The authority when using client-server will always be the server. -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), are only relevant when using a distributed authority network topology: +## Ownership in distributed authority -| **Ownership setting** | **Description** | -|-------------------|-------------| -| `None` | Ownership of this NetworkObject can't be redistributed, requested, or transferred (a Player might 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 isn't 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. | -| `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. | +In [distributed authority](./distributed-authority.md) the owner of an object is always the authority of that object. In this way, ownership comes before authority. Authority can be transferred between clients via changing and requesting ownership. -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. +![diagram showing ownership precedes authority](../images/diagrams/distributedAuthorityOwnership.png) -> [!NOTE] -> The ownership permissions are only visible when you have the Multiplayer Services SDK package installed and you're inspecting a NetworkObject within the Editor. Ownership permissions have no impact when using a client-server network topology, because the server always has authority. +When building your game you can use [ownership permissions](../advanced-topics/networkobject-ownership.md#ownership-permissions-settings) to control how and when ownership of objects can be transferred between clients. -#### Request ownership +Objects with the `OwnershipStatus.Distributable` permission will have their ownership automatically distributed between all connected game clients whenever a new client joins or an existing client leaves. This is the key mechanism in how the game simulation is distributed between clients in a distributed authority session. -When requesting ownership of a NetworkObject using [`NetworkObject.RequestOwnership`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.RequestOwnership.html), the following outcomes are possible depending on the ownership status of the NetworkObject when the request is received. +## Checking for ownership -| **Ownership status of NetworkObject** | **Response** | **Description** | -|--------------------------|--------------|---------------------| -| `OwnershipStatus.Transferable` | `OwnershipRequestStatus.RequestSent` | Ownership is transferred immediately, as long as a request isn't already in progress and the NetworkObject's ownership isn't locked. Ownership isn't locked after the transfer. | -| `OwnershipStatus.RequestRequired` | `OwnershipRequestStatus.RequestSent` | Request granted, as long as a request isn't already in progress and the NetworkObject's ownership isn't locked. | -| `OwnershipStatus.RequestRequired` but `IsOwner` is `true`for the requesting client | `OwnershipRequestStatus.AlreadyOwner` | No action taken. The current client is already the owner. | -| `OwnershipStatus.RequestRequired` but `IsOwnershipLocked` is `true` | `OwnershipRequestStatus.Locked` | Request denied. The current owner has locked ownership which means requests can't be made at this time. | -| `OwnershipStatus.RequestRequired` but `IsRequestInProgress` is `true` | `OwnershipRequestStatus.RequestInProgress` | Request denied. A known request is already in progress. You can scan for ownership changes and try again after a specific period of time or no longer attempt to request ownership. | -| `OwnershipStatus.SessionOwner` | `OwnershipRequestStatus.SessionOwnerOnly` | Request denied. Only the session owner can have ownership of this NetworkObject. | -| `OwnershipStatus.Distributable` | `OwnershipRequestStatus.RequestRequiredNotSet` | Request denied. Distributable NetworkObjects can only have their ownership changed as part of distribution when clients join or leave a session. | -| `OwnershipStatus.None` | `OwnershipRequestStatus.RequestRequiredNotSet` | Request denied. Ownership of this NetworkObject can't be redistributed, requested, or transferred. | +The `IsOwner` 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 `IsOwner` whenever you're synchronizing transform movements, regardless of whether you're using a distributed authority or client-server topology. ## Additional resources * [Authority](authority.md) * [Client-server](client-server.md) * [Distributed authority](distributed-authority.md) +* [Controlling NetworkObject ownership](../advanced-topics/networkobject-ownership.md)