Home > OS >  Universally Changing Volume in Unity C#
Universally Changing Volume in Unity C#

Time:03-02

I am coding a game in Unity and want to make a button that makes every sound's volume go from full volume to 2/3 volume to 1/3 volume to muted and then go back to full volume. I know I can individually adjust each audio source but is there a way to lower the volume of everything at once?

I am using Unity 2020.3.24f1 and coding in C#. It is a 2D game.

CodePudding user response:

There are a bunch of ways you can do this, depending on what best suits your needs.

  1. Retired Ninja suggested using adjustments to AudioListener volume, which is a great centralized solution.
  2. Use static events to broadcast your button click. This allows you to exclude certain audio sources from the changes, if that's something you need. The drawback is that you will have to make sure any new audio sources added are subscribed to the event.
  3. Use a ScriptableObject to share settings among all audio sources. You can either use a static field, or give every audio source a reference to the settings file. This is a popular tool for sharing data among many different objects.
  4. Add your audio sources to an Audio Mixer and adjust the master volume.

Examples

Static Events

In the class where you have your button callback:

public class ButtonHandler
{
    public delegate void VolumeEvent(float volume);
    public static event VolumeEvent OnChangeVolume;

    private int _step = 3;
    private float _volIncrement = 0.333f;

    public void OnClick()
    {
        _step = _step == 0 ? 3 : --step;

        OnChangeVolume?.Invoke(_step * _volIncrement);
    }
}

In the classes where you control each AudioSource:

public class AudioManager : MonoBehaviour
{
    private AudioSource _source;

    // subscribe
    private void Awake() =>
        ButtonHandler.OnChangeVolume  = UpdateVolume;

    // always remember to unsubscribe
    private void OnDestroy() =>
        ButtonHandler.OnChangeVolume -= UpdateVolume;

    private void UpdateVolume(float vol) =>
        _source.volume = vol;
}

Scriptable Objects

Any object in your game can reference an instance of the following script. Those objects will be able to read and write to public fields, and every other object with a reference to the ScriptableObject will be able to read those changes.

public class AudioSettings : ScriptableObject
{
    public float volume;

    #if UNITY_EDITOR
    [UnityEditor.MenuItem("Assets/Create/Audio Settings")]
    public static void Create()
    {
        var path = UnityEditor.EditorUtility.SaveFilePanelInProject(
        "Save Audio Settings", "Audio Settings", "asset", "Save Audio Settings",
        "Assets/");

        if(path == "") return;
        UnityEditor.AssetDatabase.CreateAsset(CreateInstance<AudioSettings>(), path);
    }
    #endif
}
public class AudioManager : MonoBehaviour
{
    private AudioSource _source;
    [SerializeField] private AudioSettings _settings;

    private void Update() =>
        _source.volume = _settings.volume;
}
public class ButtonHandler
{
    [SerializeField] private AudioSettings _settings;

    private int _step = 3;
    private float _volIncrement = 0.333f;

    public void OnClick()
    {
        _step = _step == 0 ? 3 : --step;

        _settings.volume = _step * _volIncrement;
    }
}

This will allow you to create a settings file by clicking Assets > Create > Audio Settings. Find it in your Assets folder and drag the file into the field for anything that needs a reference to it. Alternatively, make the volume field static and access it by AudioSettings.volume.

  • Related