Little modification in script

Hey, I want to make music player with more then 2 audio sources.
how this script line should be for more then 2 audio sources?

    public void PlayMusic(AudioClip musicClip)
    {
        AudioSource activeSource = (FirstMusicSourceIsPlaying) ? musicSource : musicSource2;
        activeSource.clip = musicClip;
        activeSource.volume = 1;
        activeSource.Play();
    }
    public void PlayMusicWhiteFade(AudioClip newClip, float transitionTime = 1.0f)
    {
        AudioSource activeSource = (FirstMusicSourceIsPlaying) ? musicSource : musicSource2;
        StartCoroutine(UpdateMusicWithFade(activeSource, newClip, transitionTime));

You’d probably have to make an array to keep track of which audio sources are playing and find one that isn’t? I’m not sure how you keep track of “FirstMusicSourceIsPlaying” in the existing script. I’m also not sure what the actual desired behavior is here.

1 Like

That’s probably not the best idea I would suggest that you use an array of Audio Clips and one AudioSource then whenever you need AudioClip[2] you can set the clip of your AudioSource to that AudioClip

I just donr know how to handle with this line:

AudioSource activeSource = (FirstMusicSourceIsPlaying) ? musicSource : musicSource2;

means if the first audio is playing, the second isn’t and its working very well. but if I want to add third or fourth audio, how this line should looks like?

I’m not sure what advantage manually managing multiple sources is giving you over having a single source but something like the below should work. You’d first need to declare a list of audio sources, either populated in the editor or on Awake:

[SerializeField] private List<AudioSource> audioSources;

Then in your PlayMusic method you could set your audio source as follows:

AudioSource activeSource;

for (int i = 0; i < audioSources.Count; i++)
{
    if (audioSources[i].isPlaying)
    {
        activeSource = audioSources[i];
        break;
    }
}

// If no sources are playing default to first in list
if (activeSource == null)
{
    activeSource = audioSources[0];
}

I tried but there is still little problem and its not working. I made 2 scripts, one for the audio manager and one for the list of songs. I want to use the keyboard to switch between songs (like press “1” for song #1, “2” for song #2…) sill cant figure what is the problem.

The audio Manager:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioManager : MonoBehaviour
{
    #region Static Instance
    private static AudioManager instance;
    AudioSource activeSource;
    public static AudioManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<AudioManager>();
                if (instance == null)
                {
                    instance = new GameObject("Spawned AudioManager", typeof(AudioManager)).GetComponent<AudioManager>();
                }
            }

            return instance;
        }
        private set
        {
            instance = value;
        }
    }
    #endregion

    #region Fields

    [SerializeField] private List<AudioSource> audioSources;

    private bool FirstMusicSourceIsPlaying;
    #endregion

    private void Awake()
    {
        DontDestroyOnLoad(this.gameObject);

    }

    public void PlayMusic(AudioClip musicClip)
    {
        for (int i = 0; i < audioSources.Count; i++)
        {
            if (audioSources[i].isPlaying)
            {
                activeSource = audioSources[i];
                break;
            }
        }
        if (activeSource == null)
        {
            activeSource = audioSources[0];
        }
    }
    public void PlayMusicWhiteFade(AudioClip newClip, float transitionTime = 1.0f)
    {
        for (int i = 0; i < audioSources.Count; i++)
        {
            if (audioSources[i].isPlaying)
            {
                activeSource = audioSources[i];
                break;
            }
        }
        if (activeSource == null)
        {
            activeSource = audioSources[0];
        }

    }
   
    private IEnumerator UpdateMusicWithFade(AudioSource activeSource, AudioClip newClip, float transitionTime)
    {
        if (!activeSource.isPlaying)
            activeSource.Play();

        float t = 0.0f;

        for (t = 0; t < transitionTime; t += Time.deltaTime)
        {
            activeSource.volume = (1 - (t / transitionTime));
            yield return null;
        }

        activeSource.Stop();
        activeSource.clip = newClip;
        activeSource.Play();

        for (t = 0; t < transitionTime; t += Time.deltaTime)
        {
            activeSource.volume = (t / transitionTime);
            yield return null;
        }

    }
  
}

