Search code examples
c#unity-game-engineaudio-source

How to manage AudioSources at runtime in Unity c#


In a music application in Unity, when you put a fadeout so that the sounds that are being created have no clicking when they stop, all the music that is in the background also enters into the fadeout. I would like to be able to do fadeout without interfering in the background music, but i don't know how. This is my code:

private AudioSource[] sound;

void OnTouchDown()
{

    if (instrument == "Piano")
    {
        FindObjectOfType<PianoAudioManager>().Play("PianoGmaj1G"); 
    }

void OnTouchUp()
{        
    sound = FindObjectsOfType(typeof(AudioSource)) as AudioSource[];
    foreach (AudioSource audioS in sound)
    {
        StartCoroutine(AudioFadeOut.FadeOut(audioS, 0.02f));
    }
}

How could I save the sound when I activate it so I can do the fadeout without affecting everything else? I have been stuck with this for days and I can not find how to do it. I would be very grateful for any help. Thank you

Edit. Yes, sorry, my PianoAudioManager code is:

public class PianoAudioManager : MonoBehaviour{

    public PianoSound[] PianoSounds;

    public static PianoAudioManager instance; 
    public AudioMixerGroup PianoMixer;

    void Awake() 
    {

        if (instance == null)
            instance = this;
        else
        {
            Destroy(gameObject);
            return;
        }

        DontDestroyOnLoad(gameObject); 

        foreach(PianoSound s in PianoSounds)
        {
            s.source = gameObject.AddComponent<AudioSource>(); 
            s.source.outputAudioMixerGroup = PianoMixer;
            s.source.clip = s.clip;

            s.source.volume = s.volume;
            s.source.pitch = s.pitch;
        }
    }

    public void Play (string name)
    {
        PianoSound s = Array.Find(PianoSounds, sound => sound.name == name);  
        if (s == null)
        {
            Debug.LogWarning("Sound: " + name + " not found!");
            return;
        }
        s.source.Play();
    }
}

Solution

  • Right now, you are fading out every single AudioSource in your scene, but I think you only want to fade out the audiosource that is playing your piano noise. If that's correct, then you need to remember which audiosource is playing the sound, and fade out out just that one!

    Add/change this in PianoAudioManager:

    public List<PianoSound> soundsToFadeOut = new List<PianoSound>();
    public void Play (string name)
    {
        PianoSound s = Array.Find(PianoSounds, sound => sound.name == name);  
        if (s == null)
        {
            Debug.LogWarning("Sound: " + name + " not found!");
            return;
        }
        s.source.Play();
    soundsToFadeOut.Add(s);
    }
    

    And change your other functions:

    void OnTouchDown()
    {
    
        if (instrument == "Piano")
        {
            PianoAudioManager playable = FindObjectOfType<PianoAudioManager>();
            playable.Play("PianoGmaj1G"); 
        }
    
    void OnTouchUp()
    {        
        PianoAudioManager playable = FindObjectOfType<PianoAudioManager>();
        foreach (PianoSound s in playable.soundsToFadeout)
        {
            StartCoroutine(AudioFadeOut.FadeOut(s.source, 0.02f));
        }
        playable.soundsToFadeout.Clear();
    }
    

    Explanation:
    You want to keep track of the sounds that are actually playing, and only fade out those songs!