Back to the blog

Release

Nebula 0.1.0-beta.1

This release follows beta.0. A worker can now simulate a large crowd of server-owned characters, and a client is sent far less of it. A client can tell why its connection ended and what it is doing about it. A worker can read your game's settings from environment variables. Clients built for beta.0 must be rebuilt.

Run crowds of server-owned characters

Every entity used to cost its worker about 4 microseconds each tick, whether or not it moved or anyone saw it, and a client received every nearby entity at a player's update rate. Three new controls change that:

  • NetworkIdentity.UpdateInterval makes the worker update an entity every N ticks instead of every tick. RelevancePriority (Normal, High, Low, Background) sets how quickly the gateway slows its updates to a distant client.
  • InterestHighTiers, InterestLowTiers, and InterestBackgroundTiers in NebulaConfig give each priority its own distance bands, so slowing a crowd no longer slows players or ships. SyncDistanceRating makes a behavior's sync state follow the same bands.
  • NetworkIdentity.Sleep puts an entity to sleep. A sleeping entity keeps its authority, state, and ghosts, but its NetworkTick is not called and it sends no updates. SleepWhenUnobserved sleeps it once no gateway has watched it for a number of seconds.

In our measurements, 1,500 sleeping entities beside 150 active ones cost a worker 0.43 milliseconds a tick in the Editor. A client among 200 active and 1,000 background walkers was sent about 90 kilobits per second with the crowd settings, while a normal player 40 meters away kept 15 updates a second. Your figures will differ with your entity counts and settings.

A server-owned character that walks onto a moving ship now crosses into the ship's physics frame and rides it, the same way a player does. The new Server-owned boarding sample shows the code.

Run crowds of server-owned entities

Replicate a map that sends only what changed

NetworkMap<TKey, TValue> is a keyed collection you declare on a NetworkBehaviour. The authoritative worker writes it, every copy reads it, and each tick Nebula sends only the keys that changed. A client that starts holding the entity later receives one full copy, then the same changes as everyone else. Add [Persist] to save it.

Chunk state uses a map now, so mining one rock sends that entry instead of the chunk's whole table. Its API and saved format are unchanged.

Replicate a keyed collection

Handle connections that end

The client now reports why a connection ended and what happens next:

  • NebulaClient.Disconnected passes a DisconnectInfo with a typed DisconnectReason, a message, and WillRetry.
  • IsReconnecting, ReconnectAttempt, and the Reconnecting, Reconnected, and ReconnectGaveUp events show a reconnection as it happens. NebulaConfig sets the retry schedule and an optional give-up time.
  • NebulaClient.Leave() ends the session at once, so the pawn does not stay in the world for the reclaim time. NebulaWorker.Kick and NebulaGateway.Kick remove a player with a reason the client can read.
  • A gateway that stops first tells its clients, so they no longer wait out the 8-second transport timeout.
  • LocalPlayerLost fires when the client loses its pawn. ServerStalled and ServerResumed fire when no state arrives from a worker for ClientStallSeconds.
  • On the server, OnPlayerDisconnected and OnPlayerReconnected run on the worker that owns the pawn, and IsOwnerConnected replicates whether the player is still there.
Find out why the connection ended

Gate features on a sign-in token

Set NebulaConfig.ForwardedClaims to a list of claim names, and the gateway copies them from the verified OpenID Connect token to the worker. Read them from PlayerInfo.Claims or NetworkIdentity.TryGetOwnerClaim. Clients are never sent claims. NameClaim names a claim to use as the player's name, so a client can no longer choose its own.

Forward token claims to workers

Pass settings to workers

NebulaEnv.Get reads a setting from the command line, the process environment, or a .env.nebula file at your project root. nebula env manages a deployment's variables on Nebula Cloud or your own Hetzner project. A worker reads its variables once, when it starts, so on Nebula Cloud run nebula restart-workers to apply a change now. It replaces the workers one at a time.

Set environment variables

More changes

  • An entity can declare an extent, so a large building or ship is ghosted to a neighboring worker when its walls cross a seam, not only its root.
  • ScopeRetireWithEntities lets a scope retire while it holds saved objects. Its persistent entities come back with it.
  • NebulaBuild.BuildLinuxBatch builds the Linux player in batch mode, for a continuous integration job.
  • Two checkouts of one project can each run the Multiplayer Play Mode loop, using a port offset in UserSettings/NebulaEditorPortOffset.txt.

Fixes

  • After a refusal that stops retries, such as a version mismatch, the client stayed Connected and never raised ConnectionStateChanged. It now moves to Disconnected.
  • An InstanceBoundary inside a scoped grid, such as a planet, never let anyone in. It now stands in the scope of the container it is parented under.
  • In the Multiplayer Play Mode loop, a client that joined far from the origin received no new spawns or variable changes. It now receives them.
  • A client's reduced-rate tier could freeze an entity that updates every few ticks. A root NetworkTransform also sends its reliable recovery entry once it has settled, which removes about a tenth of a crowd's traffic.
  • The worker's verbose launch log no longer prints the mesh token or the player signing key.

Upgrade to beta.1

0.1.0-beta.1 uses wire protocol 24. A gateway admits clients of protocols 23 and 24 and refuses older ones with ProtocolUnsupported, including clients built for beta.0. Rebuild your clients against this version. Gateways and workers of one mesh must still run the same build.

Replace gateways and workers
0.1.0-beta.1 release