Skip to content

Instancer Nodes

Instancer nodes are terminal nodes that consume Point data and place objects in the scene. They do not output any port data. All nodes in this category use the purple node color (#993399).

Instancer nodes support two Instancing Modes: traditional GameObject instantiation and BRG (BatchRendererGroup) for high-performance GPU-instanced rendering. In GameObject mode, a staticFlags field (Unity's StaticEditorFlags) can be set to mark spawned instances as batching-static, contribute-GI, occluder/occludee, etc. When BatchingStatic is included, StaticBatchingUtility.Combine is invoked on the parent after spawning.


Common Concepts

Transform Offsets

All instancer nodes support a set of base transform fields that are applied on top of each point's existing transform matrix:

FieldTypeDefaultDescription
baseOffsetVector3(0, 0, 0)Local position offset applied in the instance's rotated space.
baseRotationVector3(0, 0, 0)Euler rotation offset in degrees applied after the point's own rotation.
baseScaleVector3(1, 1, 1)Scale multiplier. Use this to correct FBX import scale differences.

Weighted Instancer does not have a baseScale on the node — each WeightedPrefab entry has its own baseScale instead.

Material Property Mapping

Prefab Instancer and Weighted Instancer both expose a materialProperties array of PPGMaterialPropertyMapping entries. Each mapping reads a point attribute and writes it to a named MaterialPropertyBlock shader property on all Renderer components of the spawned instance.

This allows per-instance shader variation (e.g. driving a tint colour from the point's color field, or passing a noise attribute to a wind sway shader) without requiring separate prefab variants.

Parent To Component

When parentToComponent is true (the default), spawned GameObjects are parented under the PPGComponent's Transform. This allows the component to track and clean up instances on re-generation or scene unload via ManagedResources.

BRG Instancing Mode

Prefab Instancer and Weighted Instancer support a BRG instancing mode that uses Unity's BatchRendererGroup API for GPU-instanced rendering. Instead of creating individual GameObjects, BRG mode uploads instance transforms directly to a GPU buffer and renders them in minimal draw calls.

How It Works

  1. The prefab's MeshFilter and MeshRenderer are inspected at generation time.
  2. Mesh and material(s) are extracted automatically — including LODGroup prefabs (LOD0 is used) and multi-material prefabs (one draw command per submesh).
  3. Instances are partitioned into an XZ grid (default 32m cells, configurable via gridSizeOverride).
  4. Each grid cell becomes a separate BRG Batch. During rendering, a Burst-compiled culling job tests each cell's AABB against the view's cullingPlanes.
  5. Shadow passes use the same per-cell test but iterate each shadow cascade split independently, building a splitVisibilityMask so a cell in outer cascades is still drawn even when excluded from nearer ones. SRP-provided shadow planes are already extended toward receivers, so casters visibly affecting on-screen shadows remain included.
  6. Optional camera-pass distance culling (maxCullDistance) additionally rejects cells whose nearest bound is farther than the configured distance from the camera. Shadow passes are not affected by this setting.

BRG Eligibility

A prefab is BRG-eligible if it meets all of the following:

RequirementDetails
Single MeshFilter + MeshRendererOnly one renderer hierarchy (LODGroup with one renderer per LOD is OK)
No SkinnedMeshRendererSkeletal meshes are not supported
All materials non-nullEvery sharedMaterials entry must be assigned
DOTS Instancing shaderMaterials must use shaders with DOTS Instancing support (URP Lit / HDRP Lit in Unity 6 are compatible)

If a prefab is not BRG-eligible, the node automatically falls back to GameObject mode and logs a diagnostic message explaining why.

Grid & Distance Culling

FieldTypeDefaultDescription
gridSizeOverridefloat0BRG grid cell size in meters. 0 uses the default (32m). Smaller values improve culling granularity but increase batch count.
maxCullDistancefloat0Camera-pass maximum render distance in meters. 0 disables distance culling. Shadow passes are unaffected, so distant casters can still contribute shadows.

Limitations

  • No physics / colliders: BRG renders meshes only. Use GameObject mode for prefabs that need colliders or MonoBehaviour components.
  • No LOD switching: All instances render at LOD0. Distance-based LOD is planned for a future release.
  • No per-instance material animation: MaterialPropertyBlock is not used in BRG mode. Custom per-instance shader properties require the advanced PPGInstanceField API (planned).
  • Editor preview: BRG rendering works in both Play Mode and Edit Mode. After domain reload (script recompile), instances are automatically regenerated.

When to Use BRG

ScenarioRecommended Mode
Thousands of static meshes (grass, rocks, trees)BRG
Prefabs with physics collidersGameObject
Prefabs with custom MonoBehaviour logicGameObject
Nested procedural generation (inner graphs)PrefabGraphInstancer (always GameObject)

Prefab Instancer

Prefab Instancer

Category: Instancers
Description: Instantiates a single prefab at every input point.

Ports

DirectionNameType
InputInPoint

Settings

Prefab

FieldTypeDefaultDescription
prefabGameObjectnullPrefab to instantiate at each point. A warning is logged if unset.

Instantiation Mode

FieldTypeDefaultDescription
modeInstancingModeGameObjectGameObject: standard Instantiate. BRG: GPU-instanced rendering via BatchRendererGroup (see BRG Instancing Mode).
staticFlagsStaticEditorFlags0 (None)Editor-only. Static editor flags applied to spawned GameObjects in GameObject mode. Including BatchingStatic triggers StaticBatchingUtility.Combine on the parent after spawning.

Transform Offsets

FieldTypeDefaultDescription
baseOffsetVector3(0, 0, 0)Position offset in the instance's rotated local space.
baseRotationVector3(0, 0, 0)Euler rotation offset in degrees.
baseScaleVector3(1, 1, 1)Scale multiplier.

BRG Grid & Distance Culling

FieldTypeDefaultDescription
gridSizeOverridefloat0Grid cell size for BRG spatial partitioning. 0 = default (32m).
maxCullDistancefloat0Camera-pass maximum render distance in meters. 0 disables. Shadow pass is unaffected.

Parenting

FieldTypeDefaultDescription
parentToComponentbooltrueParent spawned GameObjects under the PPGComponent transform.

Material Properties

FieldTypeDefaultDescription
materialPropertiesPPGMaterialPropertyMapping[]Empty array ([])Per-instance material overrides. Each entry maps a point attribute to a shader property name via MaterialPropertyBlock.

Tips

  • GameObject mode + staticFlags.BatchingStatic reduces draw calls by combining spawned meshes via StaticBatchingUtility.Combine. Requires parentToComponent = true so the Combine call has a parent. Note that combined meshes lose per-instance transform mutation at runtime.
  • BRG mode provides the best performance for large instance counts. No GameObjects are created — rendering is handled entirely via GPU buffers. If the prefab is not BRG-eligible, the node automatically falls back to GameObject mode with a diagnostic log.
  • Cancellation is checked every 64 instances during execution to keep the editor responsive.
  • When parentToComponent is false, instances are not tracked by ManagedResources and must be cleaned up manually.

Prefab Graph Instancer

Prefab Graph Instancer

Category: Instancers
Description: Instantiates prefabs at each input point and, if the prefab contains a PPGComponent, automatically executes its inner graph.

This node enables nested procedural generation: the outer graph places parent prefabs, and each prefab's own graph generates content relative to its position.

Ports

DirectionNameType
InputInPoint

Settings

Prefab

FieldTypeDefaultDescription
prefabGameObjectnullPrefab to spawn. If it has a PPGComponent, that component's graph is automatically executed after instantiation.

Transform Offsets

FieldTypeDefaultDescription
baseOffsetVector3(0, 0, 0)Position offset in the instance's rotated local space.
baseRotationVector3(0, 0, 0)Euler rotation offset in degrees.
baseScaleVector3(1, 1, 1)Scale multiplier.

Parenting

FieldTypeDefaultDescription
parentToComponentbooltrueParent spawned GameObjects under the PPGComponent transform.

Binding Resolution

FieldTypeDefaultDescription
bindingResolveModePPGBindingResolveModeByNameThenTypeHow inner graph binding slots are resolved to components on the spawned instance. See enum table below.

PPGBindingResolveMode enum

ValueDescription
NoneNo automatic resolution. Bindings must already be configured inside the prefab.
ByNameThenTypeSearches for a child GameObject matching the slot name first (via Transform.Find), then falls back to GetComponentInChildren by type.
ByTypeOnlyResolves exclusively via GetComponentInChildren by the slot's binding type.

Inner Graph Execution

When a spawned instance contains a PPGComponent:

  1. The instance is created inactive to prevent Start() from triggering an early Generate() call.
  2. GenerateOnStart on the inner component is set to false.
  3. A deterministic seed is derived from WangHash(point.seed ^ contextSeed) and assigned to innerComp.Seed.
  4. Bindings are resolved according to bindingResolveMode.
  5. The instance is activated, Physics.SyncTransforms() is called to ensure colliders are ready, and innerComp.Generate() is invoked.

If the inner graph throws, a warning is logged for that specific point and execution continues with the remaining points.

If the prefab has no PPGComponent, the node falls back to behaving like a standard Prefab Instancer (activate and continue).

Recursion Limit

The node guards against infinite recursion. If nesting depth exceeds 4 levels, an error is logged and the node returns false. Avoid circular prefab graph references.

Tips

  • Inner graph seeds are deterministic: the same outer seed + point layout always produces the same inner layout.
  • ByNameThenType is recommended when prefabs have named sub-objects that match binding slot names (e.g. a Terrain child named "Terrain" matching a terrain binding slot).
  • A warning is emitted if a resolved binding target has no Collider component, since surface-sampling nodes (e.g. surface scatter) inside the inner graph will not function without a collider.
  • Spawned instances are tracked by the outer ManagedResources and are cleaned up when the outer component regenerates.

Weighted Instancer

Weighted Instancer

Category: Instancers
Description: Instantiates from a list of prefab entries, selecting which prefab to spawn per point using weighted random, float-range attribute mapping, or direct integer indexing.

Ports

DirectionNameType
InputInPoint

Settings

Instantiation Mode

FieldTypeDefaultDescription
modeInstancingModeGameObjectGameObject: standard Instantiate. BRG: GPU-instanced rendering via BatchRendererGroup (see BRG Instancing Mode).
staticFlagsStaticEditorFlags0 (None)Editor-only. Static editor flags applied to spawned GameObjects in GameObject mode. Including BatchingStatic triggers StaticBatchingUtility.Combine on the parent after spawning.

Selection

FieldTypeDefaultDescription
selectionModePPGWeightedSelectionModeRandomWeightAlgorithm used to pick an entry per point. See enum table below.
selectionAttributePPGAttributeSelectorDensityAttribute that drives selection in FloatRange and DirectIndex modes. Ignored in RandomWeight mode.

PPGWeightedSelectionMode enum

ValueDescription
RandomWeightPerforms a deterministic weighted random roll per point using WangHash(point.seed) ^ WangHash(contextSeed + pointIndex).
FloatRangeReads a [0, 1] float from selectionAttribute and maps it to weighted bands proportional to each entry's weight field.
DirectIndexReads an integer from selectionAttribute and uses it as a direct entry index (with modulo wrap-around).

Weighted Prefab Entries

entries is an array of WeightedPrefab structs:

FieldTypeDefaultDescription
prefabGameObjectnullPrefab to spawn for this entry. Entries with a null prefab are skipped.
weightfloat1.0Relative probability weight. Values are normalised internally to sum to 1.
baseScaleVector3(1, 1, 1)Per-entry scale multiplier applied to the spawned instance.

Transform Offsets (node-level)

FieldTypeDefaultDescription
baseOffsetVector3(0, 0, 0)Position offset in the instance's rotated local space.
baseRotationVector3(0, 0, 0)Euler rotation offset in degrees applied after point rotation.

Unlike the other instancer nodes, there is no node-level baseScale. Scale is controlled per-entry via WeightedPrefab.baseScale.

BRG Grid & Distance Culling

FieldTypeDefaultDescription
gridSizeOverridefloat0Grid cell size for BRG spatial partitioning. 0 = default (32m).
maxCullDistancefloat0Camera-pass maximum render distance in meters. 0 disables. Shadow pass is unaffected.

Parenting

FieldTypeDefaultDescription
parentToComponentbooltrueParent spawned GameObjects under the PPGComponent transform.

Material Properties

FieldTypeDefaultDescription
materialPropertiesPPGMaterialPropertyMapping[]Empty array ([])Per-instance material overrides mapped from point attributes to shader properties via MaterialPropertyBlock.

Consumed Attributes

When selectionMode is FloatRange or DirectIndex and selectionAttribute is a custom attribute, it is declared as consumed (IPPGAttributeConsumer).

Internal Weight Normalisation

Entry weights are normalised to a cumulative probability table at runtime:

cumulativeWeights[i] = sum(entries[0..i].weight) / totalWeight

The last entry is always clamped to exactly 1.0 to prevent floating-point drift. If totalWeight <= 0, a warning is logged and no instances are spawned.

Tips

  • In RandomWeight mode, each point's seed is combined with the graph's context seed and the point's index to produce a deterministic, reproducible selection even across multiple generate calls.
  • FloatRange mode is ideal for attribute-driven variety: e.g. use a Attribute Noise node to generate a density field, then map it to prefab bands (sparse undergrowth at low density, dense canopy at high density).
  • DirectIndex mode is useful when upstream nodes explicitly tag points with an integer category attribute created by a Create Attribute node.
  • Setting staticFlags to include BatchingStatic requires parentToComponent = true; StaticBatchingUtility.Combine is performed on the parent GameObject after all instances are placed.
  • BRG mode groups entries by (Mesh, Material[], layer, shadowCastingMode, receiveShadows) and creates separate BRG batches per group. Multi-material prefabs are supported (one draw command per submesh). If any entry is not BRG-eligible, the entire node falls back to GameObject mode.
  • Parameter expose (SupportsParameterExpose) is disabled for this node because per-entry weight values are not individually exposable as graph parameters.

Spline Mesh Deformer

Spline Mesh Deformer

Category: Instancers Description: CPU-side mesh deformation along a spline. Takes a prefab and tiles its mesh along the spline into uniformSegmentCount uniform segments. Shader-agnostic — works with any Material on URP, HDRP, and Built-in.

Inputs

PortTypeRequiredDescription
SplineSplineYesThe curve driving the deformation. Typically from Get Binding or Create Spline from Points.

Settings

FieldTypeDefaultDescription
prefabGameObjectnullPrefab with a MeshFilter + MeshRenderer in its children. LODGroup is supported (LOD0 used). Multi-submesh + multi-material prefabs are supported. The mesh must be Read/Write enabled.
forwardAxisVector3(0,0,1)Which axis of the source mesh points along the spline direction.
upAxisVector3(0,1,0)Which axis of the source mesh is "up" in its local space.
parentToComponentbooltrueParent the generated GameObject under the PPGComponent's transform.
staticFlagsStaticEditorFlags0 (None)Editor-only. Static editor flags applied to the spawned GameObject. Including BatchingStatic invokes StaticBatchingUtility.Combine on the parent afterwards.
uniformSegmentCountint8Number of uniform tile segments along the spline. Range 1–128.
baseScaleVector3(1, 1, 1)Scale applied to source mesh vertices before deformation. In post-axis-rotation space: X = cross-section width, Y = cross-section height. Z (spline-forward direction) is visually inert — use uniformSegmentCount to control tile count instead. Normals are compensated for non-uniform scale.
alphaEpsilonfloat1e-4Retained for serialization compatibility with older graphs; no longer read at runtime.
shadowCastingModeShadowCastingModeOnStandard MeshRenderer shadow setting.
receiveShadowsbooltrueStandard MeshRenderer shadow setting.
layerint0Layer of the spawned GameObject.

Behavior

  1. The node generates uniformSegmentCount + 1 normalised alphas [0, 1/N, ..., 1] along the spline. Each consecutive pair forms one segment; N segments from N+1 alphas.
  2. The prefab's mesh is cloned, tiled segmentCount times along the forward axis, and deformed so each tile occupies its corresponding [alpha_i, alpha_{i+1}] range on the spline.
  3. Per-vertex attributes (positions, normals, UV channels 0..3, colors) and all submesh triangle arrays are tiled. Normals + tangents are recomputed.
  4. A single GameObject with MeshFilter + MeshRenderer is spawned. The deformed Mesh clone is owned by a marker component so it is destroyed alongside the GameObject during PPG cleanup.

Tips

  • For the trivial "one mesh across the full spline" case, set uniformSegmentCount = 1 → a single segment spanning the full spline.
  • To place a pre-tiled 10m road mesh along a 100m spline without distortion, set uniformSegmentCount = 10 so each tile matches the mesh's forward length.
  • Deformation is Burst-compiled (IJobParallelFor) and runs on all vertices in parallel; large meshes remain responsive.
  • Uses Unity Splines' NativeSpline.Evaluate internally — no PTF accumulation, no shader required.

Terrain-conforming Meshes

To make a road/path follow terrain, build the driving spline from terrain-projected points:

Get Binding (SplineContainer)
  └─▶ Spline Sampler (ByCount = N)
        └─▶ Project To Surface (Terrain)
              └─▶ Create Spline from Points
                    └─▶ Spline Mesh Deformer

Create Spline from Points rebuilds a Spline whose knots sit on the terrain, and the Deformer's tile pipeline follows that new curve. See Create Spline from Points for options (tangent mode, closed loop, sort by attribute).

Procedural Placement Graph for Unity