The song list:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioManagerTest : MonoBehaviour
{
    [SerializeField] private List<AudioSource> activeSource;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
            AudioManager.Instance.PlayMusicWhiteFade(audioSources);

    }
}

its says: the name audioSource does not exist in the current context, and if there is no error, it still doesn’t do nothing.

You need to declare the activeSource variable before the for loop, it’s the first line in the code on my last post. The code handles getting the active source it doesn’t play anything.

As it’s being called in multiple places you’d be better off turning it into its own method so you only have to make changes in one place:

private AudioSource GetActiveSource()
{
    AudioSource activeSource;
    for (int i = 0; i < audioSources.Count; i++)
    {
        if (audioSources[i].isPlaying)
        {
            activeSource = audioSources[i];
            break;
        }
    }
    // If no sources are playing default to first in list
    if (activeSource == null)
    {
        activeSource = audioSources[0];
    }

    return activeSource;
}

Combining this with the code in your original post your two play methods would then look like this:

 public void PlayMusic(AudioClip musicClip)
    {
        AudioSource activeSource = GetActiveSource();
        activeSource.clip = musicClip;
        activeSource.volume = 1;
        activeSource.Play();
    }
    public void PlayMusicWhiteFade(AudioClip newClip, float transitionTime = 1.0f)
    {
        AudioSource activeSource = GetActiveSource();
        StartCoroutine(UpdateMusicWithFade(activeSource, newClip, transitionTime));

I’ve also just noticed in AudioManagerTest class you’re trying to pass a list of audio sources to the PlayMusicWithFade method. This won’t work as that method expects an audio clip. From the description of what you want this to do you’ll need to change the AudioManagerTest class to something like the following:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioManagerTest : MonoBehaviour
{
    [SerializeField] private List<AudioClip> audioClips;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            AudioManager.Instance.PlayMusicWhiteFade(audioClips[0]);
        }

        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            AudioManager.Instance.PlayMusicWhiteFade(audioClips[1]);
        }
    }
}

Thanks for your help. there is still little problem with the 2 scripts:

the audio manager looks like this and there is no error:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioManager : MonoBehaviour
{
    #region Static Instance
    private static AudioManager instance;
    public static AudioManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<AudioManager>();
                if (instance == null)
                {
                    instance = new GameObject("Spawned AudioManager", typeof(AudioManager)).GetComponent<AudioManager>();
                }
            }

            return instance;
        }
        private set
        {
            instance = value;
        }
    }
    #endregion

    #region Fields
    [SerializeField] private List<AudioSource> audioClips;
    private AudioSource musicSource;

    #endregion

    private void Awake()
    {
        DontDestroyOnLoad(this.gameObject);
        musicSource = this.gameObject.AddComponent<AudioSource>();
        musicSource.loop = true;

    }

    private AudioSource GetActiveSource()
    {
        AudioSource activeSource = (musicSource);
        for (int i = 0; i < audioClips.Count; i++)
        {
            if (audioClips[i].isPlaying)
            {
                activeSource = audioClips[i];
                break;
            }
        }
        if (activeSource == null)
        {
            activeSource = audioClips[0];
        }
        return activeSource;
    }

    public void PlayMusic(AudioClip musicClip)
    {

        AudioSource activeSource = GetActiveSource();
        activeSource.clip = musicClip;
        activeSource.volume = 1;
        activeSource.Play();
    }

    public void PlayMusicWhiteFade(AudioClip newClip, float transitionTime = 1.0f)
    {
        AudioSource activeSource = GetActiveSource();
        StartCoroutine(UpdateMusicWithFade(activeSource, newClip, transitionTime));

    }
    private IEnumerator UpdateMusicWithFade(AudioSource activeSource, AudioClip newClip, float transitionTime)
    {
        if (!activeSource.isPlaying)
            activeSource.Play();

        float t = 0.0f;

        for (t = 0; t < transitionTime; t += Time.deltaTime)
        {
            activeSource.volume = (1 - (t / transitionTime));
            yield return null;
        }

        activeSource.Stop();
        activeSource.clip = newClip;
        activeSource.Play();

        for (t = 0; t < transitionTime; t += Time.deltaTime)
        {
            activeSource.volume = (t / transitionTime);
            yield return null;
        }

    }

}

