Running locally
Build the player, run the whole mesh on one machine, watch it on the dashboard, and stop it.
Everything below goes through the nebula CLI, run from inside a project that has had nebula init (the Nebula repository is itself such a project). The Editor menu Nebula offers the same operations for people who prefer buttons.
Build
nebula build
nebula build --linuxnebula build runs Nebula.Editor.NebulaBuild in Unity batchmode, using the Unity version from ProjectSettings/ProjectVersion.txt found through Unity Hub's install folders, NEBULA_UNITY, or nebula config unity. It produces the executable every role runs: Builds/Win64/Nebula.exe on Windows (the base name comes from executable in nebula.json). --linux builds the Linux dedicated server into Builds/Linux64 and packs Builds/nebula-linux.tar.gz for deployment.
If the Editor has the project open it holds an exclusive lock, so the build automatically runs from a mirrored copy under ~/.nebula-cli/scratch/<project> and the result is copied back into Builds/. Lines tagged [nebula] and compiler errors are echoed while it runs; the full log is Builds/unity-build.log. A running mesh holds the previous build open; nebula build --stop-mesh stops it first.
Start
nebula start --open-ui
nebula start --workers 2 --bots 2
nebula start --workers 4 --npcs 128start does, in order:
- Starts a local SpacetimeDB if none answers on
mesh.spacetimeUrifromnebula.json(logs toBuilds/<platform>/Logs/spacetimedb.log). - Publishes the control-plane module with fresh data (
--skip-publishto keep the tables). - Launches the orchestrator from the last build. The orchestrator launches the gateway and
--workersworker processes, writes one lease per container, and deals containers across the workers. - Launches
--botsbot clients. - Waits for the dashboard and prints how to join.
Defaults come from the mesh section of nebula.json. --build builds first.
Joining
Press Play in the Editor (NebulaBootstrap.EditorRole is Client by default), or run the build as a client:
Builds\Win64\Nebula.exe -nebula-role client -nebula-name jesseEither way a title screen asks for the gateway (Local = 127.0.0.1:7000, Hetzner = the last remote address you used, or anything typed in) and a name. Escape in game brings it back to disconnect or switch. Clients started with -nebula-gateway <addr:port> or -nebula-connect, and bots, skip the title screen and connect at once.
Bots and NPCs
Two different things drive a pawn without a human, and they cost very different amounts:
Bot (--bots N) | NPC (--npcs N) | |
|---|---|---|
| What it is | A full client process (-nebula-role client -nebula-bot) that connects through the gateway, predicts and reconciles like a real player, with a bot brain in place of the keyboard | A server-driven entity: an ordinary entity with no owning client, driven by whichever worker owns it |
| Cost | One headless Unity player each | One entity |
| Use it for | Exercising the client path | Load |
| How many | A handful. 128 of them on one machine starve the workers | Hundreds. 128 NPCs on 4 workers ran for 7 minutes at 0.25 to 0.35 ms per tick |
The NPC total is a live mesh setting: change it on the dashboard, or type npcs 300 in the in-game console (backquote key). The policy of who spawns which NPC is game code, described in Spawning.
Watch
nebula status
nebula logs w1 --follow
nebula logs gateway -n 200status prints the workers with the containers they own, how many players, bots and NPCs each simulates, and the orchestrator's recent events. logs reads a role's log: orchestrator, gateway, w1..wN or bot1... Logs live next to the build in Logs/.
The dashboard at http://localhost:7080/ shows the same and more: every worker with its authoritative and ghost entity counts, tick time and heartbeat age; the container-to-worker table with lease epochs; the gateway; mesh settings; and the event log. Its buttons add a worker, remove one gracefully, kill one (a simulated crash; it is relaunched) and force a rebalance. The same operations are an HTTP API, described in Orchestrator and dashboard.
In game, F3 toggles the technical overlay: tick, RTT and input lead, your container and its worker, handovers observed, and the container-to-worker table.
Stop
nebula stop
nebula stop --spacetimestop kills every process of the build and the SpacetimeDB the CLI started. --spacetime also stops one that was already running before nebula start.
Unattended runs
Tools/smoke-test.ps1 drives the mesh through the CLI with bot clients that roam between quadrants and shoot at each other, then reads the logs and reports handovers, cross-worker hits, kills, errors and warnings:
pwsh Tools/smoke-test.ps1
pwsh Tools/smoke-test.ps1 -KillWorker w2 -KillAfter 30
pwsh Tools/smoke-test.ps1 -ScaleTo 2 -ScaleAfter 25-KillWorker kills a worker mid-run to check reassignment and relaunch; -ScaleTo shrinks the mesh through the dashboard API to check graceful drain. Tools/typecheck.ps1 is a compile check without the Editor. Both are described in Debugging.
From the Editor
The Nebula menu has Control Plane (start and stop a local SpacetimeDB, publish the module, regenerate the C# bindings), Mesh (start and stop a local mesh from the last build, open the dashboard, launch an extra client window) and Build (Windows player, Linux dedicated server). A game adds its own menus next to it; the ShooterGame demo, for example, has ShooterGame > Generate Arena Scene + Prefabs, which regenerates its scene, prefabs and config from code.