diff --git a/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md b/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md index 3b683f8770..cac3597c62 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,6 +23,7 @@ * [Network components](network-components.md) * [Core components](components/core/corecomponents.md) * [NetworkObject](components/core/networkobject.md) + * [NetworkObject ownership](advanced-topics/networkobject-ownership.md) * [NetworkObject parenting](advanced-topics/networkobject-parenting.md) * [NetworkBehaviour](components/core/networkbehaviour.md) * [Synchronizing & Order of Operations](components/core/networkbehaviour-synchronize.md) diff --git a/com.unity.netcode.gameobjects/Documentation~/advanced-topics/networkobject-ownership.md b/com.unity.netcode.gameobjects/Documentation~/advanced-topics/networkobject-ownership.md new file mode 100644 index 0000000000..26b1d3079d --- /dev/null +++ b/com.unity.netcode.gameobjects/Documentation~/advanced-topics/networkobject-ownership.md @@ -0,0 +1,164 @@ +# NetworkObject ownership + +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). + +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. + +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. + +> [!NOTE] +> 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. + +## Authority ownership + +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. + +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. + +```csharp +GetComponent().Spawn(); +``` + +To change ownership, the authority uses the `ChangeOwnership` method: + +```csharp +GetComponent().ChangeOwnership(clientId); +``` + +## Client-server ownership + +In a client-server game, 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). + +## 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 can always change 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** | +|-------------------|-------------| +| `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` | Any client can change ownership of this NetworkObject at any time, as long as ownership is not locked or a request is pending. | +| `RequestRequired` | Ownership of this NetworkObject must be requested before ownership can be changed. | +| `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. | + +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. + +```csharp +// To lock an object from any ownership changes +GetComponent().SetOwnershipLock(true); + +// To unlock an object so that the underlying ownership permissions apply again +GetComponent().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 +GetComponent().ChangeOwnership(clientId); + +// To change ownership to self +GetComponent().ChangeOwnership(NetworkManager.Singleton.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 +internal class MyTransferrableBehaviour : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + NetworkObject.OnOwnershipPermissionsFailure = OnOwnershipPermissionsFailure; + base.OnNetworkSpawn(); + } + + private void OnOwnershipPermissionsFailure(NetworkObject.OwnershipPermissionsFailureStatus ownershipPermissionsFailureStatus) + { + // Called on the calling client when NetworkObject.ChangeOwnership() has failed + } + + public override void OnNetworkDespawn() + { + NetworkObject.OnOwnershipPermissionsFailure = null; + 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 = GetComponent().RequestOwnership(); +``` + +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). + +```csharp +internal class MyRequestableBehaviour : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + NetworkObject.OnOwnershipRequestResponse = OnOwnershipRequestResponse; + base.OnNetworkSpawn(); + } + + private void OnOwnershipRequestResponse(NetworkObject.OwnershipRequestResponseStatus ownershipRequestResponseStatus) + { + // Called when the requesting client has gotten a response to their request + } + + public override void OnNetworkDespawn() + { + NetworkObject.OnOwnershipRequestResponse = null; + base.OnNetworkDespawn(); + } +} +``` + +## Spawn with ownership + +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] +> 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 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. + +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`. + +```csharp +[Rpc(SendTo.Authority)] +void SpawnForRequestingPlayer(RpcParams rpcParams = default) { + var instance = Instantiate(myprefab).GetComponent(); + instance.Spawn(); + instance.transform.position = transform.position; + instance.GetComponent.MyNetworkVar.Value = initialValue; + instance.ChangeOwnership(rpcParams.Receive.SenderClientId) +} +``` + +This flow allows the spawning client to completely spawn and finish initializing the object locally before transferring the ownership to another game client. 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..995813983d 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. @@ -38,12 +38,16 @@ virtual void OnNetworkObjectParentChanged(NetworkObject parentNetworkObject) { } > [!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 -Similar to [Ownership](../basics/networkobject#ownership), only the server (or host) can control NetworkObject component parenting. +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. + +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. + +![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..edf97bdfec 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](../advanced-topics/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/networkobject.md b/com.unity.netcode.gameobjects/Documentation~/components/core/networkobject.md index 371a942222..ed47709bbd 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](../../advanced-topics/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~/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~/terms-concepts/distributed-authority.md b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/distributed-authority.md index 74861dd7e8..2ac9502a3b 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](../advanced-topics/networkobject-ownership.md). 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 NetworkObjects isn't bound to a single server, but distributed across clients depending on a NetworkObject's [ownership permission settings](../advanced-topics/networkobject-ownership.md#ownership-permissions-settings). NetworkObjects 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 NetworkObjects 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 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. + +![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..827ab4a78f 100644 --- a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/ownership.md +++ b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/ownership.md @@ -1,61 +1,44 @@ # Ownership -Understand how ownership works in Netcode for GameObjects as a precursor to [authority](./authority.md). - -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). - -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. +Along with [authority](./authority.md), Ownership is a core concept within Netcode for GameObjects. Ownership behaves slightly differently for each [network topology](network-topologies.md). ## 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 in distributed authority +In [client-server](client-server.md), ownership behaves as a subset of [authority](./authority.md). The owner of an object can control some aspects of that object, while the authority controls and synchronizes others. -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. +Ownership provides client-side reactivity. By giving individual clients ownership over objects 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. -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. +Here's a table showing what actions the authority vs the owner can do in a client-server game. -![Distributed authority start](../images/distributed-authority-start.jpg) +|Action |Authority*|Owner | +|--------------------------------|----------|-------| +|Spawn/Despawn objects |**Yes** |No | +|Change Ownership |**Yes** |No | +|Move transform |No |**Yes**| +|Update NetworkVariables** |**Yes** |No | +|Synchronize late joining clients|**Yes** |No | +|Update object parenting*** |**Yes** |No | -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. +*The authority when using client-server will always be the server. -![Distributed authority new client](../images/distributed-authority-new-client.jpg) +**This default behaviour can be changed using the [NetworkVariableWritePermission.Owner](../basics/networkvariable.md#write-permissions) +***This default behaviour can be changed by setting [NetworkObject.AllowOwnerToParent](../advanced-topics/networkobject-parenting.md#who-can-parent-networkobjects) -### Ownership permission settings (distributed authority only) - -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 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. | +## Ownership in distributed authority -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. +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. -> [!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)