Pepper.SFX
All Guidance pages

Guidance / API reference

AudioManager

Namespace: AudioSystem Inheritance: MonoBehaviour (partial class) Access: Singleton via AudioManager.Instance

Inspector Configuration

The core AudioManager fields. Occlusion-related inspector fields (slot pools, ray count, smoothing taus) live in the AudioManager Slot Pool API section. Reverb-sends fields live in the AudioManager Reverb-Sends API section.

Lifecycle

Field Default Description
persistAcrossScenes true On: DontDestroyOnLoad, as before 3.1 (the manager must be a root object), and a second manager removes its whole GameObject. Off: no DontDestroyOnLoad; the manager and its voices belong to its scene, and a second manager removes only its own component, with a warning. Read as PersistAcrossScenes.

The voices and every coroutine Pepper runs live on “AudioVoices”, a root object of Pepper’s own (kept or scene-bound like the manager, destroyed with it), so switching the manager’s GameObject or a parent off changes nothing.

Audio Configuration

Field Default Description
masterMixerGroup null Optional master mixer group handle. Not directly routed by AudioManager; exposed for project-side scripts.
masterVolume (range 0–1) 1 Global linear volume multiplier applied to every voice. Combines with per-bus volumes.
muteAll false Global mute switch. When ON, every voice’s output is forced to zero.

Voices

Field Default Description
maxRealVoices 32 Maximum voices playing through real AudioSources at once. Beyond this, the least important plays are kept virtual, a whole play at a time, and made real again when they matter more. Pepper warns at startup if this is above Unity’s own Max Real Voices.
maxVirtualVoices 64 Maximum virtual voices tracked behind the real-voice cap. Real + Virtual is the budget: when it is full, a new play makes room by ending whole plays (never persistent ones), or is skipped if it can’t.
stealHeadroom 4 Spare AudioSources beyond Real + Virtual, for stolen sounds still fading out.
stealFadeSeconds 0.025 How long a stolen sound that can be heard fades out (pool steals, Max Instances steals, a Switch’s Restart), never fewer than three frames; 0 = the old cut (3.1.0-dev.8). Read and set as StealFadeSeconds.
stealDeclickSeconds 0.005 With stealFadeSeconds 0 only: how far ahead on the DSP clock a stolen voice is cut.
voiceUpdateInterval 0.1 Seconds between voice priority / virtualization passes (default 10 Hz).
spatialMode Unity Who pans and attenuates 3D sounds: Unity, or Pepper from every listening point (3.1.0-dev.8). See Listening Point Methods.
updateMode Automatic When Pepper’s per-frame step (parameter ramps, Blend layers, virtual voices) runs. See UpdateMode / Tick.

Occlusion / LOD

Field Default Description
occlusionMask ~0 Physics layer mask used by the occlusion raycast. The rays ignore trigger colliders, and AudioZone/AudioPortal make their colliders triggers when authored, so their layer doesn’t need excluding.
occlusionUpdateInterval 0.2 Seconds between OcclusionUpdate ticks (raycast cadence, default 5 Hz). Per-frame smoothing handles the in-between.
enableLOD true Voice virtualization: once more than maxRealVoices (or a bus’s MaxRealVoices) would be heard, the least important plays (distance × volume × the priority’s weight, from a play’s loudest voice) are virtualized, a whole play at a time. Off = nothing is virtualized for the budget (a Blend’s Silent Layers still are).
lodDistances {10, 25, 50, 100} Not used in this version; hidden in the inspector. There are no distance tiers.

See the slot-pool subsection for occlusionRayCount, occlusionRaySpreadMeters, occlusionGainSmoothingSeconds, occlusionCutoffSmoothingSeconds, voiceMixer, occlusionLayout, and defaultOcclusionSlotsPerBus. See the reverb-sends subsection for reverbSendBusRegistry and reverbSendsUpdateInterval.


Properties

Instance

public static AudioManager Instance { get; }

Description: Singleton instance of AudioManager. Returns: The active AudioManager in the scene.

Inert

public static bool Inert { get; set; }

Description: For a dedicated server: set it once at boot, before any AudioManager starts. While true, every post (AudioEvent.Post, PostMultiPosition, AudioManager.Post / PostEvent, AudioEmitter.Post) returns one shared, already-finished handle without allocating or logging, with an AudioManager or without one; an AudioManager that starts builds no voices, coroutines or per-frame step (it still becomes Instance and loads the event registry); the manager’s parameter, switch and RTPC calls do nothing; the ambient system doesn’t create itself. Setting it while an AudioManager runs warns and keeps the value. False again at the start of each play session. See USER_GUIDE §17.11.

