Nebula
World partition

RuntimeGrid

Maps runtime containers to a planar or three-dimensional grid.

generated from the sources
public sealed class RuntimeGrid

Maps runtime containers to a planar or three-dimensional grid. Provides a stable 64-bit id per cell, cell bounds in the current floating-origin frame, and neighborhood queries.

Each id packs three signed 21-bit coordinates. Keep this format stable because container leases and persisted entities use these ids to identify cells.

Constructors

RuntimeGrid

public RuntimeGrid(float cellSize);
public RuntimeGrid(Vector3 cellSize);
public RuntimeGrid(Vector3 cellSize, bool planar);
public RuntimeGrid(Vector3 cellSize, bool planar, string scopeKey);

Fields

MinCoordinate

public const int MinCoordinate = -(1 << 20);

Coordinates outside [MinCoordinate, MaxCoordinate] on any axis cannot be packed into a runtime id.

MaxCoordinate

public const int MaxCoordinate = (1 << 20) - 1;

Properties

CellSize

public Vector3 CellSize { get; }

Size of one cell in meters, per axis.

Planar

public bool Planar { get; }

Cells are columns: the grid has a single layer at y = 0 and CellSize.y is the column's height, centered on absolute y = 0. Surface worlds want this — a chunk that is 64 m wide and 512 m tall is one container nothing ever leaves vertically, so verticality never costs a cell, a lease, or a neighborhood dimension. The packing is unchanged (y is simply always 0), so a planar and a volumetric grid produce the same ids for the same coordinates.

ScopeKey

public string ScopeKey { get; }

The scope this grid's chunks belong to: "" is the public world, anything else a scope activated with ScopeKind.Grid. It is what makes chunk (x,y,z) of two worlds two different containers: it goes into every id this grid hands out (IdOf).

InstanceId

public ulong InstanceId { get; }

The 64-bit isolation id of ScopeKey (ScopeKeys.Hash); 0 for the public world.

IsPublic

public bool IsPublic { get; }

Whether this is the public world's grid, whose ids are the pinned packing and nothing else.

GridKey

public string GridKey { get; }

The key this grid is registered under (NebulaChunks.GridFor) and its chunk ids derive from (IdOf). A scope's root grid's is its ScopeKey; a hosted grid's is its own, distinct from the scope it lives in (docs/container-tree.md D22).

HostContainerId

public string HostContainerId { get; }

The container a hosted grid's chunks are leased under, by id: a container with a physics frame of its own, typically a carrier's (a planet, a station). Null for a scope's root grid, whose chunks are roots.

IsHosted

public bool IsHosted { get; }

Whether this grid is hosted by a container (docs/container-tree.md D22) rather than being its scope's root grid: its chunks are children of HostContainerId, its coordinates are the host's own (carrier-local), and its Frame follows the host's floating origin.

Geometry

public IChunkGridGeometry Geometry { get; }

The grid's shape: which cell a point is in, each cell's box, its neighbours and its id. A root grid's is always a ChunkLattice of CellSize; a hosted grid's may be any IChunkGridGeometry a game supplies (NebulaChunkedWorld.HostedGeometry), and every hosted-grid answer below goes through it.

Host

public Container Host { get; }

A hosted grid's host container in this process, or null while it is not here (a carrier not spawned or not yet seen) or for a root grid. A planar grid makes its host's frame keep its origin level (PhysicsFrame.KeepOriginLevel), and the frame's origin shifts are this grid's (ScopeFrame.Shifted).

LeadStep

public float LeadStep { get; }

How far apart the allocator samples a pawn's lead line (IChunkGridGeometry.LeadStep).

Frame

public ScopeFrame Frame { get; }

This grid's floating-origin frame: WorldOrigin for the public world, and a frame of its own for every other scope. Every piece of arithmetic below is relative to it, which is what lets two scopes on one worker both sit near Unity's origin (docs/scope-frames.md). A hosted grid's frame follows its host's floating origin (ScopeFrame.IsFollowing): its ScopeFrame.OriginOffset turns the host's own coordinates into simulation space and back, on a worker and on a client while it predicts; a client draws the host where it is (PhysicsFrame.ToParent).

Methods

From

public static RuntimeGrid From(ChunkGridDefinition definition, string scopeKey);

