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.
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
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:
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:
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
with the - its says "cannot apply indexing with [ ] to an expression of type âaudioclipâ
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]);
}
}
}