The spawner
A population-authoring subsystem, not a random scatter. Its job is to generate variety inside constraints you authored, and then write down exactly what it did.
Why constrained placement#
Uniform random placement is easy and almost useless. It puts crates inside walls, people on roofs and pallets halfway through a forklift, and a detector trained on floating barrels learns floating barrels.
Hand-placing is the other extreme: physically plausible and impossible past a few dozen frames.
The spawner sits between them. You draw the volume and declare the rules; it fills the volume subject to spacing, slope, exclusion and ground contact, and reshuffles for every frame.
What a population is made of#
asset pools what may be placed
spawn zones where it may go
placement domains how positions are chosen inside a zone
numeric distributions how many
spatial distributions how they are spread
clusters structured local groups
relative rules placement anchored to other objects
inter-class distances relationships between populations
nested groups multi-object units
representations how each placement is realised in the engine
Each of these has its own page below. All of them end up in the same place: a spawn manifest per frame recording what was requested, what was placed and what was refused.
Native placement domains#
Four, and they answer different questions about where inside a zone a position comes from.
| Domain | Positions come from | Typical use |
|---|---|---|
surface | Sampling the zone and resolving onto the ground | Floors, terrain, yards, open regions |
grid | Cells of a lattice across the zone | Shelving, warehouse layouts, parking |
spline | Points along a path | Vehicles on roads, queues, cones along a route |
navmesh | Projection onto navigable space | Anywhere a character could actually stand |
Current semantics are projection-based: sampled positions are projected onto navigation. That is genuinely useful, and it is not the same as statistically uniform sampling over navmesh polygon area. A projection that fails is a rejection with a reason, not a silent fallback to somewhere arbitrary.
Spacing, grounding, collision and orientation#
Four contracts apply to every placement regardless of domain.
spacing center | footprint
grounding bounds_bottom | pivot
collision disabled | bounds
orientation upright_random_yaw | preserve | fixed | random_euler
align_surface_normal | spline_tangent | face_target
Spacing and collision covers the first three in detail. Orientation is worth one line each:
upright_random_yaw— the sane default for objects that stand up.preserve— keep the asset's authored rotation.fixed— one declared rotation for every placement.random_euler— full random rotation, for objects with no natural up.align_surface_normal— lie along the surface underneath.spline_tangent— face along the path, for vehicles and queues.face_target— point at the target zone, for anything that should be looking at the subject.
An unsupported collision mode is an error rather than being quietly treated as
bounds. A placement rule that cannot be honoured should fail loudly at
authoring time, not produce a dataset that silently ignored it.