The grid a ChunkGridDefinition describes, for the scope it was activated under.

Hosted

public static RuntimeGrid Hosted(ChunkGridDefinition definition, string scopeKey, string gridKey, string hostContainerId, IChunkGridGeometry geometry = null);

A grid hosted by a container (docs/container-tree.md D22): chunks of definition's size leased as children of hostContainerId, laid out in the host's own coordinates, in scope scopeKey, with ids derived from gridKey and the coordinate. A planar one is a single layer of columns centred on the host's y = 0. The scope key must not be empty (the public world hosts no grids) and the grid key must not be any scope's key. geometry replaces the lattice the definition describes with a shape of the game's own (a cube-sphere's faces); its cell size then only sizes the grid's frame. NebulaChunkedWorld.ActivateHostedGrid makes one on every worker; build one directly only for a custom allocation workflow.

TryHostPosition

public bool TryHostPosition(NetworkIdentity entity, out Vector3 local);

A hosted grid: the position of entity in the host's own coordinates, wherever it is (in a chunk of this grid, in the host's frame at any depth, or outside the host altogether). False when the host is not in this process, or for a root grid.

CoordOfAbsolute

public Vector3Int CoordOfAbsolute(Vector3 absolute);

Which cell a position in this grid's absolute coordinates falls in: the scope's absolute world for a root grid, the host's own coordinates for a hosted one. No floating origin enters into it.

AbsoluteCenterOf

public Vector3 AbsoluteCenterOf(Vector3Int coord);

Centre of a cell in this grid's absolute coordinates (the host's own, for a hosted grid). A planar grid's column is centred on y = 0.

AbsoluteBoundsOf

public Bounds AbsoluteBoundsOf(Vector3Int coord);

