Pepper.SFX
All Guidance pages

Guidance / API reference

AudioEvent

Namespace: AudioSystem Inheritance: ScriptableObject

Properties

EventName

public string EventName { get; }

Description: Unique name identifying this event.

Actions

public List<EventAction> Actions { get; }

Description: List of actions to execute when this event is posted.

Priority

public VoicePriority Priority { get; }

Description: How important this event’s sounds are (Low, Medium, High, Critical): a weight in each voice’s importance, which decides what goes virtual and what is stolen first. Critical is the strongest weight, not an exemption; to keep a sound from ever being stolen, tick Persistent.

MaxInstances

public int MaxInstances { get; }

Description: Maximum concurrent plays (0 = unlimited). One play is everything a single Play action starts: all of a multi-clip Routing container’s clips, or all of a Blend’s layers, count as one instance.

StealBehavior

public VoiceStealBehavior StealBehavior { get; }

Description: Which play to end when the limit is reached (Oldest, Quietest, Furthest, LowestPriority). A steal ends the whole play, meaning every voice it started. Oldest means the play that started first, judged by start time rather than playback position. Quietest uses each play’s loudest voice. Furthest uses each play’s nearest voice.

Cooldown

public float Cooldown { get; }

Description: Minimum time between triggers in seconds.

MaxInstancesPerEmitter / CooldownPerEmitter

public int MaxInstancesPerEmitter { get; }   // 0 = no limit per emitter
public float CooldownPerEmitter { get; }     // seconds; 0 = none

Description: The same limits for one AudioEmitter, on top of the game-wide ones: a post on an emitter already playing MaxInstancesPerEmitter plays of this event ends one of that emitter’s plays, chosen by StealBehavior; a post sooner than CooldownPerEmitter after the last one on that emitter returns a finished handle. Other emitters aren’t affected. Posts without an emitter aren’t counted per emitter. On the event’s TimeMode, like Cooldown.

TimeMode

public AudioTimeMode TimeMode { get; set; }   // Scaled (default) or Unscaled

Description: Inspector: Time. The clock this event’s timing runs on: Cooldown, CooldownPerEmitter, Delay actions, its sounds’ Sequence gaps, its CrossFade action and AudioManager.CrossFade(handle, thisEvent). Scaled is game time: it stops at time scale 0, as before. Unscaled is real time, for UI and pause-menu sounds. Changing it mid-session compares the next post with a time from the old clock once.

public enum AudioTimeMode { Scaled, Unscaled }

Persistent

public bool Persistent { get; }

Description: Inspector: Persistent. This event’s plays are never stolen by the voice pool to make room for other sounds (an engine). They can still go virtual, and this event’s own Max Instances can still end one. If the pool is full of persistent plays, a new sound is skipped with a warning. Their voices get Unity’s highest AudioSource.priority (0).


Methods

Post

public AudioHandle Post(GameObject source = null, Vector3 position = default)

Description: Posts the event. Optionally attach to a GameObject and/or specify a 3D position.

Parameters:

  • source - (Optional) GameObject to attach sound to
  • position - (Optional) 3D world position for spatial audio

Returns: AudioHandle for controlling playback.

Example:

// Non-spatial (2D)
AudioHandle handle = myEvent.Post();

// Attached to a GameObject at its position
AudioHandle handle = myEvent.Post(gameObject, transform.position);

// At a specific world position, not attached
AudioHandle handle = myEvent.Post(null, explosionPosition);

Post(GameObject, Vector3, double scheduledDspTime) starts the voices at an exact DSP time instead of the next buffer (tempo-driven callers).

Post (on an emitter)

public AudioHandle Post(AudioEmitter emitter)
public AudioHandle Post(AudioEmitter emitter, double scheduledDspTime)

