NebulaConfig
Project-wide Nebula settings.
Nebula · Packages/com.1by3.nebula/Runtime/Core/NebulaConfig.cs[CreateAssetMenu(menuName = "Nebula/Config", fileName = "NebulaConfig")]
public sealed partial class NebulaConfig : ScriptableObjectProject-wide Nebula settings. Workers and clients load Resources/NebulaConfig. Builds export its settings to nebula-services.json for the standalone orchestrator and gateway. Command-line switches override fields at runtime.
Fields
GameScene
public string GameScene = "Arena";Scene containing the Container volumes and gameplay. Loaded by workers and clients; builds export its containers for the services.
WorldManifest
public WorldContainerManifest WorldManifest;Baked container manifest of an authored partitioned world (Nebula > World). Leave empty for a single scene or a RuntimeWorld.
RuntimeWorld
public WorldDefinition RuntimeWorld;Definition of a procedural world whose containers are registered while the mesh runs. Nebula loads its floating-origin frame without authored cell scenes. Leave WorldManifest unset: a baked manifest takes precedence when both are assigned.
ClientLoadRadiusCells
public int ClientLoadRadiusCells = 1;Clients keep this many cells around the local pawn loaded (1 = the 3x3x3 block).
WorkerLoadRingCells
public int WorkerLoadRingCells = 1;Workers keep this many rings of neighboring cells loaded around every cell they control. Ghosts and boundary physics need this geometry.
OriginShiftThresholdCells
public int OriginShiftThresholdCells = 4;The floating origin moves once the pawn (client) or the centroid of the leased cells (worker) is more than this many cells from the origin cell.
ServerBuildDevelopment
public bool ServerBuildDevelopment = true;Editor only. Linux dedicated server builds are development builds (slower; profiler and script debugging). Untick for a release server. nebula build --release / --development override it for one build.
ServerBuildScriptingBackend
public NebulaServerScriptingBackend ServerBuildScriptingBackend = NebulaServerScriptingBackend.Mono;The scripting backend of the Linux dedicated server build. Mono (the default, as before) or IL2CPP, which needs the Unity install's Linux IL2CPP module. nebula build --il2cpp / --mono override it for one build.
EditorRunMode
public NebulaEditorRunMode EditorRunMode = NebulaEditorRunMode.Mesh;Editor only. Mesh: Play runs EditorRole against a mesh started with nebula start. MultiplayerPlayMode: a Multiplayer Play Mode virtual player hosts the server (orchestrator, gateway, one worker) and the main Editor joins it as a client, with no build. Builds ignore this.
EditorPersistence
public NebulaEditorPersistence EditorPersistence = NebulaEditorPersistence.DevSaveFile;Where the server a virtual player hosts keeps persistent entities under NebulaEditorRunMode.MultiplayerPlayMode: NebulaEditorPersistence.DevSaveFile (the default) keeps them in Library/Nebula/DevSaves/world.bin from one Play to the next, apart from anything a mesh started with nebula start keeps; NebulaEditorPersistence.InMemory starts every Play from a fresh world. Nebula > Dev Loop > Reset Dev Saves deletes the file.
EditorPortOffset
public int EditorPortOffset = 50;Added to GatewayPort, WorkerBasePort and DashboardPort by both sides of NebulaEditorRunMode.MultiplayerPlayMode, so the dev loop and a mesh started with nebula start can run on one machine at once. 50 by default: with the default ports, the dev loop's gateway listens on 7050, its worker on 7151 and its dashboard on 7130. 0 uses the ports as configured. A checkout's UserSettings/NebulaEditorPortOffset.txt replaces it for that checkout only (EditorDevPaths.PortOffset), so copies of one project can run their dev loops side by side.
GatewayAddress
public string GatewayAddress = "127.0.0.1";GatewayPort
public ushort GatewayPort = 7000;WorkerBasePort
public ushort WorkerBasePort = 7100;The base of the worker ports: a worker listens on WorkerBasePort plus its index. A worker started with -nebula-port listens on that port instead, and one started without it listens on the PORT environment variable when that is set to a port from 1 to 65535. Only the worker reads PORT. The worker registers the port it listens on, and gateways and other workers connect to that, so no other process needs this value to find it.
WorkerAdvertiseAddress
public string WorkerAdvertiseAddress = "127.0.0.1";Address workers advertise to peers and the gateway.
WebClients
public bool WebClients = true;The standalone gateway also accepts clients from a Web build: WebRTC signaling over HTTP on WebPort and data channels over UDP on WebRtcPort. It serves the web build too when a Web folder sits next to it. -nebula-web false turns this off.
WebPort
public ushort WebPort = 0;TCP port of the gateway's HTTP server (WebRTC signaling and the web build). 0 = the same number as GatewayPort. A browser client connects to this port. -nebula-web-port overrides.
WebRtcPort
public ushort WebRtcPort = 0;UDP port browsers' WebRTC traffic arrives on. 0 = GatewayPort + 1. -nebula-webrtc-port overrides.
ControlPlaneUrl
public string ControlPlaneUrl = "http://127.0.0.1:7080/";Address of the orchestrator that hosts the control plane (its dashboard, e.g. http://127.0.0.1:7080/), for a worker or gateway started by hand. Processes the orchestrator launches get it on the command line (-nebula-control-plane).
MeshToken
public string MeshToken = "";Shared secret every worker and gateway presents to the orchestrator. Empty = none (fine on a development machine or a private network). -nebula-token overrides.
UseLocalControlPlane
public bool UseLocalControlPlane = false;Keep the control plane in this process instead of talking to an orchestrator. Only meaningful when orchestrator, gateway and worker share a process (tests, single-process runs).
DatabaseUrl
public string DatabaseUrl = "";Where the orchestrator keeps the control plane and saved entities: sqlite:<file> or postgres://user:password@host/db (standalone orchestrator), file:<folder> (Unity orchestrator), or memory. Empty = a default next to the process. -nebula-database overrides.
AuthIssuers
public string AuthIssuers = "";OpenID Connect providers whose ID tokens the gateway accepts, as issuer URLs separated by commas (for example https://accounts.google.com or https://your-tenant.auth0.com/). The gateway fetches each provider's signing keys from its discovery document. Empty = no sign-in tokens are accepted. -nebula-auth-issuers overrides.
AuthAudience
public string AuthAudience = "";The audience (aud claim) a token must carry: the client id the provider issued your game. Empty skips the check, which lets a token minted for another app of the same provider join. -nebula-auth-audience overrides.
AuthAnonymous
public bool AuthAnonymous = true;Let clients that present no token join with an anonymous identity the gateway issues and the client keeps for its next connection. Off = every client needs an ID token from AuthIssuers. -nebula-auth-anonymous overrides.
AuthSigningKey
public string AuthSigningKey = "";Secret the anonymous identity tokens are signed with; every gateway of a mesh must use the same one. Empty = derived from MeshToken, or, with no mesh token either, a random key kept in nebula-auth.key next to the gateway. -nebula-auth-key overrides; the standalone gateway also reads NEBULA_AUTH_KEY.
ForwardedClaims
public string ForwardedClaims = "";Claims of a verified sign-in token that the gateway passes on to workers, as claim names separated by commas (for example is_admin, username). Workers read them from NetworkIdentity.OwnerClaims, PlayerInfo.Claims and NebulaWorker.GetPlayerClaims. At most 16 names; values longer than 256 characters are dropped. Anonymous players have none. Empty = none are forwarded. -nebula-auth-forward-claims overrides.
NameClaim
public string NameClaim = "";A claim of the verified sign-in token that becomes the player's name (for example username or name) in place of the name the client asked for. A player whose token lacks the claim, and an anonymous player, keeps the client's name. Empty = always the client's name. -nebula-auth-name-claim overrides.
SessionReclaimSeconds
public float SessionReclaimSeconds = 30f;Seconds a worker keeps a player's pawn after the player's connection drops, so the player can reconnect (through any gateway of the mesh) and continue with the same session and pawn. 0 despawns at once.
SingleSessionPerPlayer
public bool SingleSessionPerPlayer = true;Coordinate one connection per player through the gateway fleet. A replacement waits until the previous gateway confirms disconnection; if that cannot be coordinated, the new join is rejected. Off lets one identity hold several pawns at once. -nebula-single-session overrides.
GatewayDrainReconnectSeconds
public float GatewayDrainReconnectSeconds = 10f;When a gateway is asked to drain, how many seconds its clients are told they have to reconnect before it closes their links.
GatewayShutdownDrainSeconds
public float GatewayShutdownDrainSeconds = 0.5f;When a gateway process stops (the host object is destroyed, the application quits, or the standalone gateway gets SIGTERM or Ctrl-C), it first tells its connected clients: that it is draining when another gateway is serving, or that the server is shutting down when none is. It then waits up to this many seconds for the notices to go out, returning as soon as every client has hung up, so clients reconnect at once rather than after the transport's timeout. 0 stops at once, without telling anyone.
GameContentVersion
public uint GameContentVersion = 0;The game's content version. Clients announce this value when joining. A gateway with a nonzero value checks the client's version against MinGameContentVersion..GameContentVersion. A gateway value of 0 disables the check. -nebula-content-version overrides.
MinGameContentVersion
public uint MinGameContentVersion = 0;The oldest game content version a gateway admits, when GameContentVersion is set. 0 = exact match: only clients carrying GameContentVersion may join. -nebula-min-content-version overrides.
EncryptClients
public bool EncryptClients = true;Enable encrypted client UDP connections using ChaCha20-Poly1305 and X25519. Plaintext clients are accepted unless RequireEncryption is enabled. Infrastructure connections are unencrypted and require a private network. -nebula-encrypt-clients overrides.
RequireEncryption
public bool RequireEncryption = false;Require encrypted client connections. Plaintext clients receive an EncryptionRequired refusal. -nebula-require-encryption overrides.
EncryptionCertPath
public string EncryptionCertPath = "";PEM file holding the certificate the gateway presents to clients (an RSA certificate; the key may be in the same file). Empty = a self-signed certificate generated on first run and kept in EncryptionSelfSignedPath. -nebula-encryption-cert overrides.
EncryptionKeyPath
public string EncryptionKeyPath = "";PEM file holding the certificate's private key, when it is not in EncryptionCertPath. -nebula-encryption-key overrides.
EncryptionCertPem
public string EncryptionCertPem = "";The certificate as PEM text instead of a file, for deployments that inject secrets as environment variables. The standalone gateway also reads NEBULA_ENCRYPTION_CERT.
EncryptionKeyPem
public string EncryptionKeyPem = "";The private key as PEM text instead of a file. The standalone gateway also reads NEBULA_ENCRYPTION_KEY.
EncryptionSelfSignedPath
public string EncryptionSelfSignedPath = "";File for the generated self-signed certificate and key. Empty uses nebula-transport.pem in the standalone gateway's application directory or Unity's persistent data directory.
ClientEncryption
public bool ClientEncryption = false;Client: encrypt UDP connections to the gateway. Disabled by default. WebRTC connections use their own encryption. -nebula-encrypt overrides.
GatewayFingerprint
public string GatewayFingerprint = "";Client: the expected SHA-256 fingerprint of the gateway certificate's SubjectPublicKeyInfo public-key encoding, as hex. Used when ClientEncryption is enabled. Empty skips certificate authentication. The gateway prints its fingerprint at startup. -nebula-gateway-fingerprint overrides.
WorkerCount
public int WorkerCount = 4;How many worker processes the orchestrator starts with. Autoscaling then moves the count between MinWorkers and MaxWorkers.
MaxWorkers
public int MaxWorkers = 32;The most workers the orchestrator will ever run (dashboard and autoscale stop here). Worker indices are 16-bit, so up to 65535.
AssignmentPolicy
public string AssignmentPolicy = "auto";How containers are dealt to workers: 'auto' (the cost policy: by reported load along a space-filling curve), 'baked' (the opt-out: evenly by count, sticky), 'cost' (the same as auto, named explicitly). -nebula-assignment overrides.
CostRebalanceThreshold
public float CostRebalanceThreshold = 0.3f;Cost policy: how far above the average a worker's cost may be before containers are re-dealt (0.3 = 30 %).
CostWeights
public CostWeights CostWeights = CostWeights.Default;Cost policy: what one player / bot / server-driven entity / other entity costs, and what a leased container costs by itself.
DefaultCostLinkBytesPerSec
public const double DefaultCostLinkBytesPerSec = 100.0 * 1000.0 * 1000.0 / 8.0;The default of CostLinkBudgetMbps in bytes per second: 100 Mbit/s.
CostLinkBudgetMbps
public float CostLinkBudgetMbps = 100f;Cost telemetry: the outbound budget one worker's traffic is weighed against, in megabits per second. It decides nothing about what is sent; it is the yardstick that lets a container's bytes be compared with its simulation time, so the dashboard and the scaler can say whether a hot container is hot in simulation, in replication or in gateway relay.
CapacitySaturation
public float CapacitySaturation = 0.9f;How full one container (or one scope, taken as the worst of its parts) may get before the mesh calls it at capacity: the dominant cost component's share of its own budget, 0.9 = 90 %. A join or a prepared transfer into a target at capacity is refused with a typed reason unless NebulaAdmission.Decide admits it. 0 turns the signal off and admits everything, as before. -nebula-capacity-saturation overrides.
AutoScale
public bool AutoScale = true;Keep the worker count between MinWorkers and MaxWorkers from how busy the workers are: add one when the busiest worker's tick time stays over ScaleOutUtilization of the tick budget, remove one when the mesh's mean stays under ScaleInUtilization. Every change is checked against a dry run of the assignment policy first.
MinWorkers
public int MinWorkers = 1;The fewest workers autoscaling will leave running. 0 allows scaling to zero (the first player then waits for a worker to boot).
ScaleOutUtilization
public float ScaleOutUtilization = 0.7f;Grow when the busiest worker spends more than this fraction of its tick budget simulating (0.7 = 11.7 ms of a 16.7 ms tick), for ScaleHoldSeconds.
ScaleInUtilization
public float ScaleInUtilization = 0.3f;Shrink when the mesh's mean utilization stays under this fraction of the tick budget for ScaleHoldSeconds and the survivors would stay under ScaleOutUtilization.
ScaleHoldSeconds
public float ScaleHoldSeconds = 30f;How long a condition must hold before a worker is added or retired. Only one change happens per hold.
ScaleWindowSeconds
public float ScaleWindowSeconds = 20f;Length of the rolling per-worker tick-time window whose 90th percentile is the scaling signal.
ScaleMinGain
public float ScaleMinGain = 0.1f;The smallest predicted drop in the busiest worker's utilization that makes another worker (or a re-deal) worth it. Below this the orchestrator reports the hot container as unsplittable instead of growing.
IdlePoolSeconds
public float IdlePoolSeconds = 0f;How long a retired worker is kept in the idle pool, ready to be taken back without a boot, on a host where that is cheaper than recreating it (a cloud VM). 0 = the host's own answer: Hetzner keeps it for the rest of the hour it has already been billed, a local process is killed at once.
SeamGraceMeters
public float SeamGraceMeters = 10f;Cost policy: a container with a player within this many metres of a seam that would move is left alone for a pass (see ContainerHint, phase 3).
WorkerExecutable
public string WorkerExecutable = "";Unity executable used to spawn workers. nebula start supplies this path to the standalone orchestrator with -nebula-worker-exe.
WorkerHost
public string WorkerHost = "process";Where workers run: 'process' (child processes of the orchestrator) or 'hetzner' (one cloud VM per worker). -nebula-host overrides.
BuildArtifactDir
public string BuildArtifactDir = "";Directory the orchestrator serves at /build/ (the Linux server tarball worker VMs download). Empty = next to the executable.
OrchestratorSpawnsGateway
public bool OrchestratorSpawnsGateway = true;WorkerHeartbeatSeconds
public float WorkerHeartbeatSeconds = 1f;WorkerTimeoutSeconds
public float WorkerTimeoutSeconds = 5f;WorkerCatchUpBudgetMs
public float WorkerCatchUpBudgetMs = 40f;Wall time in milliseconds a worker may spend simulating ticks in one frame while it catches up with the clock. Once a frame has spent this much, the remaining ticks wait for the next frames (or are skipped when the worker is more than 15 ticks behind), so a starved worker keeps a short frame and keeps polling the network and sending heartbeats. About two to three tick periods; 0 turns the budget off.
ServerFrameRate
public int ServerFrameRate = 0;Frames per second a worker or gateway process runs its Update loop at (it polls its network once per frame). 0, the default, runs at the tick rate (60), one tick a frame. Simulation stays at the 60 Hz tick rate whatever this is: a higher value makes a packet wait less for the next poll but costs CPU for every extra frame (240 measured about 6 x the frame time of 60 in a game worker), and a lower one (10 or more) runs several ticks in a frame, which models a loaded server. Clients are not affected. -nebula-server-fps overrides.
WorkerPollBeforeTick
public bool WorkerPollBeforeTick = true;A worker polls its network at the start of each frame's first FixedUpdate, before it simulates, so an input that arrived since the last Update is seen by the tick that follows (and by PredictedBehaviour.OnServerInputReceived) instead of one frame later. -nebula-poll-before-tick overrides.
FlushRpcsImmediately
public bool FlushRpcsImmediately = true;Push a client RPC onto the wire as soon as it is sent when it goes to one client (OwnerRpc) or asks for Delivery.Sequenced, on the worker and again on the gateway that forwards it, instead of at the end of the tick or the loop. A gateway also pushes what it forwarded from a poll before it does its other work. -nebula-flush-rpcs overrides.
DeadWorkerReplaceDelaySeconds
public float DeadWorkerReplaceDelaySeconds = 8f;Seconds to wait after a worker is declared dead before a replacement is launched.
WorkerDrainTimeoutSeconds
public float WorkerDrainTimeoutSeconds = 10f;Seconds a retiring worker gets to hand its entities over before it is killed regardless.
DashboardPort
public ushort DashboardPort = 7080;Port of the Nebula Dashboard the orchestrator serves (http://localhost:<port>/). 0 disables it.
GatewayExtension
public string GatewayExtension = "";Your own server code inside the standalone gateway: a class library that references the gateway's Nebula.Services.dll and implements Nebula.IGatewayExtension. This is where a game installs an interest policy, tags clients with their team and feeds fog-of-war changes. Give the assembly's file name (it sits next to the gateway executable, so it ships with the build and the deploy tarball) or an absolute path. Empty = no extension. -nebula-gateway-extension overrides.
GatewayExtensionType
public string GatewayExtensionType = "";Which class in that assembly to load, when it holds more than one IGatewayExtension. Empty = the only one. -nebula-gateway-extension-type overrides.
GatewayExtensionOptions
public string GatewayExtensionOptions = "";Settings passed to the extension, as key=value;key=value. It reads them with context.Option(key); -nebula-ext-<key> on the gateway's command line overrides one.
GhostBandMargin
public float GhostBandMargin = 4f;Entities within this many metres of a neighbouring container are ghosted to its worker ahead of time.
HandoverHysteresis
public float HandoverHysteresis = 0.35f;An entity must be this far inside a new container before authority transfers. This prevents repeated transfers near a boundary.
GhostLingerSeconds
public float GhostLingerSeconds = 2f;Ghosts stay resident this long after leaving the band.
StateHistoryTicks
public int StateHistoryTicks = StateHistory.DefaultWindowTicks;Ticks of pose and [SyncHistory] state every worker keeps per entity, for lag compensation and time-sensitive validation (NetworkIdentity.StateAt). About half a second at 60 Hz by default. 0 turns recording off. -nebula-state-history overrides.
AuthorityCallMaxHops
public int AuthorityCallMaxHops = 3;How many times an AuthorityRpc may be forwarded after the target entity changes worker before it is rejected with RejectedHopLimit. Also the number of authority changes a call's epoch may lag behind the entity before it is rejected as stale. -nebula-authority-call-hops overrides.
PortalProxyLayer
[Range(0, 31)]
public int PortalProxyLayer = 31;The physics layer Nebula puts a portal's proxies and aperture colliders on (docs/portals.md D26 to D28). Keep it free of your own objects and out of the layer masks of your own raycasts, and let it collide with whatever bodies collide with in the layer collision matrix. 31 by default.
ScopeRenderingLayers
public uint ScopeRenderingLayers = 0;Rendering-layer bits (a mask) a client reserves for drawn scopes, one per scope drawn at once (docs/portals.md D42): the view, the scopes it looks through, the public world and every scope kept drawn. Nebula stamps a scope's bit, and only that bit, on its static content, its chunks' content and its entities' renderers; the game uses the bits in its light and portal masks. 0 turns slots off; eight bits allow eight drawn scopes. Read the bit with Portals.RenderingLayerOf.
PersistenceMode
public string PersistenceMode = "auto";Where entities carrying a PersistentEntity are stored: 'auto' (the orchestrator uses its database, a worker asks the orchestrator, a single-process run uses a local file), 'database', 'remote', 'local' (a file next to the process), 'memory' or 'off'. -nebula-persistence-mode overrides.
PersistenceLocalFile
public string PersistenceLocalFile = "";File the local store writes to. Empty = <persistentDataPath>/nebula-persistence.bin. -nebula-persistence-file overrides.
PersistenceCheckpointSeconds
public float PersistenceCheckpointSeconds = 5f;Seconds between checkpoints of an authoritative persistent entity. A change or a move saves sooner; PersistentEntity.CheckpointSeconds overrides it per prefab.
PersistenceRestoreGraceSeconds
public float PersistenceRestoreGraceSeconds = 3f;After gaining a container lease, how long a worker waits before restoring that container's persisted entities. Gives the previous owner's handover time to arrive so nothing comes back twice.
SharedCacheMode
public string SharedCacheMode = "auto";Where NebulaSharedCache keeps the derived data workers share: 'auto' (the orchestrator uses its database, a worker of a mesh asks the orchestrator, a single-process run and the Editor use a local folder), 'local' (a folder), 'remote', 'database', 'memory' or 'off'. -nebula-shared-cache-mode overrides.
SharedCacheLocalFolder
public string SharedCacheLocalFolder = "";Folder the local shared cache writes to. Empty = <project>/Library/Nebula/SharedCache in the Editor, <persistentDataPath>/nebula-shared-cache otherwise. -nebula-shared-cache-folder overrides.
SharedCacheMaxObjectBytes
public int SharedCacheMaxObjectBytes = 32 * 1024 * 1024;Largest object the shared cache stores or returns, in bytes. Larger puts are refused (HTTP 413 from the orchestrator). Set the same value on the orchestrator and on every worker. -nebula-shared-cache-max-bytes overrides.
SharedCacheExpiryDays
public int SharedCacheExpiryDays = 30;Days a shared cache key may go unread before the orchestrator removes it. 0 keeps everything. -nebula-shared-cache-expiry-days overrides.
SharedCacheHostConcurrency
public int SharedCacheHostConcurrency = 8;Most shared cache requests the orchestrator serves at once; more get HTTP 503, which a worker treats as a miss. Keeps workers that fill a cold cache from starving the control plane.
SharedCacheClientConcurrency
public int SharedCacheClientConcurrency = 4;Most shared cache requests one worker has in flight at once; more wait their turn.
ScopeIdleRetireSeconds
public float ScopeIdleRetireSeconds = 300f;Seconds a shared simulation scope (an instance, a keyed world) may sit with nobody in it before the orchestrator retires it: its persistent entities are checkpointed, its containers are released, and the scope comes back when it is activated again. 0 turns retiring off. Never applies to the public world. -nebula-scope-idle-retire overrides.
ScopeRetireWithEntities
public bool ScopeRetireWithEntities = false;Retire an idle scope that nobody is playing in even though it still holds entities, such as saved crates or parked vehicles. Its persistent entities are checkpointed and come back with it. Off: a scope retires only once it holds no entity at all. -nebula-scope-retire-with-entities overrides.
SceneEntityGraceSeconds
public float SceneEntityGraceSeconds = 2f;After a worker gains a container lease, how long it waits before spawning the unspawned scene entities standing in it. Gives the previous owner's handover time to arrive so an entity is not spawned twice.
InterestRadius
public float InterestRadius = 120f;How far a client hears about an entity, in metres. A prefab's RelevanceRadius overrides it per entity. This bounds what a client is sent, not what the mesh simulates. -nebula-interest-radius overrides.
InterestExitMargin
public float InterestExitMargin = 16f;Extra metres an entity must travel past InterestRadius before it leaves a client's set. Stops an entity on the boundary from spawning and despawning repeatedly.
InterestLingerSeconds
public float InterestLingerSeconds = 1f;Seconds an entity must stay past the exit radius before the client is told to despawn it.
InterestCellSize
public float InterestCellSize = 64f;Edge of one interest region, in metres. With a world definition this is snapped to an integer division of the cell size so region edges fall on cell edges. -nebula-interest-cell overrides.
InterestPlanar
public bool InterestPlanar = true;Regions are infinite columns: height does not take part in the region key. Right for a surface world; turn it off for a space or volume game.
InterestEvalHz
public float InterestEvalHz = 4f;How often each client's interest set is re-evaluated, in times per second. Evaluations are staggered across ticks, and a client is also evaluated at once when its focus crosses a region edge.
InterestSubscribeMargin
public float InterestSubscribeMargin = 32f;Extra metres of regions a gateway subscribes around a focus, so entities are already arriving before the client can see them. Must cover the distance a focus travels between two evaluations.
InterestRegionLingerSeconds
public float InterestRegionLingerSeconds = 3f;Seconds a region stays subscribed after the last client needed it, so a player pacing along a region edge does not make a worker start and stop sending.
InterestLinkLingerSeconds
public float InterestLinkLingerSeconds = 10f;Seconds a gateway keeps a worker connection after the last reason to hold it has gone.
InterestResyncSeconds
public float InterestResyncSeconds = 30f;Seconds between the audit snapshots a gateway sends of its whole subscription, whatever the deltas said.
InterestMaxRadius
public float InterestMaxRadius = 1024f;Ceiling on a prefab's RelevanceRadius, in metres. Also how far a wide entity may reach, which bounds the work of matching it against every client. It is never uncapped: a value of 0 or less is reported by Validate and replaced with InterestRadius.
InterestMaxFoci
public int InterestMaxFoci = 8;Most places one client may be interested in at once (an RTS camera plus owned units, a spectator's target). Foci beyond this are dropped.
InterestHintMaxDistance
public float InterestHintMaxDistance = 60f;How far a client's focus hint may sit from its pawn, in metres. A further hint is clamped to this distance; a hint is an input, never authority.
InterestHintMaxHz
public float InterestHintMaxHz = 5f;Most focus hints accepted from one client per second. The rest are dropped.
InterestMaxExplicitPerClient
public int InterestMaxExplicitPerClient = 16;Most entities one client's policy may subscribe by id (party members, quest targets).
InterestFarMaxEntities
public int InterestFarMaxEntities = 64;Most entities one client holds in the far relevance tier at once (entities with a FarRelevanceRadius, seen as markers beyond the normal radius). The nearest are kept. 0 turns the far tier off for every client.
InterestMaxFocusSpeed
public float InterestMaxFocusSpeed = 12f;The fastest a player is expected to travel, in metres per second. Only used to check that InterestSubscribeMargin covers one evaluation of travel.
InterestMaxTravelPerUpdate
public float InterestMaxTravelPerUpdate = 4f;Interest for fast movers: the most metres an entity may travel between two updates a client receives. The gateway sends a fast entity more often than its distance tier says, so that at its speed it never moves further than this between updates (400 m/s: every tick; 60 m/s: every 4th). Slow entities keep their tiers. 0 turns it off.
InterestFocusLeadSeconds
public float InterestFocusLeadSeconds = 0.5f;Interest for fast movers: seconds of travel ahead of a moving pawn at which the gateway adds a second focus, so entities ahead are in the client's set before the pawn reaches them. Added only when the lead is longer than InterestExitMargin. 0 turns it off.
PartitionWarnEntities
public int PartitionWarnEntities = 2000;A worker warns when one container holds more than this many entities: the world wants partitioning, because one container is one worker's simulation budget. 0 turns the warning off.
PartitionWarnFilterMs
public float PartitionWarnFilterMs = 2f;A worker warns when filtering its entities for the gateways takes longer than this many milliseconds per tick. 0 turns the warning off.
ChunkedWorld
public bool ChunkedWorld = false;Turnkey unbounded chunked world: with a RuntimeWorld assigned, Nebula builds the chunk grid from its cell size, leases chunks around every pawn on workers, keeps the floating origin near the pawn on clients, and raises NebulaChunks.Loaded/Unloading on every role. The game only supplies chunk content.
ChunkPlanar
public bool ChunkPlanar = true;Chunks are columns: the grid has one layer at y = 0 and RuntimeWorld's CellSize.y is the column height. Right for a surface world; turn it off for a volumetric one.
ChunkRetireSeconds
public float ChunkRetireSeconds = 30f;Seconds a chunk nobody needs stays leased before the worker retires it (its persistent contents are checkpointed and come back).
ChunkedWorldServerRingMargin
public int ChunkedWorldServerRingMargin = 1;Chunks the worker keeps leased beyond InterestSettings.NearCells around every pawn (InterestSettings.ChunkRing). 1 is the default: a chunk's content is built a whole chunk of travel before interest can reach it. 0 leases only the chunks interest can reach, which costs a whole ring less (25 to 9 containers at near 1) and leaves only the rounding slack of InterestSettings.ChunkLoadLeadSeconds to build a newly requested chunk. A scoped grid's ChunkGridDefinition.Ring overrides the resulting ring for that grid.
InterestNearRadius
public float InterestNearRadius = 30f;Entities within this many metres of a client's pawn get every tick of the world-state stream.
InterestFarRadius
public float InterestFarRadius = 80f;Entities between the near and far radius get every InterestMidDivisor-th tick.
InterestMidDivisor
public int InterestMidDivisor = 4;Send every Nth tick for entities between the near and far radius (1 = every tick).
InterestFarDivisor
public int InterestFarDivisor = 12;Send every Nth tick for entities beyond the far radius (1 = every tick). Clients without a pawn yet get this rate for everything.
InterestHighTiers
public RelevanceTierBands InterestHighTiers;High-priority entities' own distance tiers. Without Override they get the tiers above one band better: every update out to InterestFarRadius, InterestMidDivisor beyond.
InterestLowTiers
public RelevanceTierBands InterestLowTiers;Low-priority entities' own distance tiers (a crowd, traffic, critters), so they can be slowed without slowing players. Without Override they get the tiers above one band worse. A divisor of 0 sends no updates in that band.
InterestBackgroundTiers
public RelevanceTierBands InterestBackgroundTiers;Background entities' own distance tiers. Without Override they get InterestMidDivisor inside InterestNearRadius and no updates beyond. A divisor of 0 sends no updates in that band.
InterpolationDelayTicks
public int InterpolationDelayTicks = 3;Render delay for remote entities, in ticks.
AdaptiveInterpolationDelay
public bool AdaptiveInterpolationDelay = true;Client: add to InterpolationDelayTicks what the world-state streams' measured lateness needs: the InterpolationJitterPercentileth percentile, over the last two seconds, of how many ticks late each packet arrived against the client's clock, taken per worker, highest worker first, rounded down. A clean stream adds nothing; a jittery link or a worker that runs behind gets the buffer it needs, so the interpolator does not run past its newest sample and snap back. The delay rises at once and falls a tick every half second. Off: the delay grows by the slowest worker's lag behind the newest stream, as before. Either way at most MaxStreamLagTicks.
InterpolationJitterPercentile
public float InterpolationJitterPercentile = 95f;Client: the percentile of packet lateness the adaptive render delay covers (AdaptiveInterpolationDelay), 50 to 100. Default 95.
MaxStreamLagTicks
public int MaxStreamLagTicks = 12;Client: the most ticks the measured stream lateness (or lag) may add to InterpolationDelayTicks. Default 12 (200 ms at 60 Hz); it was a fixed 6.
SlowUpdateMaxDelayTicks
public int SlowUpdateMaxDelayTicks = 30;The most extra render delay, in ticks, a client gives a remote entity whose state arrives further apart than the render delay (an entity updated every few ticks, or sent in a slow distance tier), so it interpolates across its own gap instead of being extrapolated past its newest state and snapping back. Entities sent every tick or two get none. 0 turns it off. See UpdateGapDelay and NetworkIdentity.UpdateGap.
InputLeadMarginTicks
public int InputLeadMarginTicks = 2;Extra ticks of input lead on top of half the measured RTT, before the adaptive adjustment.
InputLeadTargetTicks
public int InputLeadTargetTicks = 3;Lead (in ticks) the client tries to keep its inputs arriving at the worker with. Below this the client sends further ahead at once; well above it, it slowly relaxes.
InputLeadMaxAdjustTicks
public int InputLeadMaxAdjustTicks = 30;Upper bound on the adaptive input lead adjustment, in ticks.
SimulatedLatencyMs
public float SimulatedLatencyMs = 0f;Development only. Client: round-trip latency in milliseconds added to the link to the gateway (half each way). Ignored in release builds. -nebula-sim-latency overrides.
SimulatedJitterMs
public float SimulatedJitterMs = 0f;Jitter, in milliseconds, of the simulated link: each packet's delay varies by up to half this much either way. Development only.
SimulatedLossPercent
public float SimulatedLossPercent = 0f;Percent of packets the simulated link loses in each direction. Development only.
ReconnectFirstDelaySeconds
public float ReconnectFirstDelaySeconds = 1f;Client: seconds to wait after the connection drops before the first reconnection attempt.
ReconnectBackoffFactor
public float ReconnectBackoffFactor = 2f;How much longer each reconnection attempt waits than the one before. 1 keeps the delay fixed at ReconnectFirstDelaySeconds.
ReconnectMaxDelaySeconds
public float ReconnectMaxDelaySeconds = 2f;The longest the client waits between two reconnection attempts, in seconds.
ReconnectGiveUpSeconds
public float ReconnectGiveUpSeconds = 0f;Seconds after a drop at which the client stops reconnecting: it raises NebulaClient.ReconnectGaveUp, sets NebulaClient.WantsConnection to false and stays NebulaClient.State.Disconnected. 0, the default, never gives up. A value a little above SessionReclaimSeconds stops once the worker has let the pawn go.
ClientDisconnectTimeoutSeconds
public float ClientDisconnectTimeoutSeconds = 8f;Seconds without any packet from the gateway after which the client's transport declares the link lost and the client starts reconnecting. Lower detects a dead gateway sooner; too low drops players on a brief network stall. Must be well above ClientPingIntervalSeconds.
ClientPingIntervalSeconds
public float ClientPingIntervalSeconds = 0.5f;Seconds between the keep-alive pings the client's transport sends, which also measure the round trip.
ClientStallSeconds
public float ClientStallSeconds = 2f;Seconds without any state from the server (entity state, owner state, variables, RPCs, spawns) after which a client that is in the world raises NebulaClient.ServerStalled, while its link to the gateway is still up: the worker simulating the player has stopped without the orchestrator having declared it dead yet. It raises NebulaClient.ServerResumed when state arrives again. 0 turns the watch off. The watch assumes the server sends state continuously, as it does for a predicted pawn; a world that can go quiet for longer needs a higher value, or 0.
NetworkPrefabs
public List<GameObject> NetworkPrefabs = new List<GameObject>();Every prefab that can be spawned over the network. The index is the prefab id on the wire.
Properties
CostLinkBytesPerSec
public double CostLinkBytesPerSec { get; }CostLinkBudgetMbps in bytes per second; the default when it is 0 or less.
Methods
ServerFrameRateOf
public static int ServerFrameRateOf(NebulaConfig config);The frame rate a worker or gateway process runs at: ServerFrameRate, from 10 to 1000; 0 (the default) or a null config gives the tick rate.
Load
public static NebulaConfig Load();ToInterestSettings
public InterestSettings ToInterestSettings();
public InterestSettings ToInterestSettings(float worldCellSize);The resolved, clamped interest settings. Repairs are silent here — Validate is where they are reported — so that a role can start with values that work even when nobody is reading the log.
RawInterestSettings
public InterestSettings RawInterestSettings();The settings exactly as configured, before any repair. Validation works on this.
Validate
public void Validate(List<ConfigIssue> issues);
public void Validate(List<ConfigIssue> issues, float worldCellSize);Everything wrong with this configuration, worst last-resort first: an ConfigSeverity.Error is a value no clamp can rescue and start-up should stop on, a ConfigSeverity.Warning is a value that was repaired and will not behave as typed.
ResolveWorldCellSize
public float ResolveWorldCellSize();The world definition's cell size, or 0 when the game has no world definition. Everything that has to agree on one notion of "near": content streaming, the allocator ring, the container window a client is told about — derives from this and InterestSettings.NearCells.
ToInterestGrid
public InterestGrid ToInterestGrid();The interest grid this mesh uses: the resolved settings snapped onto the world's cells so a region never straddles a cell edge. Both ends derive it from this, which is what lets the worker reject a subscription built with a different one instead of filtering with ids that mean something else.