The audio manager test look like this and there are two problems

  1. with the - its says "cannot apply indexing with [ ] to an expression of type ‘audioclip’
  2. it dosnt make any list in the game to put songs to it, there is only one box to put “Audio Clips” inside
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioManagerTest : MonoBehaviour
{
    [SerializeField] private AudioClip audioClips;
   

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            AudioManager.Instance.PlayMusicWhiteFade(audioClips[0]);
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            AudioManager.Instance.PlayMusicWhiteFade(audioClips[1]);
        }
    }

   
}

No problem! The 2 issues are caused by the same thing. You need to change:

[SerializeField] private AudioClip audioClips;

to:

[SerializeField] private List<AudioClip> audioClips;

You’ll need to add a check to make sure the list is initialised and that there is a clip at that index in the list but I left that out for clarity.

Ok so my 2 scripts look like this:

the audio manager:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioManager : MonoBehaviour
{
    #region Static Instance
    private static AudioManager instance;
    public static AudioManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<AudioManager>();
                if (instance == null)
                {
                    instance = new GameObject("Spawned AudioManager", typeof(AudioManager)).GetComponent<AudioManager>();
                }
            }

            return instance;
        }
        private set
        {
            instance = value;
        }
    }
    #endregion

    #region Fields
    [SerializeField] private List<AudioSource> audioClips;
    private AudioSource musicSource;

    #endregion

    private void Awake()
    {
        DontDestroyOnLoad(this.gameObject);
        musicSource = this.gameObject.AddComponent<AudioSource>();
        musicSource.loop = true;

    }

    private AudioSource GetActiveSource()
    {
        AudioSource activeSource = (musicSource);
        for (int i = 0; i < audioClips.Count; i++)
        {
            if (audioClips[i].isPlaying)
            {
                activeSource = audioClips[i];
                break;
            }
        }
        if (activeSource == null)
        {
            activeSource = audioClips[0];
        }
        return activeSource;
    }

    public void PlayMusic(AudioClip musicClip)
    {

        AudioSource activeSource = GetActiveSource();
        activeSource.clip = musicClip;
        activeSource.volume = 1;
        activeSource.Play();
    }

    public void PlayMusicWhiteFade(AudioClip newClip, float transitionTime = 1.0f)
    {
        AudioSource activeSource = GetActiveSource();
        StartCoroutine(UpdateMusicWithFade(activeSource, newClip, transitionTime));

    }
    private IEnumerator UpdateMusicWithFade(AudioSource activeSource, AudioClip newClip, float transitionTime)
    {
        if (!activeSource.isPlaying)
            activeSource.Play();

        float t = 0.0f;

        for (t = 0; t < transitionTime; t += Time.deltaTime)
        {
            activeSource.volume = (1 - (t / transitionTime));
            yield return null;
        }

        activeSource.Stop();
        activeSource.clip = newClip;
        activeSource.Play();

        for (t = 0; t < transitionTime; t += Time.deltaTime)
        {
            activeSource.volume = (t / transitionTime);
            yield return null;
        }

    }

and the audiomanagertest:

[code=CSharp]using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioManagerTest : MonoBehaviour
{

    [SerializeField] private List<AudioClip> audioClips;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            AudioManager.Instance.PlayMusicWhiteFade(audioClips[0]);
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            AudioManager.Instance.PlayMusicWhiteFade(audioClips[1]);
        }
    }

   
}

}[/code]

I choose 2 elements to try but it doesn’t respond…there is no error but also no music. it gives me this warning:

Assets\AudioManager.cs(32,48): warning CS0649: Field ‘AudioManager.audioClips’ is never assigned to, and will always have its default value null