PersistAcrossScenes

public bool PersistAcrossScenes { get; }

Description: The persistAcrossScenes setting (see Lifecycle above), read in Awake.


Event Methods

PostEvent

public AudioHandle PostEvent(string eventName, GameObject source = null, Vector3 position = default)

Description: Triggers an audio event by name.

Parameters:

  • eventName - Name of the event to trigger (must exist in registry or Resources/Audio/Events/)
  • source - (Optional) GameObject to attach sound to
  • position - (Optional) 3D world position for spatial audio

Returns: AudioHandle for controlling playback, or null if event not found.

Example:

AudioHandle handle = AudioManager.Instance.PostEvent("Play_Explosion");
AudioHandle handle2 = AudioManager.Instance.PostEvent("Play_Footstep", gameObject, transform.position);

GetEvent

public AudioEvent GetEvent(string eventName)

Description: Gets an AudioEvent by name.

Parameters:

  • eventName - Event name

Returns: AudioEvent, or null if not found.

GetEventContainer

public AudioContainer GetEventContainer(string eventName)

Description: Gets the first container referenced by an event.

Parameters:

  • eventName - Event name

Returns: AudioContainer, or null if not found.


Posting by Reference

public AudioHandle Post(AudioEvent audioEvent, AudioEmitter emitter)
public AudioHandle Post(AudioEvent audioEvent, AudioEmitter emitter, string point)
public AudioHandle Post(AudioEvent audioEvent, AudioEmitter emitter, PostValues values)
public AudioHandle Post(AudioEvent audioEvent, AudioEmitter emitter, string point, PostValues values)
public AudioHandle Post(AudioEvent audioEvent, AudioEmitter emitter, Vector3 localOffset, PostValues values)
public AudioHandle Post(AudioEvent audioEvent, AudioEmitter emitter, double startDsp, double startOffsetSeconds,
                        PostValues values = default)
public AudioHandle Post(AudioEvent audioEvent, GameObject source = null, Vector3 position = default)

Description: Post an event you hold a reference to: the same as audioEvent.Post(emitter), audioEvent.PostAtOffset(emitter, localOffset, values) (an impact at the contact point), audioEvent.Post(emitter, startDsp, startOffsetSeconds, values) (a moment of the sound at a DSP time) and audioEvent.Post(source, position); see AudioEvent Post and PostValues. Returns null (with a warning) when audioEvent is null. Write Post(evt) rather than Post(evt, null): a bare null matches both overloads.

Random Numbers

public AudioRandomSource RandomNumbers { get; set; }   // Pepper (default) or Unity

Description: Where sounds get random numbers (Random containers’ picks, a Sequence’s random order, volume and pitch randomization, multi-position offsets). Pepper: a sound posted on an AudioEmitter draws from that emitter’s own sequence (its RandomSeed), other sounds from one shared Pepper sequence; UnityEngine.Random’s state is never touched. Unity: UnityEngine.Random, as before 3.1. Inside a networked post’s AudioRandomScope, UnityEngine.Random is used (seeded, then put back) either way, so every machine picks the same variation.


Parameter Methods

Parameters are explained in USER_GUIDE Manual §3.4. These methods use the global scope: every sound with no emitter or play value reads it. Per-emitter values are on AudioEmitter, per-play values on AudioHandle. The string RTPC methods below are the same global values addressed by name: a name and an AudioParameter asset with that Parameter Name share one value.

SetParameter / ClearParameter / GetParameter / SnapParameter

public void SetParameter(AudioParameter parameter, float value)
public void ClearParameter(AudioParameter parameter)
public float GetParameter(AudioParameter parameter)
public void SnapParameter(AudioParameter parameter)

Description: Set, forget, read or snap the global value. Sounds follow a value set through the asset with the parameter’s smoothing; the first one is heard at once. GetParameter returns what sounds hear now (after smoothing), else the default, clamped to the parameter’s range. ClearParameter falls back to the default, easing there if smoothed. SnapParameter skips the smoothing now. SetParameter tells IRTPCListeners the written value, by the parameter’s name; ClearParameter doesn’t. A write outside the range is stored as written and logs one warning per parameter. A value that isn’t a number (NaN, an infinity) is refused at every scope and by SetRTPC, ramps and PostValues too: sounds keep the last value, listeners aren’t told, and the parameter warns once.

