For that, don’t use AudioSource.PlayClipAtPoint
as this will instantiate a new AudioSource
at the position
and clip
you specify via its input arguments, and plays that clip at that position, when the clip is done playing the AudioSource
that got instantiated will get destroyed.
So simply, attach an AudioSource to your gameObject, and play the clips normally with audio.Play
.
Here’s what I just came up for you (tested), it’s a bit hacky, but really cool: The basic idea behind this script, is to use a list of audio clips, each time you press a number, like 1, 2, 3 etc the sound equivalent to that number will get added to the end of the list. Then, we simply play the first clip from the list (at index 0), we don’t do anything till we finish playing that clip, and when you do we remove it from our list. And since it was at index 0, the next clip after it will take its place, so we can still keep playing at the same index
- The variable hasJustStartedPlaying
(just a boolean flag) is very important key for this hack to work properly. See the script to understand the logic.
import System.Collections.Generic;
private var clipsToPlay : List.<AudioClip> = new List.<AudioClip>();
private var hasJustStartedPlaying : boolean;
function Update()
{
if (Input.GetKeyDown ("1")) {
clipsToPlay.Add(sound1);
}
else if (Input.GetKeyDown ("2")) {
clipsToPlay.Add(sound2);
}
else if ....
PlayClips();
}
function PlayClips()
{
// if there's no audio playing, and we haven't started playing yet
if (!audio.isPlaying && !hasJustStartedPlaying) {
if (clipsToPlay.Count > 0) {
hasJustStartedPlaying = true;
audio.clip = clipsToPlay[0]; // we'll always play the first clip, and when we're done with it, we'll nuke it
audio.Play();
}
}
// keep skipping frames while the clip is playing
while (audio.isPlaying)
yield;
// when we reach this point, we're done playing the clip, so we'll nuke it from the list
// why do we need to check for `hasJustStartedPlaying`? well, remove it and see what happens, and try to guess why it happened...
if (clipsToPlay.Count > 0 && hasJustStartedPlaying)
{
clipsToPlay.RemoveAt(0);
hasJustStartedPlaying = false;
}
}
Btw using a Queue
structure instead of a List
in this situation is more suitable, but for simplicity’s sake, I used a list.
EDIT: After reading your comment
“I want it so when you press 1 a sound plays, then if you press 2, 3, 4 etc nothing happens. Not even after the first sound is done. I just want to be able to play a sound when there’s no other sound playing. So I don’t want the sounds to stack on each other.”
The solution becomes rather much simpler:
function Update()
{
var clip2Play : AudioClip = null;
if (Input.GetKeyDown("1") {
clip2Play = sound1;
}
else if (Input.GetKeyDown("2") {
clip2Play = sound2;
}
else if ...
if (!audio.isPlaying && clip2Play != null) {
audio.clip = clip2Play;
audio.Play();
}
}