Search code examples
c#fade

Logarithmic Fade In and Out over Game Frames


I have created a static function within Unity3d that fades out music over a certain amount of frames. The function is being placed within Unity3d's FixedUpdate() so that it updates according to real world time (or at least close hopefully).

My current math for a linear fade out looks like this:

if (CurrentFrames > 0) { 
    AudioSourceObject.volume = ((CurrentFrames / TotalFrames) * TotalVolume);
} 
if (CurrentFrames <= 0) { 
    AudioSourceObject.volume = 0.00f;
    return 0;
}
CurrentFrames--;

This works well as a simple way to create a function that's like FadeOutBGM(NumberOfFrames);...but now I'm looking at how I would create a logarithmic fade out using this function.

Looking at the equasions online, I'm completely confused as to what I should do.


Solution

  • You're more than welcome to use the builtins. Otherwise, if you'd like finer control, you could use an adjusted sigmoid function. Normally, a sigmoid function looks like this: (https://www.wolframalpha.com/input/?i=plot+(1%2F(1%2Be%5E(t)))+from+-5+to+5)

    enter image description here

    But you want your fade out function to look more like this: (https://www.wolframalpha.com/input/?i=plot+(1%2F(1%2Be%5E(3t-4))+from+-5+to+5)

    enter image description here

    Where x is your ratio of (CurrentFrames / TotalFrames) * 3, and y is the output volume.

    But how did I get from the first to the second graph? Try experimenting with the scalers (i.e. 3x or 5x) and offsets (i.e. (3x - 4) or (3x - 6)) of the exponential input (e^(play with this)) in wolfram alpha to get a feel for how you want the curve to look. You don't necessarily have to line up the intersection of your curve and an axis with a particular number, as you can adjust the input and output of your function in your code.

    So, your code would look like:

    if (CurrentFrames > 0) { 
        // I'd recommend factoring out and simplifying this into a  
        // function, but I have close to zero C# experience.
        inputAdjustment = 3.0
        x = ((CurrentFrames / TotalFrames) * inputAdjustment);
        sigmoidFactor = 1.0/(1.0 + Math.E ^ ((3.0 * x) - 4.0));
        AudioSourceObject.volume = (sigmoidFactor * TotalVolume);
    }
    
    if (CurrentFrames <= 0) { 
        AudioSourceObject.volume = 0.00f;
        return 0;
    }
    CurrentFrames--;