Description: Posts the event on an AudioEmitter. 3D voices are placed and attached exactly as with Post(emitter.gameObject, emitter.transform.position), and the sounds read the emitter’s parameter values (after the handle’s own, before the global ones). A null or destroyed emitter logs a warning and returns a finished handle with nothing playing. Same as emitter.Post(evt).

Source change in 3.1: myEvent.Post(null) with a bare null no longer compiles: it matches both this overload and Post(GameObject, ...). Write myEvent.Post() for a 2D post.

Post (with values for that sound)

public AudioHandle Post(AudioEmitter emitter, PostValues values)
public AudioHandle Post(AudioEmitter emitter, string point, PostValues values)
public AudioHandle Post(GameObject source, Vector3 position, PostValues values)

Description: Posts with PostValues for this sound only: they are set on the handle’s play scope before any Play action runs, so the first sample hears them (an impact’s strength, a footstep’s surface). A delayed Play action reads them too.

PostAtOffset (an emitter, anywhere on it)

public AudioHandle PostAtOffset(AudioEmitter emitter, Vector3 localOffset, PostValues values = default)

Description: Posts on emitter at localOffset (metres, in its own space), as at a named point but anywhere: an impact at the contact point (3.1.0-dev.7). The sound moves and turns with the emitter, reads its values, counts toward its Max Instances Per Emitter and Cooldown Per Emitter, and draws from its random numbers. Move it later with AudioHandle.SetLocalOffset. Same as emitter.Post(evt, localOffset, values). It isn’t an overload of Post, so that Post(null, position, values) keeps compiling.

Post (a moment of the sound at a DSP time)

public AudioHandle Post(AudioEmitter emitter, double startDsp, double startOffsetSeconds, PostValues values = default)
public AudioHandle Post(GameObject source, Vector3 position, double startDsp, double startOffsetSeconds,
                        PostValues values = default)

Description: startOffsetSeconds into the sound (seconds of its clips at their recorded pitch) is heard at the DSP time startDsp (3.1.0-dev.7): a pass-by whoosh whose peak lands on the pass. If startDsp has passed, or is nearer than the next DSP buffer, the sound starts at the next buffer that much further in (at its pitch), so the same moment still lands on time; a one-shot already past its end plays nothing and its handle finishes; a loop wraps. Every voice the Play actions start with takes the offset (a Blend’s layers stay aligned); a Sequence’s later clips start from their beginning; a Play action with a Delay keeps its own timing. startDsp 0 = as soon as possible, from the offset. Same as emitter.Post(evt, startDsp, startOffsetSeconds, values).

EstimateDuration

public AudioDuration EstimateDuration(PostValues values = default)
public AudioDuration EstimateDuration(AudioEmitter emitter, PostValues values = default)

Description: How long the event plays if posted now with values (3.1.0-dev.7), before posting it. Random container: its shortest and longest clip. Switch: the choice the values pick (the given values, then the emitter’s, then global, then the group’s Default). Blend and Routing: their longest layer (a Blend’s Loop Mode decides whether it loops). Sequence: the entry it plays next, or with Auto Advance the rest of the run (a run that starts again loops). Every Play action counts, its Delay added; the longest wins. A custom container: the shortest and longest of the clips it lists. Clips are measured at their recorded pitch; an addressable clip that isn’t loaded is unknown. Draws no random numbers.

AudioDuration

Namespace: AudioSystem (readonly struct)

public float Shortest { get; }   // seconds
public float Longest { get; }    // seconds; for a loop, one time through
public bool Loops { get; }       // plays until stopped
public bool IsKnown { get; }     // false when nothing would play (the lengths are 0)

PostValues

Namespace: AudioSystem (struct)

