The interface and parameters
A graph’s interface is its set of named inputs and outputs: the parameters and triggers that cross the graph boundary. On a Sound Graph the interface is your scripting surface - what game code reads and drives. On a Sub Graph it becomes the node’s pins when you place it.
You build the interface in the Interface panel of the graph editor. This page covers the member types, how they behave, and how a value flows in and out.
Signal domains
Section titled “Signal domains”Every wire and every interface member belongs to one of three domains:
- Audio - sound. Audio members are buses; they are allowed only on Sub Graphs (a Sound Graph’s interface is values and triggers, not audio).
- Float - a block-rate control value: a number that updates once per audio block. Most member types live here, including vectors and matrices.
- Trigger - a named event.
A fourth kind, Sample Set, is a binding reference rather than a live signal: it names content, latched at bind points, not carried on a wire.
Mixing widths
Section titled “Mixing widths”A Float wire carries a scalar or a Vector 2/3/4, and connecting mismatched widths is never an error - the value adapts on read, the same rule Shader Graph uses:
- Scalar into a vector input - the scalar splats: every lane gets that one
value (a scalar into a Vector 3 reads as
(x, x, x)). - Narrow vector into a wider input - the missing lanes read 0 (a Vector 2
into a Vector 3 reads as
(x, y, 0)). - Wide vector into a narrower input - the extra lanes are truncated (a
Vector 3 into a scalar input reads just
x; into a Vector 2,(x, y)).
Dynamic-width nodes (most of Math) resolve their own width from what you wire in, so a chain of scalars stays scalar and a chain fed a Vector 3 goes wide.
Member types
Section titled “Member types”Add a member with the typed + button. A Sound Graph offers value members, Trigger and Sample Set; a Sub Graph additionally offers Audio.
| Type | Domain | Notes |
|---|---|---|
| Float | Float | Continuous scalar, smoothed by default. Optional Unit tag (Hz/dB/st) and array Length. |
| Bool | Float | Snaps to 0 or 1, no smoothing. |
| Int | Float | Integer in [Min, Max], rounds on set, no smoothing. |
| Enum | Float | Integer ordinal with labels from a bound C# enum. |
| Time | Float | A duration. The Unit tag (Seconds or Beats) labels how you author and read the number; it does not convert. The member stores a raw value, and a consumer interprets it - a delay in seconds, or a beat count resolved against a transport (Musical timing) - because only the consumer knows the tempo context. |
| Vector 2/3/4 | Float | Multi-component value; per-element smoothing. |
| Trigger | Trigger | A named event; fire it, do not set it. |
| Audio | Audio | An audio bus (Sub Graph only). |
| Sample Set | Sample Set | Rebindable content for a Wave Player. |
Each member also has a Description field for documentation, and value members have a Smooth time that controls how fast a change glides to its new value.
Range (Min / Max)
Section titled “Range (Min / Max)”A range is a design decision about the member, not something Audity imposes - “this cutoff runs 200 Hz to 8 kHz” - and it exists only when you author one. A member with Max at or below Min declares no range: values pass through untouched, and the inspector shows a plain field rather than a slider. New members start that way, so setting a Cutoff to 8000 works before you have thought about bounds at all.
Declare a range and it holds everywhere: a SetFloat outside the bounds is
clamped into them, and the AuditySource inspector shows the member as a slider
between them (the graph editor’s own value fields stay plain fields). It bounds what
the game may set - never what the graph itself computes, so an
Out member is not clamped at all.
An Enum member’s labels come from a C# enum you tag with [AudityEnum]. Bind
one in the member’s Enum Type dropdown and the member takes that enum’s
labels and its 0..N-1 range. The enum’s values must be contiguous (0, 1, 2, …);
the runtime value is the ordinal, and from code you pass (int)MyEnum.Value as a
float.
Direction
Section titled “Direction”Every member has a Direction, and it means “who writes it”.
In is the game’s to write: SetFloat, Trigger, a placement input pin on a
Sub Graph. This is the default and the common case.
Out is the graph’s to write, and the game reads it back. On a Sub Graph an Out member is a placement output pin, written by a Parameter/Trigger/Audio Out node inside. On a Sound Graph it is the read half of the scripting interface - see Reading a graph from code.
Reading a member inside the graph
Section titled “Reading a member inside the graph”Drop a member’s chip onto the canvas - the drag is the whole gesture; interface nodes are not in the creation menu:
- A value member becomes a Parameter In node - its Float output is the member’s live value.
- A trigger becomes a Trigger In node - its output fires when the trigger fires.
- A Sample Set becomes a Sample Set node you wire into a Wave Player’s source.
Writing a Sub Graph output
Section titled “Writing a Sub Graph output”Inside a Sub Graph, write an Out member with a Parameter Out, Trigger Out, or Audio Out node. The value then appears on the Sub Graph node’s output pin in the parent.
Reading a graph from code
Section titled “Reading a graph from code”The traffic runs both ways. A member whose Direction is Out is written inside the graph and read by the game, which is how a value the DSP computes - an Envelope Follower’s level, a Compressor’s gain reduction, a Noise Gate’s Open - reaches gameplay.
Wire the value into a Parameter Out node naming the member, then poll it:
if (source.TryGetFloat("Level", out float level)) muzzleFlash.intensity = level * 4f;
// Or with a fallback, when branching is not worth it:float level = source.GetFloat("Level");An Out Trigger member works the same way in the other direction: fire it with a Trigger Out node and the game is called back.
void OnEnable() => source.TriggerFired += OnGraphTrigger;void OnDisable() => source.TriggerFired -= OnGraphTrigger;
void OnGraphTrigger(AudityParameterId id) { /* a beat, a gate opening, ... */ }An Out member with an Array Length greater than 1 is read the same way, all elements at once. Wire a wide value - a Spectrum Analyzer’s bands, say - into a single Parameter Out naming the member, and one connection fills every element:
readonly float[] m_Bands = new float[8]; // reused; GetFloats does not allocate
void Update(){ int count = source.GetFloats("Bands", m_Bands); for (int i = 0; i < count; i++) { /* m_Bands[i] is band i, low to high */ }}GetFloats returns how many elements it filled, so a shorter member fills only
its own and leaves the rest of the array untouched. A scalar wire into an array
member’s Parameter Out writes only the element its Element Index names - it does
not splat across the whole array. (A Vector member does splat, because setting a
Vector3 from one value meaning x=y=z is what an author expects.)
What read-back is and is not. A read value is a snapshot, as of the engine’s last report - roughly a frame old, the same way a network-replicated value is. Nothing crossing the audio thread can be instantaneous without stalling it. Every trigger fire is delivered and the count is reliable, but its timing is approximate for the same reason. So:
- Do drive gameplay, animation, VFX and UI from it.
- Don’t build anything sample-accurate on it. If a reaction has to line up with the audio exactly, keep the reaction inside the graph, where the value already is.
Read-back costs nothing on a graph that declares no Out members - no members, no reporting.
Only the root graph’s own members are visible to code. Member names are one shared namespace across a graph and every Sub Graph it pulls in, so a Sub Graph’s Out member is a real value with a real name - but it is that module’s internal wiring, not this sound’s public interface, and it is never reported to script. To publish something a Sub Graph computes, wire its output pin to a Parameter Out naming a member on the root graph’s own blackboard.
Because the namespace is shared, giving a Sub Graph member the same name as a root member makes them the same value, not two. If their Directions disagree the compiler warns: whichever side writes it will overwrite the other.
What the editor and compiler will not let you get wrong. Out members carry a few rules, all of them enforced rather than left to be discovered:
- A range never clamps a value the graph writes. Min/Max says what the game may set and what the inspector slider spans; on an Out member neither applies, so the fields are not offered and the engine does not clamp. A gain reduction in dB reads back as dB. (See Range - ranges are opt-in for every member, not just Out ones.)
- The game cannot set an Out member.
SetFloaton one is refused with a warning instead of being applied and then overwritten by the graph a millisecond later. - A Parameter Out or Trigger Out naming an In member is reported. That node is dropped from the compile entirely, so without the warning it would simply do nothing, quietly.
- An Out member nothing writes is reported, rather than reading its default forever, and so is a value with two Parameter Outs writing it, where which one you read would depend on node order.
Driving parameters from code
Section titled “Driving parameters from code”From the game, you set value members and fire triggers on a playing instance through the Audity Source component:
source.SetFloat("Cutoff", 8000f);source.SetBool("Muffled", true);source.Trigger("Footstep");Values set this way are sticky per source: they apply to the live instance
immediately (gliding over the member’s Smooth time) and are re-applied to every
future Play(). Triggers fire the named Trigger In. For the full API, including
vectors, matrices, per-frame fast paths and global parameters, see the
Scripting guide.