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)
{
EndTransition();
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
EndTransition();
}
void EndTransition()
{
if ( (transitionCoroutine == null) || (endSnapshot == null) )
{
return;
}
StopCoroutine(transitionCoroutine);
endSnapshot.TransitionTo(0f);
}