Pepper.SFX
All Guidance pages

Guidance / Cookbook

UI Sounds

Recipe: Button Click Sound

📋 What: Button with click sound and subtle variations

🎯 Use Case: UI buttons, menu navigation

Asset Setup

1. Create Container:

  • Right-click Containers/UI/ → Create → Random Container
  • Name: “UI_ButtonClick_RnC”
  • Inspector:
    • Audio Clips: Add 2-3 click sound variations
    • Avoid Repeat Last: 1
    • Use Weighting: ✓ (all weights = 1.0)
    • Volume: 0.8
    • Enable Volume Randomization: ✓ (Min: -1, Max: 1)
    • Enable Pitch Randomization: ✓ (Min: -50, Max: 50)

2. Create Event:

  • Right-click Assets/Resources/Audio/Events/UI/ → Create → Audio Event
  • Name: “Play_UI_ButtonClick”
  • Inspector:
    • Event Name: “Play_UI_ButtonClick”
    • Priority: Critical
    • Max Instances: 2
    • Steal Behavior: Oldest
    • Cooldown: 0.05
    • Actions → Size: 1
    • Action [0]:
      • Type: Play
      • Container: UI_ButtonClick_RnC
      • Target Bus: UI_Bus

Code

using UnityEngine;
using UnityEngine.UI;
using AudioSystem;

public class UIButtonSound : MonoBehaviour
{
    [SerializeField] private AudioEvent clickEvent;

    private Button button;

    void Awake()
    {
        button = GetComponent<Button>();
        if (button != null)
        {
            button.onClick.AddListener(OnButtonClick);
        }
    }

    void OnDestroy()
    {
        if (button != null)
        {
            button.onClick.RemoveListener(OnButtonClick);
        }
    }

    void OnButtonClick()
    {
        if (clickEvent != null)
        {
            clickEvent.Post();
        }
    }
}

Usage:

  1. Attach to Button GameObject
  2. Drag “Play_UI_ButtonClick” into Click Event field
  3. Click button to hear sound

✅ Result: Button clicks with subtle variation, no spam!


Recipe: Settings Menu with Volume Sliders

📋 What: Complete audio settings menu with persistence

🎯 Use Case: Options menu, settings screen

💻 Code:

using UnityEngine;
using UnityEngine.UI;
using AudioSystem;

public class AudioSettingsMenu : MonoBehaviour
{
    [Header("UI References")]
    [SerializeField] private Slider masterSlider;
    [SerializeField] private Slider sfxSlider;
    [SerializeField] private Slider musicSlider;
    [SerializeField] private Slider dialogueSlider;

    [Header("Audio Events")]
    [SerializeField] private AudioEvent testSFXEvent;

    private const string MASTER_KEY = "Audio_MasterVolume";
    private const string SFX_KEY = "Audio_SFXVolume";
    private const string MUSIC_KEY = "Audio_MusicVolume";
    private const string DIALOGUE_KEY = "Audio_DialogueVolume";

    void Start()
    {
        LoadSettings();
        SetupListeners();
        ApplySettings();
    }

    void LoadSettings()
    {
        masterSlider.value = PlayerPrefs.GetFloat(MASTER_KEY, 1f);
        sfxSlider.value = PlayerPrefs.GetFloat(SFX_KEY, 1f);
        musicSlider.value = PlayerPrefs.GetFloat(MUSIC_KEY, 1f);
        dialogueSlider.value = PlayerPrefs.GetFloat(DIALOGUE_KEY, 1f);
    }

    void SetupListeners()
    {
        masterSlider.onValueChanged.AddListener(OnMasterVolumeChanged);
        sfxSlider.onValueChanged.AddListener(OnSFXVolumeChanged);
        musicSlider.onValueChanged.AddListener(OnMusicVolumeChanged);
        dialogueSlider.onValueChanged.AddListener(OnDialogueVolumeChanged);
    }

    void ApplySettings()
    {
        OnMasterVolumeChanged(masterSlider.value);
        OnSFXVolumeChanged(sfxSlider.value);
        OnMusicVolumeChanged(musicSlider.value);
        OnDialogueVolumeChanged(dialogueSlider.value);
    }

    void OnMasterVolumeChanged(float value)
    {
        AudioManager.Instance.SetMasterVolume(value);
        PlayerPrefs.SetFloat(MASTER_KEY, value);
        PlayerPrefs.Save();
    }

    void OnSFXVolumeChanged(float value)
    {
        SetPlayerVolume("SFX", value);
        PlayerPrefs.SetFloat(SFX_KEY, value);
        PlayerPrefs.Save();
    }

    void OnMusicVolumeChanged(float value)
    {
        SetPlayerVolume("Music", value);
        PlayerPrefs.SetFloat(MUSIC_KEY, value);
        PlayerPrefs.Save();
    }

    void OnDialogueVolumeChanged(float value)
    {
        SetPlayerVolume("Dialogue", value);
        PlayerPrefs.SetFloat(DIALOGUE_KEY, value);
        PlayerPrefs.Save();
    }

    // The player's volume on a bus (Manual §6.8): on top of the mix, never saved into the bus asset,
    // and a mix state can't undo it. Not SetBusVolume, which changes the bus's own Volume.
    void SetPlayerVolume(string busName, float linear)
    {
        var bus = AudioManager.Instance.GetBus(busName);   // an unknown name warns once
        if (bus != null)
            bus.PlayerVolumeDb = AudioSystem.AudioExtensions.LinearToDb(linear);  // qualified: Unity 6.3 has its own AudioExtensions
    }

    // Call this from a "Test" button
    public void PlayTestSound()
    {
        if (testSFXEvent != null)
        {
            testSFXEvent.Post();
        }
    }
}

UI Setup:

  1. Create 4 Sliders (Master, SFX, Music, Dialogue)
  2. Set slider range: 0 to 1
  3. Create “Test Sound” button
  4. Attach script to settings panel
  5. Assign references

✅ Result: Full audio settings with persistence and test button!

💡 Why PlayerVolumeDb and not SetBusVolume: SetBusVolume changes the bus’s own Volume, the mix you authored. In the editor a Play-mode change stays in the asset, and a state that sets the bus’s level overwrites the player’s choice. The player’s volume is a separate level on top. Example08_AudioSettingsUI is the full version.

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