#multiplayer
16 items (4 guides · 12 fixes)
The practical patterns for Sandbox.Decal: orienting the projection box to a hit normal, keeping a decal byte-identical across multiplayer peers, making paint follow an animated character, and scaling to thousands of decals without a performance cliff, plus the pitfalls that catch each one.
Two proven architectures on top of the engine networking primitives: replicate the generator spec (not the geometry) for deterministic worlds, and retrofit local-only gameplay systems to host-authority without breaking single-player.
The operational recipe for shipping player-hosted (P2P) multiplayer in s&box (lobby mechanics, invite codes, the join handshake liveness contract, replication traps, and the three-rung testing ladder), covering the layer the official docs don't document and where live multi-peer sessions actually break.
The complete method for wiring s&box's built-in Voice component into a networked game (push-to-talk, 3D positional playback, custom falloff curves, speaking indicators, and lip-sync), with no third-party voice SDK.
A second editor instance launched with -joinlocal is not a real Steam lobby member, yet Networking.GetData still resolves the host's Networking.SetData values -- they arrive over the ServerDataMsg the host sends on connect, not via lobby membership. The message can lag scene load by a few frames, so read GetData in a short poll loop.
A -joinlocal second instance connects to whichever process holds the loopback port 127.0.0.1:55333, so the precondition to check is socket ownership, not which editor is in play mode.
A joining client can build a code-generated world twice -- once on local StartupScene load, once on the networked scene handoff. A non-idempotent world author that clears its tracking lists but never destroys prior GameObjects stacks a whole second world. Make the author idempotent, and compute any sync hash from the build recipe, not a live scene scan.
Dev-host streaming sends assemblies and compiled assets but NOT loose data files read via FileSystem.Mounted: a joining client that loads a raw JSON manifest builds differently, silently.
Deferred Destroy() leaves the old code-built world overlapping the fresh one for a frame: use DestroyImmediate for teardown before rebuild, and pair it with a recipe hash for belt-and-suspenders join verification.
A static Instance claimed behind if (!IsProxy) in OnStart grabs the host's character on a joining client: the client camera follows the wrong player forever.
sbox.exe -joinlocal +instanceid 1 gives you a real second peer against an editor host with no publish, no second Steam account, and no lobby discovery. It has no host selector: it joins whichever local editor is in PLAY MODE, so no other editor on the machine may be playing.
A batch of networking API facts, verified from the installed build's source and XML, that overturn common assumptions when you plan multiplayer code before it touches the compiler. LobbyInformation is a struct, so a null guard does not compile. Networking.Connections is deprecated in favour of Connection.All and emits CS0618. Connection.MaxChunkSize is internal, so game code hard-codes the 131072 value instead of referencing the symbol. NetworkAccessor exposes Owner, OwnerTransfer, and OrphanedMode as get-only, with AssignOwnership, SetOwnerTransfer, and SetOrphanedMode called after NetworkSpawn. Networking.TryConnectSteamId exists and is public. SB1000 whitelisting is assembly-level, so the real constraint on a networking call is public versus internal accessibility, not the whitelist. A green dotnet build does not mean an editor-green result for networked types.
The Sandbox.Voice component defaults PushToTalkInput to 'voice', but not every project ships a matching 'Voice' InputAction. PTT is a dead key with zero errors until you add it to Input.config.
An [Rpc.Broadcast] called on a component whose GameObject is not networked executes locally and silently never crosses the wire -- no warning at any log level.
Sandbox.Decal self-seeds with Random.Shared.Int(10000) on enable: a decal spawned identically on two peers renders differently by default.
A Steam lobby survives its host switching to a different s&box game with stale metadata: a joiner connects and loads the wrong game's content.