Unity-first · prototype 0.1 · MIT-style honesty included

Dynamically meshed multiplayer servers for Unity

One world, many dedicated servers. Nebula leases each container of your level to a worker, ghosts entities across the seams before they cross, and hands authority over mid-firefight without the player noticing. Written against a Mirror and NGO-shaped API, run from one command-line tool.

Windows (PowerShell)
iwr https://windows.nebula.1by3.co -useb | iex
macOS / Linux
curl -sSf https://install.nebula.1by3.co | sh

Five roles, one build

Every box below is the same Unity player started with a different -nebula-role. Workers simulate the containers they lease and peer directly over UDP for ghosts and authority transfers. The gateway is the one address clients connect to. The orchestrator deals containers to workers through a SpacetimeDB control plane that is never on the per-tick path.

  • Worker: headless Unity, 60 Hz, ticks derived from the wall clock so nobody is the tick master.
  • Gateway: routes inputs to the current owner, drops stale epochs, caches keyframes for late joiners.
  • Orchestrator: keeps N workers alive, reassigns leases, serves the dashboard and its HTTP API.
  • Control plane: leases and heartbeats in SpacetimeDB; if it goes away the mesh keeps simulating.
  • Client: predicts, reconciles, and is never a party to the handover protocol.
SpacetimeDB control planeworkers · leases · gateways · settingsOrchestratordashboard :7080Gatewayudp :7000Worker w1NE · udp :7101Worker w2SW · udp :7102lateral link: ghosts + authority transfersNE · w1NW · w1SE · w2SW · w2containers, leased to workers; entities cross with a handoverClientinputs up, snapshots down

Containers, not grids

Authority is assigned per designer-authored volume with its own local space: a room, a ship, a district. The container tree is static; which worker simulates each one is decided at runtime.

Pre-warmed handover

Entities approaching a boundary are ghosted to the neighbouring worker ahead of time. The flip hands over the exact final state, the new epoch and the not-yet-simulated inputs, so the input stream never breaks.

The API you already know

NetworkBehaviour, NetworkVariable, ClientRpc, ServerRpc, NetworkTransform, NetworkAnimator, NetworkRigidbody. The meshing-specific additions fit on one line: HasAuthority, IsGhost, AuthorityRpc.

Disposable workers

Workers are stateless compute leased authority over containers. Kill one and its containers are reassigned within a second; scale from four workers to two mid-match and players see a handover, nothing more.

One CLI, local to cloud

nebula init installs it into your Unity project, nebula start runs the whole mesh on your machine, nebula deploy puts the same build on real VMs with a dashboard you can watch.

Honest about limits

This is a working prototype, not a finished product. The docs say what is verified, what is deliberately not there yet, and what the current security caveats are.

Gameplay code that does not know it is meshed

A predicted controller is a struct of input and a pure Simulate. The worker runs it with the client's inputs; the client runs it ahead and replays after a correction. When the pawn walks into a container owned by another worker, the buffered inputs travel with it.

The one meshing-specific line is the AuthorityRpc: it runs on whichever worker owns the victim, as a direct call when that is you and over the lateral link when you only hold a ghost.

Prediction guide
public sealed class PlayerController : PredictedBehaviour<ShooterInput>{    public NetworkVariable<float> Health = new NetworkVariable<float>(100f);    // Owning client: sample the keyboard once per tick.    protected override ShooterInput GatherInput() { /* ... */ }    // Runs on the worker, on the predicting client, and again during a replay.    protected override void Simulate(uint tick, in ShooterInput input, float dt)    {        Move(input, dt);        if (input.Fire && HasAuthority && TraceShot(out var victim))        {            // Runs on whichever worker owns the victim: local call, or the lateral link.            victim.AuthorityRpc(victim.TakeDamage, Damage, NetId, PlayerName.Value);        }    }    [AuthorityRpc] void TakeDamage(float amount, ulong attacker, string name) => Health.Value -= amount;    [ClientRpc]    void RpcShotFired(Vector3 from, Vector3 to, bool hit) { /* laser bolt */ }}

What has been verified

The repository's smoke test runs the whole mesh headless with bot clients that roam between containers and shoot at each other, then reads the logs. All runs on one machine; the same build runs on Hetzner Cloud VMs.

ScenarioResult
4 workers, 3 bots, 75 s47 authority handovers (out = in), 39 cross-worker hits, 15 kills, 0 errors
Kill worker w3 at 25 sIts container reassigned within a second; w3 relaunched after 8 s and got it back. The simulation never stopped.
Scale 4 workers to 2 mid-runw3 and w4 drained in one pass, handing every entity over; 0 drain timeouts, 0 errors
128 worker-simulated NPCs, 7 min~30 handovers per second sustained, 0 dropped packets, worker tick 0.25 to 0.35 ms

Deliberately not there yet: rewind on hit validation, delta compression, persistence, staged container reassignment, a warm worker pool, authenticated control-plane reducers. The full list is in the architecture page.