Tutorial: Arranging GameObjects with Layout¶
Take a set of GameObjects and snap them into a row, a grid, a circle, a fan — anywhere on demand. A Layout Command does it: its Arrange step pulls subjects from one source, slots from another, and snaps each subject's transform to its slot.
By the end of this tutorial you'll have a circle of pooled markers that re-arrange themselves whenever the underlying data changes.
Prerequisites: Familiarity with the Process system and Process Component.
How Layout Works¶
Three pieces:
- A subject source (
ILayoutSubjectSource) — what to arrange. Could be a list of GameObjects, a pool's active items, the children of a transform. - A slot source (
ILayoutSlotSource) — where to put them. A grid layout strategy, a circle strategy, a list of explicit Transforms. - The Arrange step — resolves both, snaps each subject's transform to its matching slot.
flowchart LR
SS["Subject Source<br/>(what to arrange)"]
SL["Slot Source<br/>(where to put them)"]
LC["Arrange step<br/>(Layout Command)"]
R["Subjects snapped<br/>to slots"]
SS --> LC
SL --> LC
LC --> R
The Process Component hosting the command begins on its execution frame (default: on enable) and arranges once. To re-arrange when data changes, begin it again from a Reactor, event or signal, or put the Layout Command straight into that reaction's process.
1. Add a Layout¶
Create a GameObject named MarkerLayout.
Add Component → Jungle → Spatial → Layout
This adds a Process Component running a Layout Command with one Arrange step. Its fields:
- Subjects — the subject source.
- Slots — the slot source.
- Origin — the object slot strategies anchor their slots to. Defaults to Context, the object the component sits on.
- Apply Scale — write
localScalefrom each slot (default on), or leave scale untouched.
2. Wire the Subject Source¶
Pick what to arrange. The picker shows the available ILayoutSubjectSource types:
- From List — explicit list of GameObjects.
- From Container — pulls items from an
IItemContainer<GameObject>. - From Pool — every currently-active instance of a PooledObjectCreator.
- From Children — every immediate child of a Transform.
- From Detector — every currently-detected GameObject.
For this tutorial pick From Pool and reference your PooledObjectCreator that produces markers.
3. Wire the Slot Source¶
Pick a layout strategy. Common ones:
| Strategy | Arrangement |
|---|---|
| Circular | Even spacing around a circle in a plane. |
| Linear | Row or column along an axis. |
| Grid | Rows × columns. |
| Fan | Arc with configurable angle range. |
| Stack | Vertical stack with offset per item. |
| Explicit | A list of Transforms — slot N is transforms[N]. |
For this tutorial pick Circular:
| Field | Value |
|---|---|
| Radius | 3 |
| Plane | XZ |
| Start Angle | 0 |
| Direction | Clockwise |
Press Play. The pool's active markers snap to evenly-spaced positions on a 3-unit circle around MarkerLayout.
4. Re-Run on Data Changes¶
Two common patterns:
From a Reactor¶
Add a Reactor on the same GameObject. Set its source to whatever drives the data change (the pool's "item added" event, an inventory's change signal). Put a Layout Command with an Arrange step in its process, or a step that begins the MarkerLayout Process Component again.
Automatically via a Visualizer¶
Use a Visualizer with a layout strategy directly on its entry. The Visualizer reruns layout automatically after every add/remove/reorder. This is the higher-level pattern when the GameObjects you're arranging are themselves visualized from data.
5. Inspecting Resolved State¶
Watch the Arrange step in the Monitor window. It draws the slots the last run used in the Scene view and counts them, and its Layout Now button arranges right away, in edit mode too, with undo.
Useful for debugging mismatches ("I asked for 8 markers but only 6 are showing").
6. Layout vs Layout Strategy¶
Subtle but useful distinction:
- A layout strategy is a recipe — "circle, radius 3, in XZ". Just data.
- The Arrange step is what pulls subjects, resolves slots from the strategy, and writes the result.
The same layout strategy types appear in:
- A Layout Command's Arrange and Spawn steps.
Visualizerentries (inline layout).- Octoputs's BatchTransformPipelineManager (batch-friendly variants).
Authoring a new strategy means implementing one interface; it then works in every host.
7. Vary Slots Along a Shape With Attributes¶
A shape can carry named values on its points, like point attributes in Houdini. Anything that reads one gets the points around it blended: along a line or curve, the two points on either side; across a surface, every point, the nearest counting most.
- Select the shape and open Attributes. Click Add Attribute, name it (for example
size) and pick its type: a number, a Vector3 or a color. The default is what the shape reads while it has no points. - Click Add Point, or on a curve Add a Point on Each Curve Point. Set each point's values. Points placed on curve points follow them when you move the curve, and a curve point you add gets its own attribute point with the value blended there.
- On the Shape slot source, set Scale By Attribute to
size. Each slot's scale is multiplied by the size where it sits, so objects grow and shrink along the shape.
To drive anything else, use the Shape Attribute value in any number or Vector3 field. It reads the attribute where the shape is closest to a position you give it, for example the object's own position.
Attribute points show in the Scene view as pink markers with their values. Drag a free one to slide it along the shape.
- Name the attribute and pick its type.
- Add points and set each point's value.
- Type the attribute name in Scale By Attribute.
8. Use Cases¶
- Card hand — Fan strategy, every card a subject, the player's hand transform as origin.
- Marker grid — Grid strategy, every spawn point a subject.
- Inventory row — Linear strategy, every inventory item a subject (visualized through a Visualizer that re-runs the layout).
- Orbiting satellites — Circular strategy, every satellite a subject. Add a Reactor that re-triggers layout on each frame to make them spin (or rotate the Layout's own transform).
Next Steps¶
- Layout Command reference — full field list.
- Process Component reference — when the layout runs.