Multi-values in the Emitter Guide

Multi-values in the Emitter Guide

Almost every number you see in the Emitter Guide — a starting size, a speed, a color — is a value: something the editor computes for each particle. A value starts out as a single row (a fixed number, a random range, a graph over the particle's life …), but it does not have to stay that simple. This page describes how a value grows into a multi-value: several rows combined by an expression, with rows that can themselves be multi-values.

From a single value to rows

Every value shows an S button at its right edge while it is in its simple, single form. Press it — or pick Switch to Multi-Value from the value's type menu — and the value becomes a list of rows:

  • Each row is a full value of its own, with its own type (Fixed, Random, a graph, and the rest) picked from its type button.
  • Each row has a one-letter name (a, b, c …) shown at its left.
  • The expression line at the bottom combines the rows into the final result, referring to them by those names — a * b, lerp(a, b, c), a + vec2(0, b) and so on.
  • The + button on the expression line adds another row; the trash button on a row removes it.

The S button on the last remaining row collapses the value back into its simple form.

Two ready-made templates

Almost every multi-value people build by hand turns out to be one of two shapes: a value scaled by a number, or a value offset by one. The type menu therefore offers them directly, right under Switch to Multi-Value:

  • a * b — switch to a multi-value, add a second row holding 1, and set the expression to a * b.
  • a + b — the same, with the expression a + b.

Either entry does in one click what would otherwise take four steps (switch, add a row, type the number, type the expression). Your existing value becomes row a untouched; the new row b starts at 1, ready to be changed to whatever multiplier or offset you actually want — and since 1 leaves a product unchanged, picking a * b never alters how the effect looks until you edit that number.

The same two entries appear in a row's type menu inside a multi-value. There they nest that row and apply the template inside it, matching what Switch to Multi-Value does on a row.

Rotation (R) values do not offer these templates: multiplying a rotation by a plain number is not a meaningful operation, so the entries would only produce an expression the editor marks as invalid.

Nesting: a row that is a multi-value

A row of a multi-value can itself be switched to a multi-value, from the same Switch to Multi-Value entry in the row's type menu. The nested level appears inline under its row, indented, with rows and an expression line of its own — so a value like "a base size, times a variation that is itself randomized per particle" can be built entirely in the Guide, without touching the Emitter Scheme.

A few things to know:

  • Levels nest up to four deep. The menu entry is simply not offered where a value does not allow nesting, or the depth limit is reached.
  • A nested level that has real structure — several rows, or an expression — is framed by a pair of thin vertical lines, so where one level ends and the next begins stays readable even a few levels down. A nested level holding a single plain row stays as light as an ordinary row.
  • The S button on the nested level's own row collapses the level back into a plain row (its expression is discarded; the surviving row's value is kept).
  • Undo and redo treat every step of this — nesting a row, growing a level, collapsing it — like any other edit.

Whole levels can be copied and pasted: copying a nested level puts the entire level on the clipboard, and it can be pasted into any row that accepts one. See Emitter Guide presets, which also covers copying single values between rows.

The Noise value

Any 3D value slot offers a Noise type in its type menu. The value becomes a 3D noise field sampled at a point you choose:

  • Input — a nested value: the 3D point the noise is sampled at. It defaults to the particle position, so nearby particles get similar noise and the effect reads as a coherent field; but it is a full multi-value — replace it with a fixed point, an emitter property, an expression over several rows, or anything else.
  • Smoothness — the size of the noise pattern in space: bigger values give broader, slower-changing noise.
  • Anim. speed — a 3D velocity that slides the noise field through space over time, so the noise "boils" even for particles that stand still.
  • Scale — a nested 1D value multiplying the output range. The raw output spans [-1; 1] per component; the scale stretches it.

A typical use is a per-particle color or size variation driven by where the particle is: pick Noise on the slot, keep the particle-position input and tune the smoothness until the pattern reads at your effect's scale. Under the hood the value drives a Noise3 scheme block; its remaining parameters (interpolation type, additive mode, output range bounds) keep their defaults and can be edited in the Emitter Scheme if needed.

Over Value: one graph, any X

A graph value gives you a curve to draw: the editor reads a Y off the curve and uses it as the value. What decides where on the curve it reads is the X — and with the Over Value type, X is a value you build yourself.

Pick Over value… from a value's type menu and the value shows two things:

  • Edit Graph… — opens the curve editor, the same one every graph uses.
  • X — a value of its own. It is a full value: give it a type from its type button, switch it to a multi-value, nest levels inside it, write an expression over several rows.

While X is a simple one-line value — a time source, a custom value, a number — it sits inline on the same row as the button, after an X: label, and the whole graph value reads as a single row, just like the classic over particle life graphs always did. Build something bigger in X (several rows, a nested value, an expression) and it expands into its own X block under the button; trim it back to one line and it folds back in.

Four value types exist to be dropped into that X slot, and read as plain numbers wherever else you use them:

  • Particle Life — the particle's age from 0 (just born) to 1 (about to die).
  • Particle Time — seconds since the particle was generated.
  • Emitter Time — seconds since the emitter started. For an emitter attached to another emitter's particle, time counts from when that parent particle was born.
  • Effect Time — seconds since the effect started.

Because X is an ordinary value, it is not limited to those. Drive the curve by the particle's speed, by a custom value your game sets, by an expression mixing several sources — anything a value can be.

The familiar graphs, now one click away

The type menu still lists Over particle life, Over particle time, Over particle speed, Over emitter time, Over system time and an entry per custom value. They are shortcuts: each one creates an Over Value with its X already filled in for you. Everything after that is the same value, so a graph started as Over particle life can have its X edited into something else later, without recreating it.

The type button's icon and the checkmarks in the menu follow what actually drives X, not how the value was created. Build an X by hand that happens to match a shortcut and the menu shows that shortcut ticked — it is the same value either way.

Graphs saved with earlier versions of the editor open as Over Value with their X already set to whatever they used to run over, curves and all. Nothing needs converting, and effects keep exporting exactly as before.

Values decided at birth

Some values are computed once, when a particle is born, and stay put for the particle's whole life — the starting size, the maximum lifetime, the steady rotation axis. For these, the editor freezes the value's final result on the particle: one stored property per value, created only when the value actually varies from particle to particle. A value that is the same for every particle (all rows fixed) stores nothing at all. This keeps the per-particle state of exported effects small no matter how many rows and nested levels the value uses.

Values that are recalculated every frame — movement, forces, a color over the particle's life — instead offer a per-row storage toggle (the padlock on the row), which freezes that row's result at birth when you switch it on. Row types that only make sense frozen (Random) have it switched on for you; types that only make sense live (a graph over the particle's life) have it off. The rest is your choice.