Playing Through a Queue/List of Audio Sources, One at a Time
I'm trying to make a queue of audio sources (ended up doing a List), to play one audio clip after another. As the player enters a trigger zone the audio source from the zone is added to the list, and I want an Iterator to go through the list and play each clip once as the user enters new zones. The problem I'm having is when a player moves out of the 'sound trigger zone' and enters a new one, the audio will play over each other. I would like to play one at a time. Audio clips are different lengths varying from 10sec to 1 minute.
What is the best way to do this?
Here is my PlaySound Script which adds the audio source to the list:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
* Play sound when user enters certain zones script.
* 1.) Attach Script to Zone
* 2.) If player torch enters the zone, get the audio source and play
* */
public class PlaySound : MonoBehaviour
{
public GameObject sounds;
AudioQueue audioQueue; //REFERENCE to AudioQueue script
bool hasEntered = false; //boolean to let know if user has entered the zone before
//Get audioQueue script from sound
void Start()
{
audioQueue = sounds.GetComponent<AudioQueue>();
}
//Use on Trigger. Play torch has the rigid body
//Sound is attached to this zone object
private void OnTriggerEnter(Collider other)
{
//if the thing entering the zone is the player's torch and they have not entered before
//then make the boolean true, get the audio source and if it is not playing, play the audio
if(other.CompareTag("playertorch") && hasEntered == false)
{
hasEntered = true;
Debug.Log("Entered Zone");
PlayAudio();
}
}
public void PlayAudio()
{
AudioSource audio = GetComponent<AudioSource>();
audioQueue.AddAudioSourceToList(audio);
Debug.Log("Size of audio queue: " + audioQueue.getSize());
audioQueue.AudioPlay();
}
}
And my AudioQueue:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
* Keep a queue of audio files to play when called
* If user enters a Sound Zone, the audio should be placed in the queue to be played once the previous
* audio source finishes playing
* */
public class AudioQueue : MonoBehaviour
{
//Changed to list
List<AudioSource> audioQueue = new List<AudioSource>(); //Queue of audio files, can grow as needed
AudioSource currentAudioSource; //current audio source
int index = 0;
bool hasAudio;
/*
* If no audio is playing and there are audio source in the queue:
* 1.) Get the currentAudioSource
* 2.) Play the audio,
* 3.) Get the next audioSource from the queue
* 4.) Play that audio
*/
public void AudioPlay()
{
foreach (AudioSource sourceAudio in audioQueue)
{
if (!sourceAudio.isPlaying && hasAudioInQueue() == true)
{
sourceAudio.Play(); //play audio source
}
}
}
/* This checks to see if there is audio in the queue
*
* */
private bool hasAudioInQueue()
{
if (audioQueue.Count > 0)
{
hasAudio = true;
}
else
{
hasAudio = false;
}
return hasAudio;
}
/*
* This is to communicate with the PlayAudio script
* If a player runs into an audio zone, Play Audio will add the audio source to the queue and then start the play function
* */
public void AddAudioSourceToList(AudioSource audioSource)
{
if(audioSource != null)
{
audioQueue.Add(audioSource);
Debug.Log("Added Audio To Queue! Size: " + audioQueue.Count);
}
else
{
Debug.Log("Cannot add audio, no source found");
}
}
public int getSize()
{
return audioQueue.Count;
}
}
Answer by tormentoarmagedoom · Jul 13, 2018 at 12:09 PM
Good day.
best way is to have 1 audioSource, assign the clip you need, play it, and check when the audio has finished by using IsPlaying
AudioSource.isPlaying()
that returns false while is playing, and true one it has finished. So you can then change the AudioClip of the AudioSource, and play again.
void Update()
{
if (!audioSource.isPlaying)
{
audioSource.clip = otherClip;
audioSource.Play();
}
}
Note: AudioSource.isPlaying will return false when AudioSource.Pause() is called. When you use AudioSource.Play() again back, it will return true.
Bye!!
Thanks. I am fairly new to program$$anonymous$$g and Unity so am not quite sure how to do this though. I have multiple sound zones (let's use the example of a box and say that there is a zone on each side). Each side has a collider tagged 'zone' and an audio source, when the player enters the zone I want it to get the sound and play. Players should wait until the audio finishes to move to the next zone, but do not always follow directions so I want to queue up the audio from each zone and play one after the other (but not constantly). How would I do this with just one audio source?
I thought about the following, but not sure how to best work with it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioTest : $$anonymous$$onoBehaviour
{
//$$anonymous$$ake a Queue of Audio Clips
public List<AudioClip> audioQueue = new List<AudioClip>();
//Have index of where we are at in the queue
int index = 0;
//Get the One AudioSource
AudioSource audio;
public AudioClip firstClip;
public AudioClip secondClip;
public AudioClip thirdClip;
public AudioClip fourthClip;
public AudioClip fifthClip;
public AudioClip sixthClip;
public AudioClip seventhClip;
public AudioClip eigthClip;
bool hasEntered = false;
// Use this for initialization
void Start ()
{
audioQueue.Add(firstClip);
audioQueue.Add(secondClip);
audioQueue.Add(thirdClip);
audioQueue.Add(fourthClip);
audioQueue.Add(fifthClip);
audioQueue.Add(sixthClip);
audioQueue.Add(seventhClip);
audioQueue.Add(eigthClip);
}
void OnTriggerEnter(Collider other)
{
audio = other.GetComponent<AudioSource>();
if(other.CompareTag("zone") && hasEntered == false)
{
hasEntered = true;
Debug.Log("Entered Zone");
if (!audio.isPlaying)
{
audio.clip = audioQueue[index];
audio.Play();
index += 1;
}
}
}
}
Your answer
Follow this Question
Related Questions
Stop AudioSource on Trigger!!! 1 Answer
Audio Endless Loop c# 1 Answer
Playing multiple sounds at the same time? 1 Answer
I have a problem playing an AudioSource 2 Answers