Tutorial: Visualizing Data with Visualizer¶
Take a list-shaped data source — an inventory, a tagged DataStorage, a runtime collection — and project it onto the scene as actual GameObjects: one cube per item, one card per quest, one marker per waypoint. The Visualizer component owns that pipeline: spawn, populate, arrange.
By the end of this tutorial you'll have an inventory list whose contents appear as visuals in a row at runtime, regenerating whenever items are added or removed.
Prerequisites: Familiarity with Data, LayoutComponent, and pooled creators.
How Visualizer Fits¶
Visualizer is the "data → scene visuals" sibling of Setter ("data → sinks") and Reactor ("data → reactive bodies"). All three are ControllableComponents that host a list of entries.
flowchart LR
SRC["Data source<br/>(inventory, list,<br/>data storage)"]
VE["Visualizer Entry<br/>(observes the source)"]
SPAWN["Spawn a visual per item<br/>(via PooledObjectCreator)"]
POP["Populate the visual<br/>(bind item data to its children)"]
LAY["Arrange visuals<br/>(LayoutComponent or layout strategy)"]
SRC --> VE
VE --> SPAWN --> POP --> LAY
The entry watches a data source and keeps the scene visuals in sync — add an item, a visual appears; remove an item, a visual is reclaimed; reorder the source, the visuals rearrange.
1. Prepare a Pooled Visual¶
The visual is a prefab. Each item produces one instance.
- Create a prefab (e.g. InventoryItemVisual) representing a single visual. Give it a Renderer, a UI label, whatever you want to drive.
- Add a PoolObject component to the prefab root. This lets it participate in pooling.
- In your scene, add a PooledObjectCreator somewhere. Drop the prefab into its prefab field, set initialCount to a small pre-spawn count.
The Creator now hands out instances on demand and reclaims them when done.
Why pooled?
Visualizers add and remove visuals as the underlying data changes. Pooling avoids garbage spikes from instantiate/destroy churn.
2. Add the Visualizer¶
On your scene's "Inventory UI" GameObject (or any controller) add a Visualizer component.
Add Component → Jungle → Data → Visualizer
You'll see an Entries list. Each entry handles one "data → visuals" channel. We'll add one entry.
3. Configure the Entry¶
The available entry types depend on your data shape. A typical entry takes:
| Field | What it is |
|---|---|
| source | The data source to observe (e.g. an inventory, a list value, a DataStorage entry). |
| creator | The PooledObjectCreator that produces visuals. |
| populator | How to bind one item's data to a freshly-spawned visual's children (Text fields, Renderer color, etc.). |
| layout | How to arrange the spawned visuals (a LayoutComponent or an inline layout strategy). |
Wire your inventory source, the InventoryItemVisual creator, the populator that copies each item's name/icon into the visual, and a layout strategy that arranges them in a row.
Press Play and add an item to the inventory at runtime. A new visual appears at the next layout slot. Remove an item — the visual gets reclaimed back into the pool.
4. Layout: Where the Visuals Go¶
Visualizers don't position the visuals themselves — they delegate to a layout. Two common surfaces:
- Inline layout strategy on the entry — a layout strategy field (Linear, Grid, Circular, Fan, Stack) configured directly on the entry. Simpler when the layout belongs to this one Visualizer.
- Separate LayoutComponent — a standalone layout component pointed at the visuals. Useful when several systems share the same layout.
For the row of inventory items, an inline Linear layout strategy works:
| Field | Value |
|---|---|
| Direction | Right |
| Spacing | 1.5 |
| Origin | This GameObject's transform |
The visuals appear from the origin transform out, spaced 1.5 units apart.
5. Reorder, Remove, Replace¶
The Visualizer reacts to the source's change events:
- Item added → spawn a new visual, bind it via the populator, run layout.
- Item removed → reclaim the matching visual, run layout.
- Source reordered → leave instances in place, run layout (visuals shift to their new slots).
- Item replaced in place → re-populate the existing visual, don't respawn.
The mapping from item to visual is identity-based — the Visualizer keeps a dictionary, so the same item keeps its same visual instance across reorderings.
6. Visualize a Plain List¶
The Visualizer accepts any source that exposes a "list-shaped" interface — most commonly:
- An inventory (a list of typed items).
- A DataStorage with an "Items" key (list of GameObjects, list of typed values).
- A Detector mirrored through
IItemSource<GameObject>— visuals follow detected objects.
Pick the source type that matches your data and wire it the same way.
7. Per-Entry Lifecycle¶
Each entry begins and ends with the Visualizer. On End:
- Every active visual is returned to its creator's pool.
- The internal item-to-visual map clears.
- The next Begin re-snapshots the source and respawns fresh visuals.
This means turning the Visualizer off (or its execution frame ending) is a hard reset — anything in-flight ends cleanly.
8. Multiple Entries in One Visualizer¶
You can host many entries in one Visualizer for grouped "data → visuals" pipelines that share a lifecycle:
Visualizer
├─ Entry 1: Inventory items → row of cards
├─ Entry 2: Quest list → vertical sidebar
└─ Entry 3: Waypoint markers → world-space pins
All three start when the Visualizer begins, all three end together.
For independent lifecycles, use separate Visualizer components.
9. Visualizer vs Setter vs Reactor¶
| Component | Direction | Typical sink |
|---|---|---|
| Setter | Data → typed values / DataStorage | Settable values, keys, ref fields. |
| Reactor | Data → reactive bodies | Process bodies that react to triggers. |
| Visualizer | Data → scene visuals | Pooled GameObjects with bound children, arranged by a layout. |
All three are siblings — same lifecycle host, same execution-frame model, picked based on what kind of consumer you need on the right side.
Next Steps¶
- Setter tutorial — pushing values into sinks.
- Reactor tutorial — running reactive bodies.
- LayoutComponent reference — standalone layout.
- PooledObjectCreator reference — the visual factory.
- Visualizer reference — full API.