Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/facepunch/sbox-public/llms.txt

Use this file to discover all available pages before exploring further.

s&box multiplayer is built around a host/client model backed by NetworkObject. This page explains how that model works, how objects get networked, who controls what, and how you configure ownership behavior on your GameObject.

How the host/client model works

Every s&box session has exactly one host. The host is authoritative: it owns the scene, spawns objects, and resolves conflicts. All other participants are clients that receive state from the host. You can check which role you are running as at any time:
if ( Networking.IsHost )
{
    // Running as the host
}

if ( Networking.IsClient )
{
    // Connected to a server, not the host
}
Networking.IsHost returns true even when there is no active multiplayer session — a standalone local game is always its own host. Networking.IsActive returns true only when a real networked session exists.
The host processes all incoming client RPCs, owns unowned objects, and is the only party that can assign ownership to other connections.

NetworkObject and the three network modes

Every GameObject has a Network accessor that controls how it participates in multiplayer. The NetworkMode enum determines whether and how the object is synchronized:
ModeDescription
NetworkMode.NeverThe object is never networked. Only exists locally.
NetworkMode.ObjectNetworked as an independent object with an owner. Supports [Sync] properties and RPCs.
NetworkMode.SnapshotNetworked as part of the scene snapshot. The host controls all state.
Most game objects that players interact with use NetworkMode.Object. Use NetworkMode.Snapshot for scene-level state that only the host should write.

Ownership

Every NetworkObject in Object mode has an owner — the Connection that is allowed to write synchronized state and drive the object’s transform. When there is no owner, the host automatically acts as one. The ownership model exposes three properties you can read from any component:
// True if the local client owns this object
bool isMine = GameObject.Network.IsOwner;

// True if no connection owns this object (host controls it)
bool isUnowned = GameObject.Network.IsUnowned;

// True if another client owns this object (we receive state, don't write it)
bool isProxy = GameObject.Network.IsProxy;
Use IsProxy to skip local simulation for objects you do not own:
protected override void OnFixedUpdate()
{
    if ( GameObject.Network.IsProxy )
        return; // let the owner drive this object

    // apply local input here
}

Spawning a networked object

To spawn a GameObject on the network, call GameObject.NetworkSpawn() from the host, passing the Connection that should own it:
// Spawn a prefab and give ownership to the connecting player
var go = prefab.Clone();
go.NetworkSpawn( connection );
When NetworkSpawn is called, the engine sends a create message to all clients. Each client reconstructs the object from serialized JSON, applies the initial transform and synced properties, then calls OnNetworkSpawn on any component that implements Component.INetworkSpawn.
While the object is spawning, IsProxy is forced to false on the host so that OnAwake and OnEnabled run as if the host is the owner — even when it is spawning on behalf of another client.

Owner transfer

OwnerTransfer controls who is allowed to change ownership at runtime:
ValueBehaviour
OwnerTransfer.TakeoverAny client can claim ownership at any time.
OwnerTransfer.FixedOnly the host can change the owner.
OwnerTransfer.RequestClients send a request to the host, who approves it.
Set the transfer mode in the editor or in code:
GameObject.Network.SetOwnerTransfer( OwnerTransfer.Fixed );

What happens when an owner disconnects

When the owning client disconnects, the NetworkOrphaned setting on the object determines what happens next:
ValueBehaviour
NetworkOrphaned.DestroyThe object is destroyed for everyone. (default)
NetworkOrphaned.HostThe host takes over as the new owner.
NetworkOrphaned.RandomThe host randomly picks a connected client as the new owner.
NetworkOrphaned.ClearOwnerOwnership is cleared — the object becomes unowned.
// Keep the object alive when the owner leaves, giving it to the host
GameObject.Network.SetOrphanedMode( NetworkOrphaned.Host );

NetworkFlags: controlling transform sync

You can opt individual transform axes out of automatic synchronization using NetworkFlags:
// Disable rotation and scale sync — only position is sent
GameObject.Network.Flags = NetworkFlags.NoRotationSync | NetworkFlags.NoScaleSync;

// Disable all transform synchronization
GameObject.Network.Flags = NetworkFlags.NoTransformSync;

// Disable interpolation for this object
GameObject.Network.Flags = NetworkFlags.NoInterpolation;
Only the host can change NetworkFlags after an object has already been spawned. Clients that try to do so will have their changes ignored.

Lifecycle events

Implement the following interfaces on your components to react to network events:
public class MyComponent : Component, Component.INetworkSpawn
{
    // Called on all clients when this object is first spawned on the network
    public void OnNetworkSpawn( Connection owner ) { }
}
You can also react to ownership changes by implementing IGameObjectNetworkEvents callbacks:
public class MyComponent : Component
{
    // Called when this client gains control
    protected override void OnStartControl() { }

    // Called when this client loses control
    protected override void StopControl() { }

    // Called whenever the owner changes
    protected override void NetworkOwnerChanged( Connection newOwner, Connection oldOwner ) { }
}

Next steps

Sync vars

Sync component properties automatically using [Sync] and SyncFlags.

RPCs

Call methods across the network with Rpc.Broadcast, Rpc.Host, and Rpc.Owner.

Build docs developers (and LLMs) love