Mute AudioMixerGroup through script

I have 2 AudioMixerGroups, one for the sound effects and the other for background music.

Is there a way to mute one group through script ? I can’t seem to find any parameter that would control that through code, I can have snapshots and switch between them but that doesn’t seem very convenient.

public AudioMixerGroup BGMusic;
public AudioMixerGroup Sfx;

Rightclick the Volume parameter in the inspector → expose to code. You can then set it to 0 using the SetFloat() function of the AudioMixer object.

I made a scriptable object that actually can solve the problem.
How to use it:

  1. Expose a parameter which will represent an Audio Mixer Group Volume,

  2. Create a new AudioMixerVolumeController

  3. Pass AudioMixer and the parameter name there

Now you can inject this object anywhere and use it to change the audio group volume or mute it.
Also this class solves problem with AudioMixer Db [-80; +20] → Volume Fraction [0.0, 1.0] conversion.

PS. No Singletons

Example:

#if UNITY_EDITOR
using RichUnity.Attributes;
#endif
using UnityEngine;
using UnityEngine.Audio;

namespace RichUnity.Audio
{
    [CreateAssetMenu(fileName = "AudioMixerVolumeController", menuName = "RichUnity/Audio/Audio Mixer Volume Controller")]
    public class AudioMixerVolumeController : ScriptableObject
    {
        [SerializeField]
        private AudioMixer audioMixer;

        public AudioMixer AudioMixer
        {
            get
            {
                return audioMixer;
            }
        }

        public string VolumeParameterName;

        private const float LowerVolumeBound = -80.0f;
        private const float UpperVolumeBound = 0.0f;

        public float Volume // do not use it in Awake() or OnEnable(), Unity has a bug with AudioMixer
        {
            get
            {
                if (muted)
                {
                    return volumeBeforeMute;
                }
                else
                {
                    return VolumeNoMutedGuards;
                }
            }
            set
            {
                float newVolumeT = Mathf.Clamp01(value);
                if (muted)
                {
                    volumeBeforeMute = newVolumeT;
                }
                else
                {
                    VolumeNoMutedGuards = newVolumeT;
                }
            }
        }

        private float VolumeNoMutedGuards
        {
            get
            {
                float volume = 0.0f;
                if (AudioMixer)
                {
                    AudioMixer.GetFloat(VolumeParameterName, out volume);
                }

                volume = Mathf.InverseLerp(LowerVolumeBound, UpperVolumeBound, volume);
                return volume;
            }

            set
            {
                if (AudioMixer)
                {
                    AudioMixer.SetFloat(VolumeParameterName,
                        Mathf.Lerp(LowerVolumeBound, UpperVolumeBound, value));
                }
            }
        }

#if UNITY_EDITOR
        [ReadOnly]
#endif
        [SerializeField]
        private bool muted;
        private float volumeBeforeMute;

        public bool Muted // do not use it in Awake() or OnEnable(), Unity has a bug with AudioMixer
        {
            get
            {
                return muted;
            }
            set
            {
                muted = value;
                if (muted)
                {
                    volumeBeforeMute = VolumeNoMutedGuards;
                    VolumeNoMutedGuards = 0.0f;
                }
                else
                {
                    VolumeNoMutedGuards = volumeBeforeMute;
                }
            }
        }

        private void OnEnable()
        {
            muted = false;
        }
    }
}

This link gave me the most “complete” answer related to the idea of toggling the mute button of the mixer through script : It’s not possible to have it exposed, you’ll need to work with volumes.

https://forum.unity.com/threads/how-do-you-mute-a-audiomixergroup-from-code.308909/#post-2011302

It is not possible right now. Vote on this feedback issue, so that Unity developers notice it and improve the system.

Expose API for AudioMixer and its components

Here is a small extension.

namespace UnityEngine.Audio
{
    public static class AudioExtensions
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="mixer"></param>
        /// <param name="exposedName">The name of 'The Exposed to Script' variable</param>
        /// <param name="value">value must be between 0 and 1</param>
        public static void SetVolume(this AudioMixer mixer, string exposedName, float value)
        {
            mixer.SetFloat(exposedName, Mathf.Lerp(-80.0f, 0.0f, Mathf.Clamp01(value)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mixer"></param>
        /// <param name="exposedName">The name of 'The Exposed to Script' variable</param>
        /// <returns></returns>
        public static float GetVolume(this AudioMixer mixer, string exposedName)
        {
            if (mixer.GetFloat(exposedName, out float volume))
            {
                return Mathf.InverseLerp(-80.0f, 0.0f, volume);
            }

            return 0f;
        }
    }
}

Hello, you can use my script if you want

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;

public class audioMixer : MonoBehaviour
{

    [SerializeField] string masterVolume = "masterVol";
    [SerializeField] string sfxVolume = "sfxVol";
    [SerializeField] string bgmVolume = "bgmVol";

    public bool isMasterMuted = false;
    public bool isSFXMuted = false;
    public bool isBGMMuted = false;

    float maxLevel = 0f;
    float minLevel = -80f;

    public AudioMixer masterMixer;

    public void SetMasterVolume(float soundLevel)
    {
        masterMixer.SetFloat(masterVolume, soundLevel);
    }

    public void MuteMasterVolume()
    {
        isMasterMuted = !isMasterMuted;

        if(isMasterMuted)
        {
            masterMixer.SetFloat(masterVolume, minLevel);
        }
        else
        {
            masterMixer.SetFloat(masterVolume, maxLevel);
        }
    }

    public void SetSFXVolume(float soundLevel)
    {
        masterMixer.SetFloat(sfxVolume, soundLevel);
    }

    public void MuteSFXVolume()
    {
        isSFXMuted = !isSFXMuted;

        if (isSFXMuted)
        {
            masterMixer.SetFloat(sfxVolume, minLevel);
        }
        else
        {
            masterMixer.SetFloat(sfxVolume, maxLevel);
        }
    }

    public void SetBGMVolume(float soundLevel)
    {
        masterMixer.SetFloat(bgmVolume, soundLevel);
    }

    public void MuteBGMVolume()
    {
        isBGMMuted = !isBGMMuted;

        if (isBGMMuted)
        {
            masterMixer.SetFloat(bgmVolume, minLevel);
        }
        else
        {
            masterMixer.SetFloat(bgmVolume, maxLevel);
        }
    }
}