RampParameter

public void RampParameter(AudioParameter parameter, float target, float seconds)

Description: Move the written global value to target over seconds (unscaled time, linear), from the value written before (else the default). Smoothing applies on top. A new ramp, a Set, a Snap or a Clear on the same parameter replaces it. Listeners are told every frame it moves.

SetRTPC

public void SetRTPC(string parameterName, float value)

Description: Set the global value of the parameter named parameterName. Every sound without an emitter or play value follows it at once: values set by name are never smoothed, even if a Parameter asset of that name is. Blend layers pick it up in Pepper’s per-frame step later in the same frame. Ends a TransitionRTPC running on the same name. Registered IRTPCListeners are told at once, inside the call.

Parameters:

  • parameterName - Parameter name (case-sensitive)
  • value - Parameter value. A name has no range of its own; a Blend that names it reads it clamped to 0–1.

Example:

AudioManager.Instance.SetRTPC("CombatIntensity", 0.75f);
AudioManager.Instance.SetRTPC("EngineRPM", 0.5f);

GetRTPC

public float GetRTPC(string parameterName)

Description: The global value set under this name, as written (not smoothed, not clamped).

Returns: The value, or 0f if none has been set. A Parameter asset’s default does not apply here.

TransitionRTPC

public void TransitionRTPC(string parameterName, float targetValue, float duration)

Description: Moves the global value to a target over time (unscaled, linear), starting from GetRTPC. A second call on the same name replaces the first, and so does SetRTPC; before 3.1 both transitions kept running and fought. States with a transition time use this.

Parameters:

  • parameterName - Parameter name
  • targetValue - Target value
  • duration - Transition duration in seconds (0 or less = SetRTPC)

Example:

AudioManager.Instance.TransitionRTPC("CombatIntensity", 1.0f, 2f);

GetAllRTPCs

public IReadOnlyDictionary<string, float> GetAllRTPCs()

Description: Every global value that has been set, by name and as written: values set with SetRTPC and global writes through Parameter assets. A live, read-only view. Enumerating it allocates, so use it in tools, not per frame. Writing a value while enumerating doesn’t throw.

Returns: Parameter names mapped to their global values.

RegisterRTPCListener / UnregisterRTPCListener

public void RegisterRTPCListener(IRTPCListener listener)
public void UnregisterRTPCListener(IRTPCListener listener)

Description: Registers/unregisters an object to receive callbacks when a global value changes: SetRTPC, SetParameter, and every frame of a TransitionRTPC or global RampParameter. Called synchronously. Emitter and play values don’t notify.

Example:

// Implement IRTPCListener
public class MyComponent : MonoBehaviour, IRTPCListener
{
    void OnEnable() => AudioManager.Instance.RegisterRTPCListener(this);
    void OnDisable() => AudioManager.Instance.UnregisterRTPCListener(this);

    public void OnRTPCChanged(string parameter, float value)
    {
        if (parameter == "EngineRPM") UpdateEngine(value);
    }
}

Listening Point Methods

public AudioListeningPoint AddListeningPoint(Transform follow = null)
public void RemoveListeningPoint(AudioListeningPoint point)
public IReadOnlyList<AudioListeningPoint> ListeningPoints { get; }
public void SetPrimaryListeningPoint(AudioListeningPoint point)   // null = the first registered (3.1.0-dev.8)
public AudioListeningPoint PrimaryListeningPoint { get; }          // 3.1.0-dev.8
public AudioSpatialMode SpatialMode { get; set; }                  // Unity (default) | Pepper (3.1.0-dev.8)
public void DriveUnityListener(AudioListener listener)    // null stops it
public AudioListener DrivenUnityListener { get; }

Description: Tell Pepper where the game listens from (see AudioListeningPoint). While any point is registered the scene is never searched; with none, Pepper falls back to the scene’s AudioListener (see ListenerUtil). Points stay registered if the manager is replaced. A point whose followed transform is destroyed is removed, with one warning a session (since 3.1.0-dev.8; it used to stay where it last was).

