Skip to content
Streaming a World

Streaming a World

This guide covers three roles: the tech artist who authors the streaming graph, the designer who tunes and deploys it, and the developer who drives it from code.


The streaming rule

The key concept behind world streaming is simple: any node that reads World Position is evaluated fresh for every chunk, using that chunk’s world-space origin. Any node that does not read World Position computes once and the result repeats across all chunks.

The WorldInputNode outputs the chunk’s origin as a float3. Wire it into a node’s position input and that node becomes chunk-aware. Leave it disconnected and the node runs once during the first evaluation and its output is reused.

This rule is what makes endless terrain work: height noise is world-positioned so every chunk gets a unique patch, but a mesh you load stays the same everywhere.


Tech artist: authoring a streaming graph

Which scatter nodes follow world position

Set these nodes to Position mode and they will re-sample at each chunk’s location:

  • Grid Scatter (Position mode): places points on a regular grid aligned to the chunk’s world position, so adjacent chunks tile seamlessly.
  • Density Mask (Position mode): samples a density texture using world-space UV, giving consistent density bands across chunk boundaries.
  • Splat Filter (Position mode): reads a splat map at world-space coordinates, so biome boundaries hold their shape across chunks.
  • Mesh Selector and Random Setter nodes (Position mode): use world-space position as a seed, so the same world location always picks the same mesh or value regardless of which chunk covers it.

Poisson scatter and chunk borders

Poisson (ScatterPoissonNode) runs an independent Bridson pass inside each chunk. It does not share state with neighbouring chunks. This means two trees near a chunk border can sit closer together than the minimum spacing. This is a known limitation: Poisson guarantees minimum spacing within a chunk, not across chunk borders.

When seam-free scatter is important, prefer Grid Scatter in Position mode, which tiles by construction.

Checking for seams with the 3x3 preview

The graph window has a Single / 3x3 toggle in the preview toolbar. Use it before deploying a streaming graph:

  1. Author the graph with the toggle on Single to get fast iteration.
  2. When the graph looks right in isolation, switch to 3x3. The eight neighbouring chunks evaluate in spiral order (cardinal neighbours first, then diagonals) so seams appear immediately if they exist.
  3. Look for visible lighting creases, height discontinuities, or scatter gaps at tile edges.
  4. Switch back to Single to iterate, then re-check at 3x3 before finalising.

Switching from 3x3 back to Single is instant: the centre tile’s result is already cached.

Minimal endless terrain recipe

This is the shortest graph that produces continuous, world-positioned terrain:

World Position
    → Plane (at chunk size)
    → Transform by World Position
    → Height Displace (normalMode: Field)
    → Geometry Output

What each node contributes:

  • World Position: outputs the chunk’s world-space origin. Everything downstream that reads this value becomes chunk-aware.
  • Plane (at chunk size): generates a flat mesh sized to one chunk. The chunk size is exposed as a parameter so the designer can tune it without opening the graph.
  • Transform by World Position: moves the plane to the chunk’s origin. Without this the plane stays at the world origin and all chunks overlap.
  • Height Displace: displaces vertices by a noise function. With normalMode set to Field, normals are computed from the noise gradient rather than vertex positions, so there are no shading seams at chunk edges even when noise values happen to align.
  • Geometry Output: hands the mesh to the streaming system.

To add trees, wire a Scatter node from the terrain geometry into a second output path and connect it to a Scatter Output node. Poisson distribution works well for organic placement; use Grid in Position mode when you need consistent density.


Designer role: tuning and deploying

Setting up the scene

  1. Find the Infinio World prefab in the project and drop it into your scene.
  2. Select the InfinioWorld GameObject. In the Inspector you will see the graph asset slot and the exposed parameters for the streaming graph (chunk size, noise scale, amplitude, and so on).
  3. Assign the endless terrain graph asset to the slot.

You do not need to open the graph to change values. All exposed parameters are live: adjust the amplitude slider and the preview updates immediately.

Live preview in play mode

Press Play. The InfinioWorld component starts evaluating chunks around the camera. The status line at the bottom of the Inspector shows:

  • Chunks live: how many chunks are currently rendered.
  • Chunks queued: how many are waiting to be built.
  • ms/chunk: how long the last chunk took to evaluate. Values above roughly 30 ms may cause visible pop-in on fast camera movement.

If ms/chunk is high, reduce chunk resolution (smaller subdivision count on the Plane node) or simplify the noise stack. Both are exposed parameters, so no graph editing is required.

Setting seed and view distance

The Seed parameter on the graph controls the noise character for the entire world. Change it to get a different world. The View Distance parameter on the InfinioWorld component controls how many chunks ring the camera at any moment.


Developer role: driving from code

InfinioWorld drives a BurstGraphEvaluator through the IChunkGeometryEvaluator interface. Each chunk request is a single Burst job call that returns geometry and scatter spawn points together. Only one chunk is in flight at a time; the component queues requests and dispatches them in order.

For API details see the scripting reference.

Overriding chunk size and seed at runtime

var world = GetComponent<InfinioWorld>();
world.ChunkSize = 64f;
world.WorldSeed = 42;
world.Rebuild(); // discards the current chunk cache and re-streams from scratch

Call Rebuild() whenever you change a property that affects the world’s shape. Changes to parameters that only affect appearance (material, colour) can be applied with world.RefreshMaterials() without a full rebuild.

Precision envelope

The coordinate system is single-precision float. At roughly 10 to 20 km from the world origin, vertex positions lose sub-centimetre precision and small gaps or shading artefacts may appear. For worlds larger than this, offset the world origin to follow the camera (the classic large-world technique) and keep all chunk origins inside the envelope.