Tutorial: Arranging GameObjects with LayoutComponent¶
Take a set of GameObjects and snap them into a row, a grid, a circle, a fan — anywhere on demand. LayoutComponent is the standalone Begin/End-driven component that does it: pulls subjects from one source, slots from another, 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 ControllableComponent.
How LayoutComponent 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 Layout's PerformLayout — 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["LayoutComponent<br/>(PerformLayout)"]
R["Subjects snapped<br/>to slots"]
SS --> LC
SL --> LC
LC --> R
The Layout begins on its execution frame (default: on enable) and runs PerformLayout once. To re-arrange in response to data changes, drive PerformLayout from a Reactor / event / signal — or hook the layout into a Visualizer that calls it after each change.
1. Add the LayoutComponent¶
Create a GameObject named MarkerLayout. Add the LayoutComponent.
Add Component → Jungle → Data → Layout
Fields:
- subjects — the subject source.
- slots — the slot source.
- origin — a reference transform that slot strategies can use to anchor their slots. Defaults to this component's transform.
- applyScale — write
localScalefrom each slot (default true), or leave scale untouched. - OnLayoutBegin / OnLayoutEnd — UnityEvents fired around each
PerformLayoutcall.
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 the LayoutComponent's transform.
4. Re-Run on Data Changes¶
PerformLayout is public — call it anytime the data changes.
Two common patterns:
Manually 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). Wire the body to call LayoutComponent.PerformLayout().
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¶
After each PerformLayout:
ResolvedSubjects— list of GameObjects the Layout placed.ResolvedSlots— list ofTransformDataslots used.
Useful for debugging mismatches ("I asked for 8 markers but only 6 are showing") and for writing diagnostic gizmos.
6. Layout vs Layout Strategy¶
Subtle but useful distinction:
- A layout strategy is a recipe — "circle, radius 3, in XZ". Just data.
- The LayoutComponent is the runtime host that pulls subjects, resolves slots from the strategy, and writes the result.
The same layout strategy types appear in:
- Standalone
LayoutComponent. Visualizerentries (inline layout).- Octoputs's BatchTransformPipelineManager (batch-friendly variants).
Authoring a new strategy means implementing one interface; it then works in every host.
7. 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 calls PerformLayout).
- 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 LayoutComponent's transform itself).
Next Steps¶
- Visualizer tutorial — automatic data → visuals → layout pipeline.
- LayoutComponent reference — full property list.
- ControllableComponent reference — execution-frame model.