Smooth GUI and Audio Volume Fades

Hey Guys,

I could really use your help understanding what is wrong with my code.

I’m trying to make an audio fading in out system that can be controlled with these two Booleans; If i start the level with either one selected, it moves as predicted, sliding the value smoothly between 0.00 and 1.00 over a time period, but if I turn on and off the booleans there after, or wait until it is at run time to enable and disable them, it just jumps between 0 and 1.

I’m using a similar system for my GUI fades, and I’m having the exact same issue, what is wrong with the way this is written, and how can i fix it?

Thanks in advance for your help!

    var fadeIn = false;
    var fadeOut = false;
    
    
    var minimum = 0.00;
    var maximum = 1.00;
    
    var vol = 0.00;
    
    
    function Start () 
    {
    
    
    
    }
    
    
    function Update ()
    {
    
    audio.volume = vol;
    
    if (fadeIn)
    	{
    	fadeinDo ();
    	}
    
    
    if (fadeOut)
    	{
    	fadeoutDo ();
    	}
    	
    }
    
    
    function fadeinDo ()
    {
    
    vol = (Mathf.Lerp(minimum, maximum, Time.time * 0.5));
    
    }
    
    
    function fadeoutDo ()
    {
    
    vol = (Mathf.Lerp(maximum, minimum, Time.time * 0.5));
    
    }

Yes, that’s because you’re using Time.time as the t parameter in your Mathf.Lerp functions. Because Time.time is the amount of seconds since runtime started and the t parameter is based on a range from 0 to 1, this Mathf.Lerp will only work in the first second of the game. This is further explained (and displays a better way of doing Lerp functions) here.

The problem here is that the docs are very misleading, and will probably always remain very misleading. They don’t really provide adequate information on the topic, and as such I usually use really roundabout methods to linearly interpolate between values because I still don’t understand how to fully get Mathf.Lerp to work. :confused:

Le sigh …

Hope that helps, Klep

@Kleptomaniac is right: the docs show horrible Lerp examples. You could use something like this:

var minimum = 0.00;
var maximum = 1.00;

private var tFadeIn: float = 1.0;
private var tFadeOut: float = 1.0;    
private var duration: float;

function Awake(){
  audio.volume = 0.0; // avoid sound glitches during initialization
  FadeIn(2.0); // fade in the sound during 2 seconds
}

function Update (){
  if (tFadeIn < 1.0){
    tFadeIn += Time.deltaTime/duration;
    audio.volume = Mathf.Lerp(minimum, maximum, tFadeIn);
  }
  if (tFadeOut < 1.0){
    tFadeOut += Time.deltaTime/duration;
    audio.volume = Mathf.Lerp(maximum, minimum, tFadeOut);
  }
}

function FadeIn(dur: float){
  tFadeIn = 0.0;
  duration = dur;
}

function FadeOut(dur: float){
  tFadeOut = 0.0;
  duration = dur;
}

Just call the function FadeIn(t) to make the sound fade in in t seconds, or FadeOut(t) to make it fade out.

Rather than changing boolean to start the fade In/Out, you could use coroutines. Following code is in C#, but you can easily translate it into JS (or ask someone to do it).

public class FadeVolume extends MonoBehaviour
{
    public float volume
    {
        get;
        private set;
    }

    public float minimum = 0.0f;
    public float maximum = 1.0f;
    public float timeToFade = 1.0f;

    private bool _isFadingIn = false;
    private bool _isFadingOut = false;

    public void FadeIn()
    {
        this._isFadingOut = false;            
        StartCoroutine(DoFadeIn());
    }

    public void FadeOut()
    {
        this._isFadingIn = false;            
        StartCoroutine(DoFadeOut());
    }

    private IEnumerator DoFadeIn()
    {
        this._isFadingIn = true;

        float startTime = Time.time;
        float elapsedTime = 0;
        do
        {
            elapsedTime = Time.time - startTime;
            this.volume = Mathf.Lerp(this.minimum, this.maximum, elapsedTime/timeToFade);
            yield return null;
        } while( this._isFadingIn && elapsedTime < this.timeToFade );        
        
        this._isFadingIn = false;
    }

    private IEnumerator DoFadeOut()
    {
        this._isFadingOut = true;

        float startTime = Time.time;
        float elapsedTime = 0;
        do
        {
            elapsedTime = Time.time - startTime;
            this.volume = Mathf.Lerp(this.maximum, this.minimum, elapsedTime/timeToFade);
            yield return null;
        } while( this._isFadingOut && elapsedTime < this.timeToFade );
        
        this._isFadingOut = false;
    }
}

Thanks for all your help, and for taking the time.

Sadly I still couldn’t get it working with either of those, and things just got so much worse when I started using .deltaTime.

So I have reluctantly written an ugly ‘ghetto script,’ to fit the need. And it works perfectly.

Thanks again for your help anyway!

 	var fadeIn = false;
var fadeOut = false;

var vol = 0.00;

   


function Start () 
{

vol = 0.00;

	fadeIn = true;

}


function FixedUpdate ()
{

audio.volume = vol;

if (fadeIn)
	if (vol < 1)
    	{
    	fadeOut = false;
   		vol = vol + 0.01;
    	}


if (fadeOut)
   if (vol > 0)
   		{
   		fadeIn = false;
   		vol = vol - 0.01;
   		}

}

Is there a way to do this so that the fade out is associated with a specific audio file (AudioSource) instead of a single one for all sounds in the object? In other words, if I have multiple sounds playing and I want to trigger one sound to fade out but not the other one, how can that be done? I have an example below:

`

var myAudioFile1 : AudioClip;
var myAudioFile2 : AudioClip;

var minimum = 0.00;
var maximum = 1.00;

private var tFadeIn: float = 1.0;
private var tFadeOut: float = 1.0;
private var duration: float;

function Awake(){
audio.volume = 0.0; // avoid sound glitches during initialization
FadeIn(0.0); // fade in the sound during 2 seconds
}

function FadeIn(dur: float){
tFadeIn = 0.0;
duration = dur;
}

function FadeOut(dur: float){
tFadeOut = 0.0;
duration = dur;
}

function Update()
{
if(Input.GetKeyDown(“1”))
{
if (!audio.isPlaying)
{
audio.Stop();
}
audio.PlayOneShot(myAudioFile1);
}
if(Input.GetKeyDown(“2”))
{
if (!audio.isPlaying)
{
audio.Stop();
}
audio.PlayOneShot(myAudioFile2);
}

if(Input.GetKeyUp("1"))
{
	if (!audio.isPlaying) // ideally, this should fade out clip 2 only 
	{
	FadeOut(1);
	}
}

if(Input.GetKeyUp("2"))
{
	if (!audio.isPlaying) // ideally, this should fade out clip 2 only 
	{
	FadeOut(1);
	}
}			
	
if (tFadeIn < 1.0)
{
	tFadeIn += Time.deltaTime/duration;
	audio.volume = Mathf.Lerp(minimum, maximum, tFadeIn);
}
if (tFadeOut < 1.0){
	tFadeOut += Time.deltaTime/duration;
	audio.volume = Mathf.Lerp(maximum, minimum, tFadeOut);
}

}
`