Skip to content

Tutorial: Writing Values with Setter

Where Reactor consumes values and dispatches reactions, Setter goes the other direction — it writes values into sinks. Settable values, DataStorage entries by Key, reference fields, any registered sink. One component, lifecycle-managed, all in the Inspector.

By the end of this tutorial you'll have a Setter that:

  • Copies a value from an asset into a DataStorage key on a schedule.
  • Drives a value smoothly over time (lerp / ease / spring).
  • Sets a value while active and restores it on end.
  • Accumulates a running total each frame.

Prerequisites: Basic familiarity with DataStorage, Keys, and the Process system.


Mental Model

A Setter hosts a list of ISetterEntry items. The primary entry is the typed Set <T> entry — one per value type (Set Float, Set Vector3, Set Int, Set Color, …). Each typed entry asks two things:

  1. What to set on — the sink: a settable value backed by a local field, an asset, a DataStorage key, or a component.
  2. How — the behaviour: Copy, Over Time, Scoped, or Accumulate.

The Setter component is the lifecycle host — on Begin it starts every entry's behaviour, on End it stops/undoes them all.

flowchart LR
    B1["Copy<br/>(source + schedule)"] --> E1["Set Float<br/>set on: Health key"]
    B2["Over Time<br/>(lerp / spring)"] --> E2["Set Vector3<br/>set on: Position field"]
    B3["Scoped<br/>(on begin / on end)"] --> E3["Set Color<br/>set on: Material asset"]
    E1 --> Sinks["sinks (local / asset / DataStorage / component)"]
    E2 --> Sinks
    E3 --> Sinks

1. Add the Setter

Create a GameObject (or use an existing controller). Add the Setter component.

Add Component → Jungle → Data → Setter

The Inspector shows an Entries list.


2. The Typed Set <T> Entry

  1. Click + on Entries → pick Set Float (or Set Vector3, Set Int, Set Color, …).
  2. targetwhat to set on. The picker surfaces every settable of that type: a local value, a Value asset (e.g. FloatValueFromAsset — sets into a shared ScriptableObject), a DataStorage key (e.g. FloatFromDataStorage), or a component field. This is the discoverable way to "set into an asset or a data storage".
  3. behaviourhow to set it. Four choices, next section.

The sink is an entry-level choice, so you can swap the behaviour without re-wiring where it writes.


3. The Four Behaviours

Copy — sample a source on a schedule

Reads a source and writes it into the sink each tick. The operation-based replacement for the old FloatValueSetter.

Field Value
target FloatFromDataStorage(PlayerStats, 'Health' key)
behaviour Copy
Copy → source FloatValueFromAsset(BaseHealth)
Copy → scheduler ExecuteOnce (default) / ExecuteEveryFrame / interval

Over Time — drive via the pipeline

Moves the sink toward a value gradually using the same pipeline engine behind every other "… Over Time" op (target → modifier chain → write, with completion / revert / pause). No scheduler — the pipeline ticks itself.

Field Value
target FloatFromDataStorage(PlayerStats, 'Health' key)
behaviour Over Time
Over Time → target Lerped Float 0 → 100, duration 1.5s, ease SineInOut
Over Time → modifiers (optional) smoothing, spring, noise, clamp — each with a blend factor

For a continuous "follow a moving source through a smoothing chain" instead of a finite tween, use a Value pipeline target with a smoothing modifier.

Scoped (While Active) — set on begin, undo on end

Writes a value when the Setter starts; on End either restores what was there before, or writes an explicit off value. Generalises the old "publish self while active" pattern to any type.

Field Value
behaviour Scoped
Scoped → onBeginValue the value to write while active
Scoped → restorePolicy RestorePrevious (default) or WriteOffValue
Scoped → offValue (shown when policy = Write Off Value)

Accumulate — add into the sink each tick

Adds the source onto the current sink value every tick (optionally scaled by frame time for a per-second rate). Counters, timers, fill bars. Additive types only (float/int/double/Vector3/Color).


4. Advanced: ScheduledOperationEntry (escape hatch)

When you need several writes on one shared schedule, or to drop arbitrary standalone operations into the Setter lifecycle, use Scheduled Operation Entry — it hosts a list of operations and one IExecutionScheduler. The typed Set <T> entries cover the common single-value cases; reach for this only for multi-op or non-value-set work.


5. Measurements → Measurer

Measurements are not Setter entries. To feed a DataStorage from a list of measurements, use the dedicated Measurer component (it owns all measurement sub-setters). The retired DataStorageSetter entry used to double as a measurement host — that role now lives solely in Measurer.


6. Setter, Measurer, Visualizer — The Family

Three sibling components in Jungle.Data. All inherit from ControllableComponent, so they share lifecycle and execution-frame behaviour.

Component What it does
Setter Sets values into sinks via typed Set <T> entries. The general case.
Measurer Dedicated host for measurement sub-setters feeding one DataStorage.
Visualizer Drives scene visuals (pooled spawners, layout) from data sources.

You can host all three on the same GameObject — they're independent lifecycle units. A common combo: a Measurer writes motion data into a DataStorage, a Setter drives derived values, a Visualizer spawns one cube per item in a list.


7. Execution Frames

Like every ControllableComponent, the Setter has an IExecutionFrame that decides when it begins and ends. Default: on enable / on disable. Swap to:

  • Mono Lifecycle Frame — bind to Start / OnEnable / OnDestroy / etc.
  • Event Frame — begin on one IEvent, end on another. Pair with EventFromAsset for cross-scene control.
  • Targeted Cycle Frame — bind to another component's cycle (an Attachable's Attached cycle, an Agent's Holding cycle).

The Setter's what (entries) is independent of when (the frame).


Next Steps