public const int MaxParameters = 4;
public const int MaxSwitches = 2;
public static PostValues Of(AudioParameter parameter, float value)
public static PostValues Of(AudioSwitchGroup group, string value)
public PostValues With(AudioParameter parameter, float value)   // a later value for the same parameter wins
public PostValues With(AudioSwitchGroup group, string value)
public static PostValues VolumeOffset(float db)
public PostValues WithVolumeOffset(float db)          // the handle's SetVolumeOffset, before the first sample
public PostValues WithPitchOffset(float semitones)    // the handle's SetPitchOffset, before the first sample
public int ParameterCount { get; }
public int SwitchCount { get; }
public bool IsEmpty { get; }

Description: Values a post gives its sound (the play scope, like AudioHandle.SetParameter / SetSwitch), applied before its first voice starts, and its own volume and pitch offsets (3.1.0-dev.7), which also reach the voices it starts later. Building one allocates nothing. More than 4 parameters or 2 switches: the rest are dropped with one warning; set them on the returned handle.

car.Post(impactEvent, "FrontAxle", PostValues.Of(strength, 0.8f).With(surface, "Grass"));

PostMultiPosition

public AudioMultiHandle PostMultiPosition(Vector3[] positions, GameObject source = null)
public AudioMultiHandle PostMultiPosition(Transform[] transforms, GameObject source = null)
public AudioMultiHandle PostMultiPosition(AudioMultiPositionEmitterParent emitterParent, GameObject source = null)

Description: Posts event in multi-position mode (synchronized across multiple positions or emitters).

Parameters:

  • positions - Array of 3D world positions
  • transforms - Array of transforms to track
  • emitterParent - Multi-position emitter parent component
  • source - (Optional) GameObject to attach the voices to. On a 3D container each voice still plays at its own position and moves with source.

Returns: AudioMultiHandle for controlling all voices.

Example:

// From position array
Vector3[] speakerPositions = { pos1, pos2, pos3 };
AudioMultiHandle mh = myEvent.PostMultiPosition(speakerPositions);

// From transforms
Transform[] speakers = GetSpeakerTransforms();
AudioMultiHandle mh = myEvent.PostMultiPosition(speakers);

// From emitter parent component
AudioMultiHandle mh = myEvent.PostMultiPosition(emitterParent);

GetContainer

public AudioContainer GetContainer()

Description: Gets the first container referenced in this event’s actions.

Returns: AudioContainer, or null if no Play action exists.

GetFirstActiveSource

public AudioSource GetFirstActiveSource()

Description: Gets the first active AudioSource for this event.

Returns: AudioSource, or null if no voice is active.

CreateNew (Editor Only)

public static AudioEvent CreateNew(string name, AudioContainer container, AudioBus bus)

Description: Factory method to create a new AudioEvent asset with pre-configured Play action.


EventAction (Nested Class)

[Serializable]
public class EventAction
{
    public ActionType type;
    public ActionScope scope;           // Stop/Pause/Resume: All (default) or ThisEmitter
    public AudioContainer container;
    public AudioBus targetBus;          // Play/CrossFade routing; TriggerDucking's trigger bus
    public float delay;
    public float fadeDuration;          // Stop fade-out; CrossFade/SetRTPC/SetState transition;
                                        // TriggerDucking hold time. Play ignores it.
    public AnimationCurve fadeCurve;    // Not used by any action in this version
    public string switchGroup;
    public string switchValue;
    public string rtpcName;
    public float rtpcValue;
    public string stateName;
    public AudioContainer fadeFromContainer;
    public CrossfadeType crossfadeType;

    public enum ActionType
    {
        Play, Stop, Pause, Resume,
        SetSwitch, SetRTPC, SetState,
        TriggerDucking, CrossFade
    }

    public enum ActionScope { All, ThisEmitter }
}

scope: which of this event’s sounds a Stop, Pause or Resume action acts on. All (the default, as before): every one playing, on every emitter. ThisEmitter: only those posted on the AudioEmitter the event is posted on; posted without one, it acts on all.

CrossfadeType (Nested Enum)

public enum CrossfadeType
{
    Linear,      // Linear crossfade
    EqualPower   // Maintains perceived loudness
}

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