Ownership ======================================= Overview -------- In this networking system, **ownership** determines which machine (client or server) is responsible for controlling a networked object. Only the owning machine is allowed to send authoritative updates for that object (such as position, state changes, or RPC calls tied to it). All other machines treat the object as read-only replicas. Ownership works hand-in-hand with **network object IDs** to ensure every object in the game is uniquely identified and has exactly one authoritative controller. Network Object IDs ------------------ Every networked object has a **network ID** (an integer) assigned by the server. This ID is globally unique for the lifetime of the object and is used to: - Map RPCs and sync messages to the correct GameObject. - Identify ownership. - Allow the server and clients to look up objects in their local maps. Clients do not invent IDs themselves. Instead: 1. The server maintains a counter of available IDs. 2. When a client connects, the server grants that client a **pool of IDs**. 3. When the client instantiates new objects, it consumes IDs from this pool. 4. The server keeps track of which IDs belong to which client. Default Ownership ----------------- By default: - If the **server instantiates** an object, the server owns it. - If a **client instantiates** an object using ``ClientNetwork.Instantiate``, the client owns it. Ownership implies the right to: - Send sync updates for the object (position, rotation, custom state). - Destroy the object. - Call RPCs on the object that affect other clients. Transferring Ownership ---------------------- Ownership can change during runtime. This usually happens when: - A client disconnects (their objects must be reassigned or destroyed). - An object changes area and needs a new local owner. - Game logic explicitly chooses to give control to another client. Mechanics: - **Server → Client**: The server sends an ``OwnershipGained`` message to the new client, and an ``OwnershipLost`` message to the old client. - **Client**: Updates its local list of owned IDs. The object’s GameObject receives a ``OnGainOwnership`` or ``OnLoseOwnership`` message. Example: reassigning ownership on the server: .. code-block:: csharp // Example: Give ownership of an object to another client long newOwnerId = 123456789L; int objectId = 42; // Server tells new client it now owns the object NetOutgoingMessage msg = server.CreateMessage(); msg.Write((int)MessageType.OwnershipGained); msg.Write(objectId); server.SendMessage(msg, GetClientData(newOwnerId).connection, NetDeliveryMethod.ReliableOrdered); // Server tells old client it has lost ownership NetOutgoingMessage msg2 = server.CreateMessage(); msg2.Write((int)MessageType.OwnershipLost); msg2.Write(objectId); server.SendMessage(msg2, oldClient.connection, NetDeliveryMethod.ReliableOrdered); // Update server-side bookkeeping oldClient.ownedObjects.Remove(objectId); GetClientData(newOwnerId).ownedObjects.Add(objectId); Server Ownership ---------------- Yes, the **server can own objects**. This is common for: - World objects that are always authoritative (NPCs, doors, map triggers). - Scene objects that exist regardless of which clients are present. - Spawns controlled by game logic instead of a player. When the server owns an object: - Only the server sends updates for it. - Clients cannot override its state. - The server may choose to transfer ownership later. Object Lifecycle and Ownership ------------------------------ .. code-block:: Instantiate object | v Assigned network ID | v Default owner set | v Ownership may transfer | v Owner disconnects? ---- Yes ---> Transfer or Destroy | No | v Object destroyed -> ID removed from system Best Practices -------------- - **Keep authority clear**: Only the owning machine should drive gameplay logic for the object. - **Expect ownership changes**: Always handle ``OnGainOwnership`` and ``OnLoseOwnership`` in your scripts. - **Don’t assume permanent ownership**: Players may disconnect, and the server will reassign their objects. - **Server is final authority**: Even if a client owns an object, the server enforces consistency. Unity Callbacks --------------- When ownership changes, the networking system calls Unity messages on the GameObject: - ``OnGainOwnership()`` – Called when this machine becomes the new owner. - ``OnLoseOwnership()`` – Called when this machine loses ownership. Example: .. code-block:: csharp public class PlayerController : MonoBehaviour { bool hasControl = false; void OnGainOwnership() { hasControl = true; Debug.Log("I now own this object!"); } void OnLoseOwnership() { hasControl = false; Debug.Log("I lost ownership."); } } Summary ------- - Every object has a **unique network ID** assigned by the server. - Ownership determines which machine controls the object’s state. - Default owner is whoever instantiates the object. - Ownership can transfer due to disconnection, area changes, or game logic. - The server can also own objects directly. - Ownership changes trigger Unity callbacks for easy integration.