The primary point (3.1.0-dev.8): the one the game picks with SetPrimaryListeningPoint, else the first registered. DriveUnityListener moves an AudioListener to it in every step, before Unity mixes, so Unity’s 3D panning hears from the same place (skipped when the listener is on the transform the point follows); ListenerUtil.Get / GetPosition, the ambient system and SingleEmitter posts read it; with Spatial Mode = Unity it is the only point Pepper listens from. Picking another doesn’t make sounds jump: what Pepper measures from it (the built-in Distance, Approach Speed and Angle, so Doppler and the curves on them; attenuation filters) glides to the new one over 100 ms. A point that isn’t registered is refused, with a warning.

SpatialMode (3.1.0-dev.8; inspector: Spatial Mode). Unity (the default): Unity’s 3D from its AudioListener, as before; weights and pan widths are unused. Pepper: every 3D voice plays at Spatial Blend 0 and Pepper sets its level (GainStack.SpatialGain) and panStereo from every point each frame. For each point, the voice’s attenuation there (its Attenuation asset’s volume curve, else Unity’s rolloff for its Min and Max Distance) × the point’s Weight is its contribution; the level is the largest, the pan Σ contribution × PanWidth × the point’s pan ÷ Σ contribution, eased over about 50 ms. At one point of weight 1 and width 1 it reproduces Unity’s 3D (rolloffs, constant-power pan, Spread; measured on 6000.0 and 6000.3). Each play is measured from the point that hears it loudest (changing only when another is 1 dB louder): its built-ins, Doppler, attenuation filters, occlusion rays, the Furthest steal. It goes virtual past Max Distance only from every point. Doppler is always Pepper’s (a container on Unity’s gets Pepper’s at its Doppler Level). Levels ease over 100 ms after the points change. No spatializer plugins; the project’s Doppler Factor isn’t read; a stereo clip is balanced, not placed. A change applies to the sounds started after it. USER_GUIDE §9.3.

Example:

var point = AudioManager.Instance.AddListeningPoint(mainCamera.transform);
// ... when the camera is destroyed:
AudioManager.Instance.RemoveListeningPoint(point);

UpdateMode / Tick

public AudioUpdateMode UpdateMode { get; set; }   // Automatic (default) | Manual
public void Tick()

Description: When Pepper’s per-frame step runs. In order: parameter ramps and smoothing (global, then emitters, then plays); bus parameter curves; the emitters and listening points (velocities, DriveUnityListener), with voices that follow their emitter moved to it; every dynamic play’s tree (Blend layer levels, curves, pitch follow, switches); with Spatial Mode = Pepper, every 3D voice’s level and pan; then virtual voices’ positions, the fade around virtualization and the steal fade. Automatic runs it once a frame from a PlayerLoop step just before PostLateUpdate.UpdateAudio, after every LateUpdate, so values set anywhere in this frame’s game code are heard this frame. It starts with the frame after the manager’s Awake. Manual runs it only when you call Tick(), once a frame after your last write; ramps advance by Time.unscaledDeltaTime. Calling Tick() in Automatic mode advances ramps twice. Inspector field: Update Mode.


Switch Methods

SetSwitch

public void SetSwitch(string group, string value)
public void SetSwitch(AudioSwitchGroup group, string value)

Description: Sets the GLOBAL value of a switch group: every sound with no value of its own (handle) and none on its emitter reads it. A name and an AudioSwitchGroup asset with that name are one switch. A value not in the asset’s Values warns once; a group Driven By a parameter ignores it, with one warning (by name, only when the asset is loaded).

Parameters:

  • group - Switch group name (e.g., “Surface_Type”) or asset
  • value - Switch value (e.g., “Metal”, “Wood”)

Example:

AudioManager.Instance.SetSwitch("Surface_Type", "Metal");
AudioManager.Instance.SetSwitch(surfaceType, "Metal");   // the same switch, through its asset

ClearSwitch

public void ClearSwitch(AudioSwitchGroup group)
public void ClearSwitch(string group)

Description: Forgets the global value: sounds read the group’s Default Value (a Switch that only names its group: none, so its Default Container).

GetSwitch

public string GetSwitch(string group)
public string GetSwitch(AudioSwitchGroup group)

Description: By name: the global value set, or empty string if not set. By asset: what a sound with no handle or emitter value reads (the global value, else the Default Value; for a driven group, what the parameter’s global value gives).

GetAllSwitches

public IReadOnlyDictionary<string, string> GetAllSwitches()

Description: Gets all current switch values.

Returns: Dictionary mapping switch groups to their current values.


State Methods

SetState

public void SetState(string stateName, float transitionTime = 0.5f)

