Search Unity

Fade Out Audio Source

Discussion in 'Audio & Video' started by Boris1998, Jun 21, 2015.

  1. Boris1998

    Boris1998

    Joined:
    Jul 5, 2013
    Posts:
    82
    I feel like I am asking too much and not contribuing to this Community, so here is a little code that may be useful to someone of you. It fades out sound (audioSource) over time (seconds). :D

    Just make this script named AudioFadeOut and you can call this function from anywhere you want:


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public static class AudioFadeOut {
    5.  
    6.     public static IEnumerator FadeOut (AudioSource audioSource, float FadeTime) {
    7.         float startVolume = audioSource.volume;
    8.  
    9.         while (audioSource.volume > 0) {
    10.             audioSource.volume -= startVolume * Time.deltaTime / FadeTime;
    11.  
    12.             yield return null;
    13.         }
    14.  
    15.         audioSource.Stop ();
    16.         audioSource.volume = startVolume;
    17.     }
    18.  
    19. }
    20.  
    You could use somethnig like this ...

    Code (CSharp):
    1. StartCoroutine (AudioFadeOut.FadeOut (sound_open, 0.1f));
    2.  
    3. //or:
    4.  
    5. public AudioSource Sound1;
    6.  
    7. IEnumerator fadeSound1 = AudioFadeOut.FadeOut (Sound1, 0.5f);
    8. StartCoroutine (fadeSound1);
    9. StopCoroutine (fadeSound1);
     
  2. mlamanna

    mlamanna

    Joined:
    Jan 9, 2014
    Posts:
    505
    I can't seem to get this script to work, and what I need is my background music to fade out before next scene loads.
     
  3. GameDev_Chuck

    GameDev_Chuck

    Joined:
    Jun 25, 2014
    Posts:
    17
    Thanks for posting :D Saved me some time
     
    migasporto14 and mlamanna like this.
  4. FionNoir

    FionNoir

    Joined:
    Aug 25, 2015
    Posts:
    13
    Thank you too! Exactly what I wanted.
     
  5. Enumerator_T

    Enumerator_T

    Joined:
    Nov 5, 2014
    Posts:
    3
    The script will persist through the entire game allowing you to change your music on the go.
    Full Inspector Image: https://postimg.org/image/xjjqemfp3/

    How to Setup:
    0: Go to your very first (scene)
    1: Create an Empty Object and call it MediaPlayer
    2: Create a script called MusicClass
    3: Create Empty
    4: Add AudioSource to the object you created (Make Volume '0' & Loop 'true' if needed)
    5: Put the music you want to play inside the AudioSource
    6: Put all the Music Objects inside the MediaPlayer Object
    If you want to add more music, start from (3)



    To c
    all the functions of MusicClass
    EXAMPLE->>>PlayMusic("MUSIC NAME - NAME OF THE TRANSFORM");
    Code (CSharp):
    1. FindObjectOfType<MusicClass>().PlayMusic("Beat"); // Transform name is called Beat

    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3.  
    4. public class MusicClass : MonoBehaviour
    5. {
    6.     private AudioSource[] _audioSources;
    7.     public float fadeSpeed = 0.5f;
    8.     public float fadeInOutMultiplier = 0.0f;
    9.     public bool isPlaying;
    10.  
    11.     public string playingTrackName = "Nothing";
    12.     public int playingTrackIndex;
    13.     public float playingTrackVolume = 0.000f;
    14.  
    15.     public string lastTrackName = "Nothing";
    16.     public int lastTrackIndex;
    17.     public float lastTrackVolume = 0.000f;
    18.  
    19.     public IEnumerator FadeOutOldMusic_FadeInNewMusic()
    20.     {
    21.         _audioSources[playingTrackIndex].volume = 0.000f;
    22.         _audioSources[playingTrackIndex].Play();
    23.         while (_audioSources[playingTrackIndex].volume < 1f)
    24.         {
    25.             _audioSources[lastTrackIndex].volume -= fadeSpeed * 2;
    26.             _audioSources[playingTrackIndex].volume += fadeSpeed * 2;
    27.             //Debug.Log("Fade: " + lastTrackName + " " + _audioSources[lastTrackIndex].volume.ToString() + " Rise: " + playingTrackName + " " + _audioSources[playingTrackIndex].volume.ToString());
    28.             yield return new WaitForSeconds(0.001f);
    29.             lastTrackVolume = _audioSources[lastTrackIndex].volume;
    30.             playingTrackVolume = _audioSources[playingTrackIndex].volume;
    31.         }
    32.         _audioSources[lastTrackIndex].volume = 0.000f; // Just In Case....
    33.         _audioSources[lastTrackIndex].Stop();
    34.  
    35.         lastTrackIndex = playingTrackIndex;
    36.         lastTrackName = playingTrackName;
    37.         isPlaying = true;
    38.     }
    39.  
    40.     public IEnumerator FadeInNewMusic()
    41.     {
    42.         _audioSources[playingTrackIndex].volume = 0.000f;
    43.         _audioSources[playingTrackIndex].Play();
    44.         while (_audioSources[playingTrackIndex].volume < 1f)
    45.         {
    46.             _audioSources[playingTrackIndex].volume += fadeSpeed * 2;
    47.             //Debug.Log("Fading In: " + _audioSources[track_index].volume.ToString());
    48.             yield return new WaitForSeconds(0.001f);
    49.             playingTrackVolume = _audioSources[playingTrackIndex].volume;
    50.         }
    51.         lastTrackIndex = playingTrackIndex;
    52.         lastTrackName = playingTrackName;
    53.         isPlaying = true;
    54.     }
    55.  
    56.     private void Awake()
    57.     {
    58.         DontDestroyOnLoad(transform.gameObject);
    59.         _audioSources = GetComponentsInChildren<AudioSource>();
    60.     }
    61.  
    62.     public void PlayMusic(string transformName)
    63.     {
    64.         for (int a = 0; a < _audioSources.Length; a++)
    65.         {
    66.             if (_audioSources[a].name == transformName)
    67.             {
    68.                 Debug.Log("Found Track Name (" + transformName + ") at Index(" + a.ToString() + ")");
    69.                 playingTrackIndex = a;
    70.                 playingTrackName = transformName;
    71.                 break;
    72.             }
    73.         }
    74.         if (playingTrackIndex == lastTrackIndex)
    75.         {
    76.             Debug.Log("Same Track Selected");
    77.             return;
    78.         } else {
    79.             if (isPlaying)
    80.             {
    81.                 Debug.Log("Fading in new music - Fading out old music");
    82.                 StartCoroutine(FadeOutOldMusic_FadeInNewMusic());
    83.             } else {
    84.                 Debug.Log("Fading in new music");
    85.                 StartCoroutine(FadeInNewMusic());
    86.             }
    87.         }
    88.     }
    89. }
     
    Last edited: Apr 1, 2017
    twobob and L0r3n20 like this.
  6. chall3ng3r

    chall3ng3r

    Joined:
    May 27, 2013
    Posts:
    23
    Hello,

    Thanks Boris1998 for sharing, it helped me in my current project with audio.

    I added another method for FadeIn, sharing back here my updated class:

    Code (csharp):
    1.  
    2. public static class AudioFadeScript
    3. {
    4.     public static IEnumerator FadeOut(AudioSource audioSource, float FadeTime)
    5.     {
    6.         float startVolume = audioSource.volume;
    7.  
    8.         while (audioSource.volume > 0)
    9.         {
    10.             audioSource.volume -= startVolume * Time.deltaTime / FadeTime;
    11.  
    12.             yield return null;
    13.         }
    14.  
    15.         audioSource.Stop();
    16.         audioSource.volume = startVolume;
    17.     }
    18.  
    19.     public static IEnumerator FadeIn(AudioSource audioSource, float FadeTime)
    20.     {
    21.         float startVolume = 0.2f;
    22.  
    23.         audioSource.volume = 0;
    24.         audioSource.Play();
    25.  
    26.         while (audioSource.volume < 1.0f)
    27.         {
    28.             audioSource.volume += startVolume * Time.deltaTime / FadeTime;
    29.  
    30.             yield return null;
    31.         }
    32.  
    33.         audioSource.volume = 1f;
    34.     }
    35. }
    36.  
    37.  
    Using example:

    Code (csharp):
    1.  
    2.             // stop menu music
    3.             StartCoroutine(AudioFadeScript.FadeOut(audioMenuMusic, 0.5f));
    4.  
    5.             // start game music
    6.             StartCoroutine(AudioFadeScript.FadeIn(audioGameMusic, 5f));
    7.  

    // chall3ng3r //
     
    protopop, dyupa, SibochCZ and 3 others like this.
  7. aurelien-defossez

    aurelien-defossez

    Joined:
    Jun 22, 2017
    Posts:
    2
    You can also create an extension class, to be able to call the fade out easily like this:

    Code (CSharp):
    1. sound.FadeOut(0.5f);
    Code (CSharp):
    1. using System.Collections;
    2.  
    3. namespace UnityEngine
    4. {
    5.     public static class AudioSourceExtensions
    6.     {
    7.         public static void FadeOut(this AudioSource a, float duration)
    8.         {
    9.             a.GetComponent<MonoBehaviour>().StartCoroutine(FadeOutCore(a, duration));
    10.         }
    11.  
    12.         private static IEnumerator FadeOutCore(AudioSource a, float duration)
    13.         {
    14.             float startVolume = a.volume;
    15.  
    16.             while (a.volume > 0)
    17.             {
    18.                 a.volume -= startVolume * Time.deltaTime / duration;
    19.                 yield return new WaitForEndOfFrame();
    20.             }
    21.  
    22.             a.Stop();
    23.             a.volume = startVolume;
    24.         }
    25.     }
    26. }
     
    Sidelobe and sunseeker1988 like this.
  8. martipello

    martipello

    Joined:
    Apr 28, 2015
    Posts:
    3
    yeah its 2 years old but saw your script and changed a couple things, first i added a max volume to fade in simple change, but second i added a check for if its fading as if you call fadeOut and fadeIn in relatively quick succession the coroutines fight for the volume and nothing gets called heres my simple fix


    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public static class SoundFader
    {
    public static bool isFading;
    public static IEnumerator FadeOut(AudioSource audioSource, float FadeTime)
    {
    isFading = true;
    float startVolume = audioSource.volume;
    while (audioSource.volume > 0)
    {
    audioSource.volume -= startVolume * Time.deltaTime / FadeTime;
    yield return null;
    }
    audioSource.Stop();
    audioSource.volume = startVolume;
    isFading = false;
    }
    public static IEnumerator FadeIn(AudioSource audioSource, float FadeTime, float max)
    {
    while(isFading){
    yield return new WaitForSeconds(0.5f);
    }
    float startVolume = 0.2f;
    audioSource.volume = 0;
    audioSource.Play();
    while (audioSource.volume < max)
    {
    audioSource.volume += startVolume * Time.deltaTime / FadeTime;
    yield return null;
    }
    isFading = false;
    audioSource.volume = max;
    }
    }​
     
    twobob likes this.
  9. myownbot

    myownbot

    Joined:
    Mar 30, 2017
    Posts:
    29
    Try this (via a variable adjustedVolume)

    Code (CSharp):
    1.     public static IEnumerator FadeOut (AudioSource audioSource, float FadeTime) {
    2.         float startVolume = audioSource.volume;
    3.         float adjustedVolume = startVolume;
    4.  
    5.         while (adjustedVolume > 0) {
    6.             adjustedVolume -= startVolume * Time.deltaTime / FadeTime;
    7.             audioSource.volume = adjustedVolume;
    8.             Debug.Log (adjustedVolume);
    9.             yield return null;
    10.         }
    11.  
    12.         audioSource.Stop ();
    13.         audioSource.volume = startVolume;
    14.     }
    15.  
    It seems that manipulating volume like audiosource.volume -= step doe not work for all.
    I have 2017.4.2f2
     
    Damjan-Mozetic and drktoninato like this.
  10. jandd661

    jandd661

    Joined:
    Jun 25, 2017
    Posts:
    17
    This thread helped me alot so thank you to the OP and everyone who has contributed. Google also seems to like it alot too when searching for audio crossfading. If anyone needs "set and forget" crossfading between two audio sources, I made this snippet:

    Code (CSharp):
    1.  
    2. private bool audioBlendInprogress = false;
    3. //----------------------------------
    4. // AUDIO CROSSFADE
    5. //----------------------------------
    6. private IEnumerator CrossFadeAudio(AudioSource audioSource1, AudioSource audioSource2, float crossFadeTime, float audioSource2VolumeTarget)
    7. {
    8.     string debugStart = "<b><color=red>ERROR:</color></b> ";
    9.     int maxLoopCount = 1;
    10.     int loopCount = 0;
    11.     float startAudioSource1Volume = audioSource1.volume;
    12.  
    13.     if(audioSource1 == null || audioSource2 == null)
    14.     {
    15.         Debug.Log(debugStart + transform.name + ".EngineControler.CrossFadeAudio recieved NULL value.\n*audioSource1=" + audioSource1.ToString() + "\n*audioSource2=" + audioSource2.ToString(), gameObject);
    16.         yield return null;
    17.     }
    18.     else
    19.     {
    20.         audioBlendInprogress = true;
    21.  
    22.         audioSource2.volume = 0f;
    23.         audioSource2.Play();
    24.  
    25.         while ((audioSource1.volume > 0f && audioSource2.volume < audioSource2VolumeTarget) && loopCount < maxLoopCount)
    26.         {
    27.             audioSource1.volume -= startAudioSource1Volume * Time.deltaTime / crossFadeTime;
    28.             audioSource2.volume += audioSource2VolumeTarget * Time.deltaTime / crossFadeTime;
    29.             loopCount++;
    30.             yield return null;
    31.         }
    32.  
    33.         if (loopCount < maxLoopCount)
    34.         {
    35.             audioSource1.Stop();
    36.             audioSource1.volume = startAudioSource1Volume;
    37.             audioBlendInprogress = false;
    38.         }
    39.         else
    40.         {
    41.             Debug.Log(debugStart + transform.name + ".EngineControler.CrossFadeAudio.loopCount reached max value.\nloopCount=" + loopCount + "\nmaxLoopCount=" + maxLoopCount, gameObject);
    42.         }
    43.     }
    44. }
    45.  
    It simply takes the two audio sources and fades across the two audio sources. The benefit of this method is that it's "set and forget" meaning it runs in a coroutine not in Update. Not that it's any better than anything else mentioned here, it's just another option. It also includes a safety switch (loopCount) that should be included in every "while" or "do" statement in my opinion.

    Anyways, to call it you would use:

    Code (CSharp):
    1. StartCoroutine(CrossFadeAudio(audioSource1, audioSource2, 10f, 1f));
    The first parameter "audioSource1" is the currently playing audio source.
    The second "audioSource2" is the audio source to crossfade too.
    Third is the time in seconds to do the fade.
    Forth is the target volume of audio source 2 (1f = 100%).

    Also, the "audioBlendInprogress" can be used to check if a fade is in progress.
    Code (CSharp):
    1. private bool audioBlendInprogress = false;  
    My real world example of using this method:
    Code (CSharp):
    1.  
    2. private void StartStopEngine()
    3. {
    4.         if (audioBlendInprogress == false)
    5.         {
    6.             if (engineIsRunning == false)
    7.             {
    8.                 audioSource1.clip = engineData.audioEngineStart;
    9.                 audioSource1.loop = false;
    10.                 audioSource2.clip = engineData.audioEngineIdle;
    11.                 audioSource2.pitch = 0.5f;
    12.                 audioSource2.loop = true;
    13.  
    14.                 audioSource1.Play();
    15.                 StartCoroutine(CrossFadeAudio(audioSource1, audioSource2, 10f, 1f));
    16.                 engineIsRunning = true;
    17.             }
    18.             else
    19.             {
    20.                 audioSource1.clip = engineData.audioEngineShutDown;
    21.                 audioSource1.loop = false;
    22.                 StartCoroutine(CrossFadeAudio(audioSource2, audioSource1, 3f, 1f));
    23.                 engineIsRunning = false;
    24.             }
    25.         }
    26. }
    Here I have a audio clip of an engine start and an engine idle. I wanted to play the engine start then crossfade to the idle clip. I first check to see if a crossfade is in progress. Then check if the engine is running. If I made it past that, I then set up the audio sources and start playing the engine start clip. Then I call the "CrossFadeAudio()" coroutine to fade the audio from engine start, too engine idle.

    The "else" for "engineIsRunning" is to fade between engine idle and the engine shutdown clip. I have a toggle input to start and stop the engines.

    I hope this helps someone.

    Edit: I noticed I left my debug info in the snippet and was going to remove it. But then decided to leave it in and make it self contained as it may help someone. So the main script may look more complicated than it really is lol ;-).
     
    Last edited: Jun 18, 2018
    ZiadJ likes this.
  11. Hambanana

    Hambanana

    Joined:
    Jul 3, 2013
    Posts:
    9
    I feel like everything is being overcomplicated here. If you aren't crossfading two loops just use Invoke.

    Code (CSharp):
    1.     Invoke("InvokeLoop", (introSource.clip.length - 3.5f));
    2.     public void InvokeLoop()
    3.     {
    4.         musicLoopSource.clip = menuLoop;
    5.         musicLoopSource.loop = true;
    6.         musicLoopSource.Play();
    7.     }
     
  12. indieDoroid

    indieDoroid

    Joined:
    Jan 25, 2016
    Posts:
    246
    There's also an official audio mixer from unity if you guys don't mind starting from scratch. This tutorial helped me a ton.

     
  13. BaldBeardedMonk

    BaldBeardedMonk

    Joined:
    Sep 12, 2016
    Posts:
    2
    Thanks a lot! Did save me some time and worked like a charm :)
     
  14. Smurfinator

    Smurfinator

    Joined:
    Jun 11, 2018
    Posts:
    4
    Cheers! If you only need to do this on one occasion then you can just take the coroutine out of it and place it in whatever script you like.
     
  15. MushayDroom

    MushayDroom

    Joined:
    Feb 20, 2018
    Posts:
    2
    Up! This subject is great, thanks for sharing, Borris1998 ! :D
     
unityunity