Players expect a music slider, dialogue they can hear over explosions, and a pause menu that stops the world but not its own clicks. In Pepper.SFX each of those is a setting on an Audio Bus asset. Set it once, and every event routed to that bus follows it.
How it works
- Hierarchy. Each bus has a Parent Bus. Its level (Volume, plus any state’s offset, plus the player’s volume, in dB) is multiplied by its ducking, its curves and its parents’ levels, so muting a bus mutes its children. A bus can also feed a Unity Audio Mixer Group for Unity’s effects.
- Ducking. A trigger bus lists Ducking Targets, each with a Duck Amount in dB, plus attack and release times. A TriggerDucking action or
bus.TriggerDucking(holdSeconds)starts it. When ducks overlap, the deepest wins, so a short UI duck can’t cut a dialogue duck short. - Parameter Curves on a bus. A bus’s volume, and a low- or high-pass on its Mixer Group, can follow a parameter, such as nitro sweeping the other cars’ low-pass.
- Pausing a bus.
Pause()fades the bus and its child buses out over about 25 ms and holds their place without keeping real voices.Resume()carries on, every layer in phase. While Paused decides whether one-shots posted meanwhile are dropped or held. - Player volume.
PlayerVolumeDbis a separate level for a settings menu. It is never saved into the asset, and no state undoes it. - Voice caps. Max Real Voices caps a bus’s real voices. Over it, the least important sounds go virtual, never ended, and come back in step.
- States. An Audio State can move bus levels: Set Level writes the bus’s Volume, Offset moves it and puts it back when the state ends.
- Mixer window (full version only): Window > Audio System > Mixer shows every bus as a fader with mute and solo; changes are saved and can be undone.
Example
using UnityEngine;
using AudioSystem;
public class MixControls : MonoBehaviour
{
[SerializeField] private AudioBus musicBus;
[SerializeField] private AudioBus worldBus; // parent of Vehicles, Ambience...
[SerializeField] private AudioBus dialogueBus; // ducks Music when triggered
// Settings sliders, 0 to 1.
public void SetMasterVolume(float slider) => AudioManager.Instance.SetMasterVolume(slider);
public void SetMusicVolume(float slider) =>
musicBus.PlayerVolumeDb = AudioSystem.AudioExtensions.LinearToDb(slider);
public void OpenPauseMenu()
{
Time.timeScale = 0f;
worldBus.Pause(); // the world holds; the menu's own buses play on
}
public void ClosePauseMenu()
{
worldBus.Resume();
Time.timeScale = 1f;
}
// Duck the music while a voice line plays.
public void OnLineStarted(float lineSeconds) => dialogueBus.TriggerDucking(lineSeconds);
}
Sliders set the player’s volume, so a mix state never fights the settings menu. Pausing the World bus holds the game while the UI and menu-music buses outside it keep playing.
Setting it up
- Assets > Create > Audio System > Audio Bus for Master, then Music, SFX, Dialogue and so on, each with its Parent Bus set.
- On the
AudioManager, assign the Master Bus and add every bus to Buses, so lookups by name find them. - Set the Target Bus on each event’s Play action.
- For ducking, tick Enable Ducking on the Dialogue bus, add Music to its Ducking Targets, and give the dialogue event a TriggerDucking action (Target Bus: Dialogue, Fade Duration: the hold time).
- For a filter curve, give the bus a Mixer Group, add a Low Pass Parameter Curve, and click Add Low Pass to Mixer Group in the bus inspector.
Good to know
- Ducking is triggered, not detected from what the bus plays. A duck runs on the target bus’s Ducking Time Mode: Scaled, the default, freezes at time scale 0, so set Unscaled on buses ducked during a pause.
- A raise can’t take a sound past its AudioSource’s full volume, so mix with headroom.
- Bus curves read only a parameter’s global value, and pitch curves are ignored on a bus. If the inspector button can’t edit the mixer in your Unity version, it logs the manual steps.
- Unity’s Web audio has no mixer effects, so bus filter curves don’t work in Web builds.
- On Unity 6.3, write
AudioSystem.AudioExtensionsin full: Unity added its ownAudioExtensions.