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.UpdateIntervalmakes 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, andInterestBackgroundTiersinNebulaConfiggive each priority its own distance bands, so slowing a crowd no longer slows players or ships.SyncDistanceRatingmakes a behavior's sync state follow the same bands.NetworkIdentity.Sleepputs an entity to sleep. A sleeping entity keeps its authority, state, and ghosts, but itsNetworkTickis not called and it sends no updates.SleepWhenUnobservedsleeps 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 entitiesReplicate 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 collectionHandle connections that end
The client now reports why a connection ended and what happens next:
NebulaClient.Disconnectedpasses aDisconnectInfowith a typedDisconnectReason, a message, andWillRetry.IsReconnecting,ReconnectAttempt, and theReconnecting,Reconnected, andReconnectGaveUpevents show a reconnection as it happens.NebulaConfigsets 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.KickandNebulaGateway.Kickremove 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.
LocalPlayerLostfires when the client loses its pawn.ServerStalledandServerResumedfire when no state arrives from a worker forClientStallSeconds.- On the server,
OnPlayerDisconnectedandOnPlayerReconnectedrun on the worker that owns the pawn, andIsOwnerConnectedreplicates whether the player is still there.
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.
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.
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.
ScopeRetireWithEntitieslets a scope retire while it holds saved objects. Its persistent entities come back with it.NebulaBuild.BuildLinuxBatchbuilds 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
Connectedand never raisedConnectionStateChanged. It now moves toDisconnected. - An
InstanceBoundaryinside 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
NetworkTransformalso 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.
0.1.0-beta.1 release