How To --> Fade Out Music Before Loading Level

Hello all,

This is some simple code I wrote, but perhaps it may be of use to someone,

I use this to fade out my level music before I load a new level,

The new level is loaded by a button press, the button code is also below.
The level that gets loaded is set on the game object by the ‘level’ variable.

var level : int;

function Update () {
}

function OnGUI () { 

    if (GUI.Button(Rect (168,116,166,28), "")) {   	
	FadeOutSoundAndLoadLevel(level);
  }  
}  


function FadeOutSoundAndLoadLevel (loadLevel : int) {
	
var i : int;

	for (i = 9; i > 0; i--)
	{
    	audio.volume = i * .1;
    	yield new WaitForSeconds (.5);
	}		
	Application.LoadLevel(loadLevel);
}

I hope this is of help to someone, you could also fade in by changing this line

for (i = 0; i < 0; i++)

Farewell,

Trevor

That’s going in .5 second steps, though, which could be smoother. (Also a trivial thing: you don’t need the “new” keyword in Javascript when doing yield WaitForSeconds.) Here’s an audio fade function that I use:

enum Fade {In, Out}
var fadeTime = 4.0;

function Start () {
	FadeAudio(fadeTime, Fade.Out);
}

function FadeAudio (timer : float, fadeType : Fade) {
	var start = fadeType == Fade.In? 0.0 : 1.0;
	var end = fadeType == Fade.In? 1.0 : 0.0;
	var i = 0.0;
	var step = 1.0/timer;

	while (i <= 1.0) {
		i += step * Time.deltaTime;
		audio.volume = Mathf.Lerp(start, end, i);
		yield;
	}
}

So you call FadeAudio with the number of seconds you want the fade to occur over, plus Fade.In or Fade.Out for the obvious effect.

–Eric

1 Like

And of course I have to chime in and recommend not to use linear amplitude fades. :wink:

http://www.unifycommunity.com/wiki/index.php?title=Listener

But yes, do like Eric did and update the volume as often as possible to avoid “zipper noise”.

Hm, for some reason I never do fadings (audio or graphics) this way. I always stuff the update into the Update() or FixedUpdate() function and decrement a value, i.e.:

Works every time.

Yes, but then you have the Update function running all the time whether you’re fading or not, not to mention the added complexity and inflexibility. Using a coroutine also “works every time” but is more efficient and easier to deal with. :wink:

Regarding the linear fading, normally I would agree, but when you’re just fading a music track out over a few seconds, it hardly matters.

–Eric

True that. Might as well skip the complexity and slowdown of extra code and a power function if you just need to get the sound to go away without making a click sound, which happens when you just use the Stop() function. As it is, it’s too much of a pain to design fade-out curves. I thought about making a graphical editor for that, but I’m going to wait and see what Unity 3.0 brings before I waste my time.

I know this is an old post, but I found it, so someone else might find this useful. I needed this converted to C# and found it difficult because C# handles the yield very differently. So here’s the working code for C Sharp:

enum Fade {In, Out};
float fadeTime = 4.0F;

void Start () {
	StartCoroutine(FadeAudio(fadeTime, Fade.Out));
}

IEnumerator FadeAudio (float timer, Fade fadeType) {
	float start = fadeType == Fade.In? 0.0F : 1.0F;
	float end = fadeType == Fade.In? 1.0F : 0.0F;
	float i = 0.0F;
	float step = 1.0F/timer;

	while (i <= 1.0F) {
		i += step * Time.deltaTime;
		audio.volume = Mathf.Lerp(start, end, i);
		yield return new WaitForSeconds(step * Time.deltaTime);
	}
}

Note specifically that at the time the function is called, you must explicitly use StartCoroutine.

Great stuff, Eric! Really helped me out. Thank you.

Hi!

Thanks for the script Eric!

I changed it a bit, in order to make it more easy to control the fade in-out function, through the inspector.

var FadeIn : boolean = true;
var FadeOut : boolean = false;


enum Fade {In, Out}
var fadeTime: float;

 
function Start () {
if (!FadeIn)
    
    FadeAudio(fadeTime, Fade.In);
}

function FadeAudio (timer : float, fadeType : Fade) {

    var start = fadeType == Fade.In? 1.0 : 0.0;

    var end = fadeType == Fade.In? 0.0 : 1.0;

    var i = 0.0;

    var step = 1.0/timer;
    
    while (i <= 1.0) {

        i += step * Time.deltaTime;

        audio.volume = Mathf.Lerp(start, end, i);
    yield;
 }
}

function Update () {
if (!FadeOut)
    
    FadeAudio(fadeTime, Fade.Out);
}

function FadeAudio2 (timer : float, fadeType : Fade) {

    var start = fadeType == Fade.In? 0.0 : 1.0;

    var end = fadeType == Fade.In? 1.0 : 0.0;

    var i = 0.0;

    var step = 1.0/timer;
    
    while (i <= 1.0) {

        i += step * Time.deltaTime;

        audio.volume = Mathf.Lerp(start, end, i);
    yield;
 }
}

Getting parsing errors when I add this code to my game. How is this applied?

what is your error?

My audio is glitching whenever I use this, any idea why?

I got this working with a fade in, but I get an initial pop in the audio before the fade starts, any thoughts?

Thanks

My guess is that the code assumes that your volume is full, or at zero before fading:

    float start = fadeType == Fade.In? 0.0F : 1.0F;

This will create a ‘pop’ if your volume is instead set to a lower value, or higher value.

To fix this you should ensure that your AudioSource’s volume is at 1.0f, or 0.0f before fading, or you can change the above code to instead say:

    float start = audio.volume

I would also supplement this by stopping other fade coroutines before fading so you don’t have odd behavior from two coroutines updating the same value.

You could do it with a basic Lerp

public class FadeOutAudio : MonoBehaviour {

    [TooltipAttribute("The audio source")]
    public AudioSource audioSource;
    [TooltipAttribute("Time in seconds to fade out")]
    public float fadeSpeed = 5f;
    [TooltipAttribute("Toggle the fade")]
    public bool startFade = false;

    float time = 0f;

    void Update(){
        if(startFade){
            audioSource.volume = Mathf.Lerp(1f, 0f, time);
            time += Time.deltaTime / fadeSpeed;
        }
    }

}

Thx for your update,
This is your same code with the minor changes needed, to make it work on in Unity 5.++

public class PoisonBeams : MonoBehaviour {

    enum Fade {In, Out};
    float fadeTime = 4.0F;

    void Start () {
        StartCoroutine(FadeAudio(fadeTime, Fade.Out));
    }

    IEnumerator FadeAudio (float timer, Fade fadeType) {
        float start = fadeType == Fade.In? 0.0F : 1.0F;
        float end = fadeType == Fade.In? 1.0F : 0.0F;
        float i = 0.0F;
        float step = 1.0F/timer;

        while (i <= 1.0F) {
            i += step * Time.deltaTime;
            GetComponent<AudioSource>().volume = Mathf.Lerp(start, end, i);
            yield return new WaitForSeconds(step * Time.deltaTime);
        }
    }
}

Once again, thx very much about this!!!
Simple, and working immediately :).

I’d like to use this script to fade audio out when a button is being clicked. I’ve tried to add the script as a ”On Click ()” on a button to trigger the fade with the button is pressed. But how to associate it with my audio source?