Description: Activates an audio state; the group’s previous state ends. A state whose VolumeMode is Offset moves its buses by its dB values (their StateOffsetDb), and the previous state’s offsets go back, over transitionTime (unscaled, in Pepper’s step). A SetLevel state (the default) sets the buses’ Volume and puts nothing back, as before.

Parameters:

  • stateName - Name of state to activate
  • transitionTime - Duration of transition in seconds (default: 0.5s)

Example:

AudioManager.Instance.SetState("Underwater", 1.5f);
AudioManager.Instance.SetState("Paused", 0.3f);

ClearState

public void ClearState(string stateGroup, float transitionTime = 0.5f)

Description: Leaves stateGroup’s state without setting another (3.1.0-dev.7): an Offset state’s bus offsets go back over transitionTime; a SetLevel state’s changes stay. The group has no active state afterwards.

SetStateInGroup

public void SetStateInGroup(string stateGroup, string stateName, float transitionTime = 0.5f)

Description: Sets a state within a specific state group.

Parameters:

  • stateGroup - State group name
  • stateName - State name within that group
  • transitionTime - Transition duration

Example:

AudioManager.Instance.SetStateInGroup("Location", "Underwater", 1.5f);

GetActiveState

public AudioState GetActiveState(string stateGroup)

Description: Gets the currently active state for a state group.

Returns: Active AudioState, or null if no state active.

GetActiveStateName

public string GetActiveStateName(string stateGroup)

Description: Gets the name of the currently active state.

Returns: State name, or empty string if none active.

GetAllActiveStates

public IReadOnlyDictionary<string, AudioState> GetAllActiveStates()

Description: Gets all active states across all groups.

Returns: Dictionary mapping state group to active state.


Bus Methods

SetBusVolume

public void SetBusVolume(string busName, float volumeDb, float transitionTime = 0f)

Description: Sets a bus’s Volume in decibels (the asset’s value; an empty name is the master bus). A name no bus has changes nothing and warns once per name (since 3.1.0-dev.7; it used to set the master bus). For a player’s volume from a Settings page, use AudioBus.PlayerVolumeDb instead: a state can’t undo it and it isn’t saved to the asset.

Parameters:

  • busName - Name of the bus
  • volumeDb - Target volume in dB (0 = no change, -6 = half, -80 = silence)
  • transitionTime - Transition duration in seconds (0 = instant)

Example:

AudioManager.Instance.SetBusVolume("Music", -6f, 1f);  // Duck to half volume over 1 second
AudioManager.Instance.SetBusVolume("SFX", 0f, 0.5f);    // Return to full over 0.5s

TransitionBusVolume

public void TransitionBusVolume(AudioBus bus, float targetVolumeDb, float transitionTime)

Description: Transitions a bus to a target volume over time using the bus reference directly.

Parameters:

  • bus - The AudioBus reference
  • targetVolumeDb - Target volume in dB
  • transitionTime - Transition duration

SetBusEffectProperty

public void SetBusEffectProperty(AudioBus bus, string propertyName, float value, float transitionTime = 0f)

Description: Sets an effect property on a bus with optional transition.

Parameters:

  • bus - Target bus
  • propertyName - Effect property name
  • value - Target value
  • transitionTime - Transition duration (0 = instant)

GetBus

public AudioBus GetBus(string busName)

Description: Gets a bus by name.

Returns: AudioBus, or the master bus for an empty name. For a name no bus has it also returns the master bus, as before, and warns once per name (since 3.1.0-dev.7).

GetAllBuses

public List<AudioBus> GetAllBuses()

Description: Gets all registered buses.

Returns: List of all buses.


Crossfade Methods

CrossFade

public void CrossFade(AudioContainer from, AudioContainer to, float duration,
    AudioEvent.CrossfadeType type = AudioEvent.CrossfadeType.EqualPower)

Description: Crossfades between two containers.

Parameters:

  • from - Container to fade out
  • to - Container to fade in
  • duration - Crossfade duration in seconds
  • type - Crossfade curve type (Linear or EqualPower)

Linear fades in with x and out with 1 − x; EqualPower fades in with sin(x·π/2) and out with cos(x·π/2). The incoming voices play unbussed (through the container’s Mixer Group); the CrossFade event action routes them through its Target Bus instead, and places a 3D container at the post’s position or source GameObject. Fades only the “from” voices playing now: what the outgoing sound was still going to start (a delayed Play, a Sequence’s next clip) still starts. Use the handle overload below for that.

