How can I prevent from a volume slider to jump over value when playing sfx ?

I have two sliders for music volume and for sfx effects.
Both sliders are working.

The problem is that the sfx slider volume play the sfx effect only when I change the sfx volume value.
and the problem happens if I’m changing the slider too fast.
For example if the slider value is 7 and I move it too fast to value 23 then it will play the sfx effect at value 23 but I want it to be play on all the values from 7 to 23 either if I’m moving the slider slow or very fast.

This is the script I’m using for playing the audio and in the SetSfxVolume function I’m playing the sfx effect when changing the sfx volume slider at line 113 :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;
using TMPro;
using System;
using UnityEngine.Events;
using System.Linq;

public class Settings : MonoBehaviour
{
    [SerializeField] private AudioSource[] audioSources;
    public AudioMixer audioMixer;
    public TMP_Dropdown resolutionDropdown;
    public TMP_Dropdown qualityDropdown;
    public Text musicText;
    public Text sfxText;
    public Slider[] audioSliders;
    public Toggle fullScreenToggle;

    private Resolution[] resolutions;

    private void Awake()
    {
        audioSources = GetComponents<AudioSource>();

        resolutionDropdown.onValueChanged.AddListener(new UnityAction<int>(index =>
        {
            PlayerPrefs.SetInt("resolutionvalue", resolutionDropdown.value);
            PlayerPrefs.Save();

        }));

        qualityDropdown.onValueChanged.AddListener(new UnityAction<int>(index =>
        {
            PlayerPrefs.SetInt("qualityvalue", qualityDropdown.value);
            PlayerPrefs.Save();

        }));

        fullScreenToggle.onValueChanged.AddListener(new UnityAction<bool>(index =>
        {
            PlayerPrefs.SetInt("fullscreen", boolToInt(fullScreenToggle.isOn));
            PlayerPrefs.Save();

        }));
    }

    private void Start()
    {
        qualityDropdown.value = PlayerPrefs.GetInt("qualityvalue");

        var resolutions = Screen.resolutions.Where(resolution => resolution.refreshRate == 60).ToArray();
        resolutionDropdown.ClearOptions();

        List<string> options = new List<string>();

        int currentResolutionIndex = 0;
        for(int i = 0; i < resolutions.Length; i++)
        {
            string option = resolutions[i].width + " x " + resolutions[i].height;
            options.Add(option);

            if(resolutions[i].width == Screen.currentResolution.width &&
                resolutions[i].height == Screen.currentResolution.height)
            {
                currentResolutionIndex = i;
            }
        }

        resolutionDropdown.AddOptions(options);
        resolutionDropdown.value = PlayerPrefs.GetInt("resolutionvalue", currentResolutionIndex);
        resolutionDropdown.RefreshShownValue();

        float musicvolume = PlayerPrefs.GetFloat("musicvolume");
        float sfxvolume = PlayerPrefs.GetFloat("sfxvolume");

        musicText.text = musicvolume.ToString();
        sfxText.text = sfxvolume.ToString();
        audioSliders[0].value = musicvolume / 100f;
        audioSliders[1].value = sfxvolume / 100f;

        fullScreenToggle.isOn = intToBool(PlayerPrefs.GetInt("fullscreen", 0));
       
    }

    public void SetResolution(int resolutionIndex)
    {
        if (resolutions != null)
        {
            Resolution resolution = resolutions[resolutionIndex];
            Screen.SetResolution(resolution.width, resolution.height, Screen.fullScreen);
        }
    }

    public void SetMusicVolume(float volume)
    {
        audioMixer.SetFloat("musicvol", Mathf.Log10(volume) * 20);
        musicText.text = Math.Round(volume * 100, MidpointRounding.AwayFromZero).ToString();

        PlayerPrefs.SetFloat("musicvolume", (float)Math.Round(volume * 100, MidpointRounding.AwayFromZero));
    }

    public void SetSfxVolume(float volume)
    {
        audioMixer.SetFloat("sfxvol", Mathf.Log10(volume) * 20);
        sfxText.text = Math.Round(volume * 100, MidpointRounding.AwayFromZero).ToString();

        PlayerPrefs.SetFloat("sfxvolume", (float)Math.Round(volume * 100, MidpointRounding.AwayFromZero));

        if (!audioSources[1].isPlaying)
            audioSources[1].Play();
    }

    public void SetQuality(int qualityIndex)
    {
        QualitySettings.SetQualityLevel(qualityIndex);
    }

    public void SetFullscreen(bool isFullscreen)
    {
        Screen.fullScreen = isFullscreen;       
    }

    int boolToInt(bool val)
    {
        if (val)
            return 1;
        else
            return 0;
    }

    bool intToBool(int val)
    {
        if (val != 0)
            return true;
        else
            return false;
    }
}

Maybe you’re not updating the volume at real time. “Callback executed when the value of the slider is changed.” I think this is probably like a MouseUpAsButton event, therefore only executing when mouse is lifted up. (I think)

Place your musicvolume in Update() to get to volume to be relative to the slider value. Or try to expose musicvolume variable to see if changes are real time when you move the slider.

The solution was just to remove the checking this line line 113 :

if (!audioSources[1].isPlaying)

To clarify, this is not the case, slider values update during dragging. Some other events do require a mouseup event, like OnClick.

2 Likes