diff --git a/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md b/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md index a3c0dda213..da133d6c43 100644 --- a/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md +++ b/com.unity.netcode.gameobjects/Documentation~/TableOfContents.md @@ -7,6 +7,7 @@ * [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) @@ -33,9 +34,6 @@ * [NetworkAnimator](components/helper/networkanimator.md) * [NetworkTransform](components/helper/networktransform.md) * [Physics](advanced-topics/physics.md) -* [Ownership and authority](ownership-authority.md) - * [Understanding ownership and authority](basics/ownership.md) - * [Ownership race conditions](basics/race-conditions.md) * [Spawning and despawning](spawn-despawn.md) * [Object spawning](basics/object-spawning.md) * [Network prefab handler](advanced-topics/network-prefab-handler.md) diff --git a/com.unity.netcode.gameobjects/Documentation~/basics/ownership.md b/com.unity.netcode.gameobjects/Documentation~/basics/ownership.md deleted file mode 100644 index bcfeb5e280..0000000000 --- a/com.unity.netcode.gameobjects/Documentation~/basics/ownership.md +++ /dev/null @@ -1,94 +0,0 @@ -# Understanding ownership and authority - -By default, Netcode for GameObjects assumes a [client-server topology](../terms-concepts/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](object-spawning.md). - -Netcode for GameObjects also supports building games with a [distributed authority topology](../terms-concepts/distributed-authority.md), which provides more options for ownership and authority over NetworkObjects. - -## Ownership and distributed authority - -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. - -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. - -![Distributed authority start](../images/distributed-authority-start.jpg) - -When another player joins, as in the diagram below, authority over distributable objects is split between both clients. Distributing the NetworkObjects in this way reduces the overall 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) - -### Ownership permission settings (distributed authority only) - -The following ownership permission settings, defined by `NetworkObject.OwnershipStatus`, only take effect when using a distributed authority network topology: - -* `None`: Ownership of this NetworkObject is considered static and can't be redistributed, requested, or transferred (a Player would 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 is not 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](../terms-concepts/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. - -> [!NOTE] -> The ownership permissions are only visible when the Multiplayer Services SDK package is installed and you're inspecting a NetworkObject within the editor. Ownership permissions have no impact when using a client-server network topology, since the server always has authority. For ownership permissions to be used, you must be using a distributed authority network topology. - -## Checking for authority - -### `HasAuthority` - -The `HasAuthority` 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 `HasAuthority` whenever you're working with individual objects, regardless of whether you're using a distributed authority or client-server topology. - -``` -public class MonsterAI : NetworkBehaviour -{ - public override void OnNetworkSpawn() - { - if (!HasAuthority) - { - return; - } - // Authority monster init script here - base.OnNetworkSpawn(); - } - - private void Update() - { - if (!IsSpawned || !HasAuthority) - { - return; - } - // Authority updates monster AI here - } -} -``` - -Using distributed authority with Netcode for GameObjects requires a shift in the understanding of authority: instead of authority belonging to the server in all cases, it belongs to whichever client instance currently has authority. This necessitates a shift away from using local, non-replicated properties to store pertinent states; instead, [NetworkVariables](networkvariable.md) should be used to keep states synchronized and saved when all clients disconnect from a session or ownership is transferred to another client. - -Distributed authority supports all built-in NetworkVariable data types. Since there's no concept of an authoritative server in a distributed authority session, all NetworkVariables are automatically configured with owner write and everyone read permissions. - -### `IsServer` - -`IsServer` or `!IsServer` is the traditional client-server method of checking whether the current context has authority, and is only available in client-server topologies (because distributed authority games have no single authoritative server). You can use a mix of `HasAuthority` and `IsServer` when building a client-server game: `HasAuthority` is recommended when performing object-specific operations, while `IsServer` can be useful to check for authority when performing global actions. - -``` -public class MonsterAI : NetworkBehaviour -{ - public override void OnNetworkSpawn() - { - if (!IsServer) - { - return; - } - // Server-side monster init script here - base.OnNetworkSpawn(); - } - - private void Update() - { - if (!IsSpawned || !IsServer) - { - return; - } - // Server-side updates monster AI here - } -} -``` diff --git a/com.unity.netcode.gameobjects/Documentation~/basics/race-conditions.md b/com.unity.netcode.gameobjects/Documentation~/basics/race-conditions.md deleted file mode 100644 index ba0cabd27b..0000000000 --- a/com.unity.netcode.gameobjects/Documentation~/basics/race-conditions.md +++ /dev/null @@ -1,34 +0,0 @@ -# Ownership race conditions - -> [!NOTE] -> The race conditions described on this page only affect games using a [distributed authority topology](../terms-concepts/distributed-authority.md). - -Ownership race conditions can occur when two players (clients) want to take ownership of the same NetworkObject at the same time. The following diagram illustrates a typical race condition where two clients (A and B) want to take ownership of an object (the star owned by Client-C) simultaneously. - -![Race condition](../images/race-condition.jpg) - -## Potential race conditions - -When two clients attempt to take ownership of the same NetworkObject at the same time, the outcome can vary depending on the `OwnershipStatus` of the NetworkObject. - -* `OwnershipStatus.None`: If ownership status isn't transferable, but Client-A and Client-B attempt to request ownership anyway, they’ll both receive a local ownership notification, via `NetworkObject.OnOwnershipPermissionsFailure`, with a status of `OwnershipPermissionsFailureStatus.NotTransferable`. This only occurs if the user script of both clients don't check the NetworkObject ownership permissions first. -* `OwnershipStatus.Distributable`: If this is the only ownership flag on the NetworkObject, then the end result for both clients is the same as `OwnershipStatus.None` above. -* `OwnershipStatus.RequestRequired`: If ownership transfer requires a request, then there are a few potential outcomes: - * If both clients attempt to locally change the ownership of the NetworkObject without first making a request, they'll both receive a local ownership notification, via `NetworkObject.OnOwnershipPermissionsFailure`, that they must request ownership (`OwnershipPermissionsFailureStatus.RequestRequired`). - * If both clients send a request for ownership to the authoritative client, then it can be treated as a 'first come first serve' request (this is the default response of an authoritative client) or, if the user script assigns a callback handler to the `NetworkObject.OnOwnershipRequested`, it will be up to the user script as to whether Client-A or Client-B is granted ownership. This is still handled in a 'first come first serve' fashion, but does provide an additional level of control over granting ownership upon request. -* `OwnershipStatus.Transferable`: If ownership is transferable and requests are not required, then ownership can be acquired by both clients simultaneously if the action or user script performed happens at the same time and occurs within a period of time less than the average RTT of both clients. This is where a true race condition can occur, and the end result can be ownership getting out of sync across clients. See the diagram below. - -![True race condition](../images/true-race-condition.jpg) - -## Preventing race conditions - -There are broadly three ways to help prevent these types of race conditions. - -* **Require ownership requests**: You can use the `RequestRequired` permission flag to ensure that any changes in ownership require a request first. This prevents race conditions, but requires two RTTs to complete the transfer of ownership, and can be too slow in situations where acquisition of ownership is time sensitive. -* **Use the distributed authority service**: The distributed authority service provides a certain level of governance over ownership transfer during a change in ownership of a NetworkObject with just the `Transferable` flag set. -* **Lock ownership**: When changing ownership, the user script can lock ownership for any period of time using `NetworkObject.SetOwnershipLock`. If this operation is performed immediately after changing ownership, then both the change in ownership and the updated ownership permissions are sent in the same message batch at the end of the frame. This helps the distributed authority service to govern and prevent race conditions more effectively, while also preventing immediate turnover of ownership to another client shortly after (within a few network ticks period of time) changing ownership locally. - -How you choose to prevent race conditions depends on how quickly you need to transfer ownership from one client to another, and how much contingency you intend to implement. - -* `OwnershipStatus.RequestRequired`: Is not prone to race conditions, but can take two RTTs (one RTT for the requestor and one RTT for the grantor/authority). If immediate ownership transfer is not required (that is, acquiring ownership in the same frame), then this is the recommended permissions setting to use. -* `OwnershipStatus.Transferable`: If not used in conjunction with ownership locking, can be prone to potential race-like conditions. Moreover, ownership could be transferred, locally, to a client for a full RTT period before receiving a change in ownership message that gives ownership to a client that had changed ownership slightly earlier. While this type of scenario can be managed, it’s worth noting that while immediate (i.e. `Transferable`) ownership transfer permissions provide a much faster transfer in ownership, it should be used with caution and a denial of ownership contingency script could be needed to handle such scenarios. diff --git a/com.unity.netcode.gameobjects/Documentation~/networking-concepts.md b/com.unity.netcode.gameobjects/Documentation~/networking-concepts.md index f39ffa870c..b416a58893 100644 --- a/com.unity.netcode.gameobjects/Documentation~/networking-concepts.md +++ b/com.unity.netcode.gameobjects/Documentation~/networking-concepts.md @@ -5,4 +5,5 @@ Understand the networking concepts that underpin Netcode for GameObjects. | **Topic** | **Description** | | :------------------------------ | :------------------------------- | | **[Authority](terms-concepts/authority.md)** | 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**. | +| **[Ownership](terms-concepts/ownership.md)** | Understand how ownership works in Netcode for GameObjects as a precursor to [authority](terms-concepts/authority.md). | | **[Network topologies](network-topologies.md)** | Understand and decide which network topology to use in your project. | \ No newline at end of file diff --git a/com.unity.netcode.gameobjects/Documentation~/ownership-authority.md b/com.unity.netcode.gameobjects/Documentation~/ownership-authority.md deleted file mode 100644 index 49f661088c..0000000000 --- a/com.unity.netcode.gameobjects/Documentation~/ownership-authority.md +++ /dev/null @@ -1,8 +0,0 @@ -# Ownership and authority - -Understand ownership and authority in Netcode for GameObjects. - -| **Topic** | **Description** | -| :------------------------------ | :------------------------------- | -| **[Understanding ownership and authority](basics/ownership.md)** | Understand the ownership and authority options that Netcode for GameObjects supports. | -| **[Ownership race conditions](basics/race-conditions.md)** | Ownership race conditions can occur when two players (clients) want to take ownership of the same NetworkObject at the same time. | \ No newline at end of file diff --git a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/authority.md b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/authority.md index 2b7f027931..2971a25cfb 100644 --- a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/authority.md +++ b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/authority.md @@ -14,7 +14,7 @@ Netcode for GameObjects provides two authority models: [server authority](#serve 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 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 cost of adding latencies, because all state changes must be sent to the server game instance, processed, and then sent out to other game instances. +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. Server authority games can also be resource intensive. The server runs the simulation for the entire game world, and so the server needs to be powerful enough to handle the simulation and networking of all connected game clients. This resource requirement can become expensive. @@ -22,10 +22,44 @@ Server authority is primarily used by performance-sensitive games, such as first ### Distributed authority -The distributed authority model shares authority between game instances. Each game instance is the authority for a subdivision of the networked objects in the game and is responsible for running the simulation for their subdivision of objects. Updates are shared from other game instances for the rest of the simulation. +The [distributed authority model](distributed-authority.md) shares authority between game instances. Each game instance is the authority for a subdivision of the networked objects in the game and is responsible for running the simulation for their subdivision of objects. Updates are shared from other game instances for the rest of the simulation. -The authority of each networked object is responsible for simulating the behavior and managing any aspects of running the networked game that relate to the objects it is the authority of. +The authority of each networked object is responsible for simulating the behavior and managing any aspects of running the networked game that relate to the objects it's the authority of. -Because distributed authority games share the simulation between each connected client, they are less resource intensive. Each machine connected to the game processes a subdivision of the simulation, so no single machine needs to have the capacity to process the entire simulation. This results in a multiplayer game experience that can run on cheaper machines and is less resource intensive. +Because distributed authority games share the simulation between each connected client, they're less resource intensive. Each machine connected to the game processes a subdivision of the simulation, so no single machine needs to have the capacity to process the entire simulation. This results in a multiplayer game experience that can run on cheaper machines and is less resource intensive. -The distributed authority model is the authority model used for [distributed authority games](distributed-authority.md). +## Checking for authority + +The `HasAuthority` 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 `HasAuthority` whenever you're working with individual objects, regardless of whether you're using a distributed authority or client-server topology. + +```csharp +public class MonsterAI : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + if (!HasAuthority) + { + return; + } + // Authority monster init script here + base.OnNetworkSpawn(); + } + + private void Update() + { + if (!IsSpawned || !HasAuthority) + { + return; + } + // Authority updates monster AI here + } +} +``` + +Using distributed authority with Netcode for GameObjects requires a shift in the understanding of authority: instead of authority belonging to the server in all cases, it belongs to whichever client instance currently has authority. This necessitates a shift away from using local, non-replicated properties to store pertinent states; instead, [NetworkVariables](../basics/networkvariable.md) should be used to keep states synchronized and saved when all clients disconnect from a session or ownership is transferred to another client. + +Distributed authority supports all built-in NetworkVariable data types. Because there's no concept of an authoritative server in a distributed authority session, all NetworkVariables are automatically configured with owner write and everyone read permissions. + +## Additional resources + +- [Ownership](ownership.md) diff --git a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/client-server.md b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/client-server.md index 76490a4181..4d3efa15c1 100644 --- a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/client-server.md +++ b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/client-server.md @@ -4,12 +4,116 @@ Client-server is one possible [network topology](network-topologies.md) you can ## Defining client-server -In a client-server topology, a central server is responsible for running the main simulation and managing all aspects of running the networked game, including simulating physics, spawning and despawning objects, and authorizing client requests. Players connect to the server using separate client programs to see and interact with the game. +A client-server topology consists of two distinct types of game instances: a single server game instance, and one or more client game instances. The server always has [authority](authority.md) and runs the main simulation of the game, including simulating physics, spawning and despawning objects, and authorizing client requests. Client game instances can then connect to the server to interact with and respond to the server's game simulation. -Client-server encompasses a number of potential network arrangements. The most common is a dedicated game server, in which a specialized server manages the game and exists solely for that purpose. An alternative client-server arrangement is to have a [listen server](../learn/listenserverhostarchitecture.md), in which the game server runs on the same machine as a client. +Client-server encompasses multiple potential network arrangements. The most common is a dedicated game server, in which a specialized server manages the game and exists solely for that purpose. + +An alternative client-server arrangement is a [listen server](../learn/listenserverhostarchitecture.md), in which the game server runs on the same machine as a client. In this arrangement, the server game instance is referred to as a host. A host game instance runs as both a server and a client simultaneously. + +## Checking for game instance type + +### `IsServer` + +`IsServer` or `!IsServer` is the traditional client-server method of checking whether the current game instance is running as a server instance. This is useful for ensuring that the server instance is the only instance running authoritative game logic, such as spawning objects, processing game rules, and validating client actions. + +Use `IsServer` to ensure that only the server executes authoritative or global code. For example, spawning enemies, handling core game logic, or updating shared state should only happen on the server. This prevents clients from making unauthorized changes and helps maintain a consistent game state across all connected players. + +```csharp +public class MonsterAI : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + if (!IsServer) + { + return; + } + // Server-side monster init script here + base.OnNetworkSpawn(); + } + + private void Update() + { + if (!IsSpawned || !IsServer) + { + return; + } + // Server-side updates monster AI here + } +} +``` + +### `IsHost` + +Use the `IsHost` property to determine if the current game instance is running as both a server and a client simultaneously, a configuration known as a host. In Netcode for GameObjects, this is common when using a [listen server](../learn/listenserverhostarchitecture.md), where the server and one client share the same process. + +`IsHost` can be useful for branching resource heavy logic so that a game running as a listen-server can use code-paths optimized for running on end devices. + +```csharp +public class MonsterAI : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + if (!IsServer) + { + return; + } + // Server-side monster init script here + base.OnNetworkSpawn(); + } + + private void Update() + { + if (!IsSpawned || !IsServer) + { + return; + } + if (IsHost) + { + // Monster AI that is optimized for user devices using a listen-server here. + return + } + + // Monster AI that is optimized for the dedicated game server here. + } +} +``` + +### `IsClient` + +Use the `IsClient` property to check if the current game instance is running as a client. This is helpful for executing logic that should only run on client machines, such as updating UI elements, handling local input, or playing client-specific effects. Use `IsClient` to ensure that code only runs on the client side, preventing unintended execution on the server or in non-client contexts. + +`IsClient` will be `true` for host instances as a host game instance is running as both a server and a client simultaneously. + +```csharp +public class MonsterAI : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + if (IsClient) + { + // Play client side effects here + + if (!IsHost) + { + // exit early if the game instance is only a client + return; + } + } + + // Server-side monster init script here + base.OnNetworkSpawn(); + } +} +``` ## Use cases for client-server Dedicated servers are often the most expensive network topology, but also offer the highest performance and can provide additional functionality such as competitive client prediction, rollback, and a centralized authority to manage any potential client conflicts. However, this comes at the cost of added latencies when communicating state changes from one client to another, as all state changes must be sent from client to server, processed, and then sent back out to other clients. Client-server is primarily used by performance-sensitive games, such as first-person shooters, or competitive games where having a central server authority is necessary to minimize cheating and the effects of bad actors. + +## Additional resources + +- [Network topologies](network-topologies.md) +- [Distributed authority](distributed-authority.md) +- [Listen server architecture](../learn/listenserverhostarchitecture.md) \ No newline at end of file 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 b45bf99822..74861dd7e8 100644 --- a/com.unity.netcode.gameobjects/Documentation~/terms-concepts/distributed-authority.md +++ b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/distributed-authority.md @@ -1,20 +1,18 @@ # Distributed authority topologies -## Distributed authority networks - 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). The traditional [client-server network topology](network-topologies.md#client-server) has a dedicated game instance running the game simulation. This means all state changes must be communicated to the server and then the server communicates those updates to all other connected clients. This design works well when using a powerful dedicated game server, however significant latencies are added when communicating state changes with a [listen server architecture](../learn/listenserverhostarchitecture.md). > [!NOTE] -> The distributed authority service provided by the [Multiplayer Services package](https://docs.unity.com/ugs/en-us/manual/mps-sdk/manual) offers a free tier for bandwidth and connectivity hours, allowing you to develop and test without immediate cost. Refer to the [Unity Gaming Services pricing page](https://unity.com/products/gaming-services/pricing) for complete details. +> The distributed authority service provided by the [Multiplayer Services package](https://docs.unity.com/ugs/en-us/manual/mps-sdk/manual) has a free tier for bandwidth and connectivity hours, allowing you to develop and test without immediate cost. Refer to the [Unity Gaming Services pricing page](https://unity.com/products/gaming-services/pricing) for complete details. ## Considerations 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: -* Since 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. -* Depending on the platform and overall 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. +* 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. +* 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 @@ -22,13 +20,40 @@ 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. -## More information about distributed authority - -For more information about how distributed authority works in Netcode for GameObjects, see the following pages in the documentation: +### `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. + +```csharp +public class MonsterAI : NetworkBehaviour +{ + public override void OnNetworkSpawn() + { + if (!IsSessionOwner) + { + return; + } + // Global monster init behaviour here + base.OnNetworkSpawn(); + } + + private void Update() + { + if (!IsSpawned || !IsSessionOwner) + { + return; + } + // Global monster AI updates here + } +} +``` + +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. + +## Additional resources - [Distributed authority quickstart](../learn/distributed-authority-quick-start.md) -- [Understanding ownership and authority](../basics/ownership.md) -- [Race conditions](../basics/race-conditions.md) +- [Understanding ownership and authority](./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 new file mode 100644 index 0000000000..36ebc7c883 --- /dev/null +++ b/com.unity.netcode.gameobjects/Documentation~/terms-concepts/ownership.md @@ -0,0 +1,61 @@ +# 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. + +## 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 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. + +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. + +![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) + +### 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. | + +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. + +> [!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. + +#### Request ownership + +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. + +| **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. Ownership is locked after the request is granted. | +| `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. | + +## Additional resources + +* [Authority](authority.md) +* [Client-server](client-server.md) +* [Distributed authority](distributed-authority.md) \ No newline at end of file