Example:

AudioManager.Instance.CrossFade(oldMusicContainer, newMusicContainer, 2f);

CrossFade (handle)

public AudioHandle CrossFade(AudioHandle from, AudioEvent to, float duration,
    AudioEvent.CrossfadeType type = AudioEvent.CrossfadeType.EqualPower,
    GameObject source = null, Vector3 position = default)

Description: Fades out every voice of from and cancels what it was still going to start (delayed Play actions, a Sequence’s next clip), posts to and fades in the voices that post started. Returns the new handle (null when to is null).

  • from finishes (OnFinished) when its fade-out ends; OnStopping does not fire.
  • to is an ordinary post: bus, priority, cooldown and Max Instances apply. If it is the same event as from and Max Instances is reached, the old play is ended at once by the instance limit.
  • Voices to starts later are not faded in.
  • Either argument may be null.

Example:

music = AudioManager.Instance.CrossFade(music, combatMusicEvent, 2f);

Volume & Global Control Methods

SetMasterVolume

public void SetMasterVolume(float volume)

Description: Sets master volume (global volume multiplier).

Parameters:

  • volume - Volume in linear scale (0-1)

Example:

AudioManager.Instance.SetMasterVolume(0.75f);  // 75% volume

GetMasterVolume

public float GetMasterVolume()

Description: Gets current master volume.

Returns: Master volume (0-1).

MasterVolumeDb / SetMasterVolumeDb

public float MasterVolumeDb { get; set; }
public void SetMasterVolumeDb(float db)

Description: The master volume in dB, beside the linear setter (the same value; 3.1.0-dev.7). Above 0 dB stays at full; −80 dB and below is silent.

IsAllMuted

public bool IsAllMuted { get; }

Description: True while MuteAll(true) has every sound muted (3.1.0-dev.7).

MuteAll

public void MuteAll(bool mute)

Description: Mutes or unmutes all audio.

Parameters:

  • mute - true to mute, false to unmute

Example:

AudioManager.Instance.MuteAll(true);   // Mute everything
AudioManager.Instance.MuteAll(false);  // Unmute everything

StopAllSounds

public void StopAllSounds()

Description: Stops all currently playing sounds.

PauseAll

public void PauseAll()

Description: Pauses all currently playing sounds, at once. Sounds posted afterwards play. For a game’s pause, where a pause menu must still sound, pause buses instead (AudioBus.Pause).

UnpauseAll

public void UnpauseAll()

Description: Resumes all paused sounds.


Voice Management Methods

GetVoice

public AudioVoice GetVoice()

Description: Allocates a voice from the pool. Internal use only.

Returns: Available voice, or null if pool exhausted.

ReturnVoice

public void ReturnVoice(AudioVoice voice)

Description: Returns a voice to the pool. Internal use only.

GetStatistics

public AudioStatistics GetStatistics()

Description: Gets current audio system statistics.

Returns: AudioStatistics with voice counts and system info.

Example:

var stats = AudioManager.Instance.GetStatistics();
Debug.Log($"Real voices: {stats.activeVoices}/{stats.realVoiceBudget}");

Debug Methods

GetVirtualVoiceCount

public int GetVirtualVoiceCount()

Description: Gets the number of currently virtualized voices.

GetActiveVoicesDebug

public List<AudioVoiceDebugInfo> GetActiveVoicesDebug()

Description: Gets detailed debug info for all active voices: for a virtual one, why (virtualReasonKind, see VoiceVirtualReason); its level, pitch and region.

Returns: List of AudioVoiceDebugInfo for each active voice.

GetPlaysDebug

public void GetPlaysDebug(List<AudioPlayDebugInfo> into)

Description: Fills into with every play that has a live voice, each with its voices, ordered by play number: what the editor’s Live View (USER_GUIDE §10.6) shows per emitter. A play with nothing sounding right now (a Switch with no choice, a Sequence between clips, a Delay still running) isn’t listed. Allocates; for tools and debug overlays, not per-frame game code.

ReasonText

public static string ReasonText(VoiceVirtualReason reason)

Description: The words the debug windows show for a reason: “over the cap”, “silent layer”, “past Max Distance”, “held by code”, “bus paused”, “emitter paused”, “stopping”; empty for None.

From the Pepper.SFX 3.1 guides (API_REFERENCE.md). Something wrong or unclear? Tell me.