A cell's box in this grid's absolute coordinates (the host's own, for a hosted grid).

PlacementOf

public ContainerPlacement PlacementOf(Vector3Int coord);

The placement a chunk's lease row carries: a root at its absolute centre (in double) for a root grid, a leased child of the host at its centre in the host's coordinates for a hosted one.

PartIdOf

public string PartIdOf(Vector3Int coord);

The part id a chunk's lease row and its records carry: c/x/y/z, after the grid key for a hosted grid.

IdOf

public ulong IdOf(Vector3Int coord);

This grid's runtime container id for a chunk: the pinned packing in the public world, the scope's derivation (ChunkKeys.RuntimeId) in every other scope. The one place a chunk id is made; PackId stays public-world only and stays pinned.

ContainerIdOf

public string ContainerIdOf(Vector3Int coord);

This grid's control-plane container id for a chunk (rt_ and IdOf).

TryCoordOf

public bool TryCoordOf(ulong id, out Vector3Int coord);
public bool TryCoordOf(PersistedEntityRecord record, out Vector3Int coord);

The chunk an id names in this grid, or false when the id is not this grid's. Always true for the public grid (every 64-bit value unpacks to a coordinate); for a scoped grid it is true for a chunk this process has named or adopted from a lease row (Adopt). The overload that takes a PersistedEntityRecord places a saved entity from its record's part id (PersistedEntityRecord.PartId), adopting the id as it goes, so it works in a process that never named the chunk; it is false for a record of another scope, in no runtime container, or inside a carrier.

Adopt

public bool Adopt(ulong id, string partId, out Vector3Int coord);

Learn the coordinate of a chunk this process never asked for, from the part id its lease row carries (InstanceContainerInfo.PartId). Returns false when the part is not a chunk of this grid, which is how an instance's interior part is told apart from a chunk.

TryFindCoordNear

public bool TryFindCoordNear(ulong id, Vector3Int around, int radius, out Vector3Int coord);

Find the chunk of this grid named by id by trying every coordinate within radius cells of around: a square in the y = 0 layer for a Planar grid, a cube otherwise. Use it for a scoped chunk id this process never named and no record or lease row explains, such as a record saved before PersistedEntityRecord.PartId existed, when the game keeps an approximate position for it. On a match the grid learns the id, as Adopt does.

The search goes outward ring by ring and stops at the first match. It computes one id per coordinate: (2r+1)² for a planar grid and (2r+1)³ for a volumetric one, each a short string hash, so keep the radius to what the hint's error needs. An id the grid already knows is answered from what it knows, wherever the chunk is; the public grid unpacks the id and reports whether the chunk is within the radius. False for a negative radius, or when no coordinate in range matches.

Owns

public bool Owns(Container container);

Whether a container is a chunk of this grid: same scope, and an id this grid can place.

IsValid

public static bool IsValid(Vector3Int c);

Whether a coordinate is within the range that PackId can represent.

PackId

public static ulong PackId(Vector3Int coord);

Pack a grid coordinate into a stable 64-bit runtime container id: three signed 21-bit fields, x in the high bits. The known values are pinned by RuntimeGridTests because ids are already persisted; this packing must never change.

UnpackId

public static Vector3Int UnpackId(ulong id);

Inverse of PackId.

CoordOf

public Vector3Int CoordOf(Vector3 framePosition);
public Vector3Int CoordOf(NetworkIdentity entity);

Which cell a position in this grid's own floating-origin frame falls in.

CenterOf

public Vector3 CenterOf(Vector3Int coord);

Centre of a cell in the current floating-origin frame. A planar grid's column is centered on absolute y = 0 (the origin never shifts vertically in a planar world), so its box spans ±CellSize.y/2 around the ground plane rather than sitting above it.

BoundsOf

public Bounds BoundsOf(Vector3Int coord);

Box of a cell in the current floating-origin frame.

BoundsOfId

public Bounds BoundsOfId(ulong id, Bounds fallback);

BoundsOf of the cell a packed runtime id names. Matches the ContainerRegistry.RuntimeBoundsInFrame delegate signature; see UseAsRuntimeBounds.

IsNear

public static bool IsNear(Vector3Int a, Vector3Int b, int ring);

Chebyshev (ring) distance between two coordinates, independent of cell size.

Neighborhood

public static IEnumerable<Vector3Int> Neighborhood(Vector3Int center, int ring);
public void Neighborhood(Vector3Int center, int ring, List<Vector3Int> into);

Every valid coordinate within ring cells of center on every axis (a cube).

Normalize

public Vector3Int Normalize(Vector3Int coord);

Drop the vertical component of a coordinate when this grid is Planar, so a caller's arithmetic cannot leave the single layer.

UseAsRuntimeBounds

public void UseAsRuntimeBounds();

Point ContainerRegistry.RuntimeBoundsInFrame at this grid, so a game that registers runtime containers by PackId'd coordinate can use this grid as the bounds hook. Games with their own container shape keep using the hook directly; this is purely opt-in and touches nothing else. Call once at boot, and clear (ContainerRegistry.RuntimeBoundsInFrame = null) on shutdown if another hook should take over.

ShiftOriginTo

public static void ShiftOriginTo(Vector3Int target);

Opt-in floating-origin policy for a grid world: shift the origin to target (a no-op when it is already there, or when no runtime world is loaded), suspending enabled CharacterControllers on entities of runtime containers across the shift and syncing physics transforms after. PhysX controllers must be reinserted at the new pose, not sweep over the shift. Call from the game's own update once it has decided where the origin belongs, or use KeepOriginNear for the usual policy. On a client the physics frames are posed again at once (PhysicsFrames.PoseForRender), so what stands in them moves with the origin.

ShiftOrigin

public void ShiftOrigin(Vector3Int target);

Move this grid's origin to target. The public world's frame is the process's (the streamer moves the authored cell scenes with it), so that case is ShiftOriginTo unchanged. A scoped grid owns its frame: only that scope's containers, the entities in them, their state history and interpolation buffers move, and no other scope on this worker notices (docs/scope-frames.md D3). What stands inside a physics frame keeps its simulation pose, which is the frame's (docs/container-tree.md D19); on a client the frames are posed again at once (PhysicsFrames.PoseForRender), so what stands in them is drawn with the origin.

KeepOriginNear

public void KeepOriginNear(NetworkIdentity entity, int ring = 1);
public void KeepOriginNear(Vector3Int cell, int ring = 1);

Keep the floating origin within ring cells of entity — the usual policy for a client following its local player. Shifts through ShiftOriginTo when the entity leaves that ring around WorldOrigin.Cell, and does nothing otherwise.

On this page