- Home /
How do I play simultaneous sounds one at a time?
I've been at this for days and cannot figure it out.
I have a multikill system that plays a sound as you get each multikill. The problem is when you get too many too fast the sound plays over or cuts the sound prior. I've tried using wait for seconds, wait for audio length, and isplaying. Sometimes it kind of works but the timing of the sound is off by a few seconds. I need each sound to play first then wait.
Is there anyway to play each sound only after the one prior has finished playing?
Here's my code, can someone please tell me what I'm doing wrong.
This is in C#
IEnumerator MultiKills() {
//Wait for multiKill2 sound then play multiKill3 sound
if (!audio.isPlaying) {
audio.clip = multiKill3Sound;
yield return new WaitForSeconds(multiKill2Sound.length);
audio.Play();
}
if (multiKill == 3) { //Or this?
audio.clip = multiKill3Sound;
yield return new WaitForSeconds(multiKill2Sound.length);
audio.Play();
}
}
//Multikill 3 happens
if (multiKill == 3)
{
StartCoroutine(MultiKills())
}
I was following the question but got confused by the contradiction of your title : simultaneous sounds one at a time ?
The trouble you're having is you have no way of stopping the co-routine being called again while it has already been called and is yielding. So for every event, the coroutine is called and yields, so you end up with a bunch of sounds at the event and again after the yield for each call to the coroutine.
$$anonymous$$y immediate suggestion is to put a boolean somewhere. If is yielding, make the boolean true, so then if the boolean == true, don't jump to the coroutine again. Then after the yield, return the boolean to false, so that the coroutine works again for the next event you want to detect.
$$anonymous$$y problem is that I have 9 simultaneous sounds and I need them to play one at a time. They technically will be playing at the same time script wise I just need some sort of a delay to each of them so they play separately.
I know how to program in js not C# so I'm still learning the differences.
I'll try what you said. I'm trying to use booleans right now but in update they play continuously. I'm not familiar with coroutines so I'll try to figure it out. I'm sure how coroutines work though. How can I have a boolean work with a yield?
for the code you have posted, this is how I would add a boolean :
boolean isBusyPlaying = false;
IEnumerator $$anonymous$$ulti$$anonymous$$ills() {
//Wait for multi$$anonymous$$ill2 sound then play multi$$anonymous$$ill3 sound
if (!audio.isPlaying) {
isBusyPlaying = true;
audio.clip = multi$$anonymous$$ill3Sound;
audio.Play();
yield return new WaitForSeconds(multi$$anonymous$$ill2Sound.length);
isBusyPlaying = false;
}
if (multi$$anonymous$$ill == 3) { //Or this?
isBusyPlaying = true;
audio.clip = multi$$anonymous$$ill3Sound;
audio.Play();
yield return new WaitForSeconds(multi$$anonymous$$ill2Sound.length);
isBusyPlaying = false;
}
}
//$$anonymous$$ultikill 3 happens
if (multi$$anonymous$$ill == 3 && !isBusyPlaying)
{
StartCoroutine($$anonymous$$ulti$$anonymous$$ills())
}
But I don't know C# coroutines either, and am concerned that yield return new WaitForSeconds will return i.e. not execute the isBusyPlaying = false; but you get the idea. At the start, set busy to true, so any other place in your script where you call the method/function also include the conditional check 'am i busy already' is busy == true? Then of course at the end of the coroutine/method/function, set busy back to false. Hope that explains what I was describing =]
Here's some links I found useful in converting between C# and JS :
http://answers.unity3d.com/questions/12911/what-are-the-syntax-differences-in-c-and-javascrip.html
Answer by Loius · Oct 24, 2012 at 03:51 PM
How does this do for you? I'm not 100% on my C#-Coroutine syntax, but the logic should work.
I'm thinking in your original code that you're triggering Sound1 at 0 seconds, and it's 2 seconds long. Then Sound2 triggers at one second, but then it waits for 2 seconds (instead of the one it should wait for).
private List<AudioClip> queue;
void Start() {
queue = new List<AudioClip>();
StartCoroutine(AudioCorou());
}
/*whatever type Coroutines require*/ AudioCorou() {
while ( 1 ) {
if ( queue.Count > 0 ) {
audio.clip = queue[0];
audio.Play();
yield return new WaitForSeconds( queue[0].length );
queue.RemoveAt(0);
}
yield;
}
}
void PlaySound( clip : AudioClip ) { queue.Add(clip); }
If you want to get away from the constant-yield coroutine, you could set it up to only play while queue's not empty, and then when you add an element to empty queue, start the coroutine then (instead of in Start).
Answer by Magarthryx · Oct 21, 2012 at 11:32 PM
/something like this?/
public AudioClip multiKill3; boolean queuedMultiKill3; public AudioClip multiKill5; boolean queuedMultiKill5;
void Start() { queuedMultiKill3 = false; queuedMultiKill5 = false; }
void Update() { if(!audio.isPlaying){ if(queuedMultiKill3){ queuedMultiKill3 = false; audio.PlayOneShot(multiKill3); }else if(queuedMultiKill5){ queuedMultiKill5 = false; audio.PlayOneShot(multiKill5); } } }
Thank you I'll try this out, but could you use the code sample I can't really make sense of it.
I tested this out and it doesn't seem to work. Everything still plays at the same time. I don't think it's logically correct because all the bools are always false so it defeats the purpose of using them. I appreciate the attempt though.
Yes, Please be sure to format the code in any answer or comment.
if I'm not mistaken, this code is utterly, totally, completely incorrect - I'm sorry.
(also, never use "else if")
there seems little reason not to Delete this answer, it doesn't help future readers, it's supposed to be a site of long-term value
Your answer
Follow this Question
Related Questions
audio.Play ignoring WaitForSeconds 2 Answers
yield new wait for seconds: what does "new" do? 1 Answer
OneShot Audio not playing 1 Answer
Is there a way to wait a certain amount of time before the audio plays again 0 Answers
Wait five seconds 2 Answers