Alpha Accesswebsite_badges_steamwishlistwebsite_badges_steamwishlist


AudioMixerSnapshot transitions independent of timescale

Unity Audio Mixer

One of the great new features of Unity 5 is the overhauled audio system, including the fancy new mixer and audio mixer snapshots. As a sound designer, this was one of the major selling points that pushed me to upgrade from 4.6. In particular, the AudioMixerSnapshot class lets you define a bunch of settings (for example submixer settings, filter effect values, etc) and transition between them – either instantly or over time. For example, one classic and emotionally-effective use is to low-pass filter your music when in a pause menu or item selection screen that takes you “out” of the action.

The only problem is that many people set Time.timescale to 0 when pausing their game, and this actually prevents the AudioMixerSnapshot.TransitionTo() function from transitioning smoothly. I was tired of waiting for a native solution to this, so I wrote a coroutine in my AudioManager class to handle snapshot transitions, and this is not affected by Time.timescale. Here’s the sample code, easily adaptable to your own class:

private Coroutine transitionCoroutine;
private AudioMixerSnapshot endSnapshot;
public void TransitionSnapshots(AudioMixerSnapshot fromSnapshot, AudioMixerSnapshot toSnapshot, float transitionTime)
        transitionCoroutine = StartCoroutine(TransitionSnapshotsCoroutine(fromSnapshot, toSnapshot, transitionTime));
IEnumerator TransitionSnapshotsCoroutine(AudioMixerSnapshot fromSnapshot, AudioMixerSnapshot toSnapshot, float transitionTime)
        // transition values
        int steps = 20;
        float timeStep = (transitionTime / (float)steps);
        float transitionPercentage = 0.0f;
        float startTime = 0f;
        // set up snapshots
        endSnapshot = toSnapshot;
        AudioMixerSnapshot[] snapshots = new AudioMixerSnapshot[] {fromSnapshot, toSnapshot};
        float[] weights = new float[2];
        // stepped-transition
        for (int i = 0; i < steps; i++)
                transitionPercentage = ((float)i) / steps;
                weights[0] = 1.0f - transitionPercentage;
                weights[1] = transitionPercentage;
                audioMixer.TransitionToSnapshots(snapshots, weights, 0f);
                // this is required because WaitForSeconds doesn't work when Time.timescale == 0
                startTime = Time.realtimeSinceStartup;
                while(Time.realtimeSinceStartup < (startTime + timeStep))
                        yield return null;
        // finalize
void EndTransition()
        if ( (transitionCoroutine == null) || (endSnapshot == null) )
©2017 Sombr Studio LLC