- Home /
How do I gaplessly change music clips in a script?
I'm working on a project that is going to have dynamic music. I have all my music clips in an array, and I switch to another clip whenever I want the music to vary.
Right now, I just play one clip, and in the update loop, I check if the audio is playing. If audio.isPlaying is false, I tell it to play the next clip. However, this makes a small gap in the audio that isn't present if I simply "loop" one clip. This is distracting and stifles the energy of the song.
How can I eliminate this gap?
Could you rampDown volume of ClipX while transitioning/rampUP volume of ClipY
An AudioSource can only play one clip at a time though, right? How would I have to clips playing at once?
No, you can play multiple audio clips at the same time. Example here http://answers.unity3d.com/questions/52017/2-audio-sources-on-a-game-object-how-use-script-to.html
http://answers.unity3d.com/questions/175995/can-i-play-multiple-audiosources-from-one-gameobje.html
Answer by rejwan1 · Feb 08, 2014 at 01:02 AM
We solved this issue by writing a cross-fading script. Think of it as a DJ cross-fades two songs together - he lowers the volume of the currently playing song while raising the volume of the 2nd song.
A simple "value to tween" can be used to crossfade easily with two audio sources - which luckily for you, iTween supports (http://itween.pixelplacement.com/documentation.php#ValueTo)
Pseudo code for CrossFader.cs :
AudioSource first, second;
private void CrossFade(AudioClip fadeTo)
{
// create a hashtable with from 0 to 1, with a 1 second time, calling CrossFade
iTween.ValueTo(gameObject, hashTable);
second.Play(fadeTo);
}
private void CrossFade(float currentValue)
{
first.volume = 1 - currentValue;
second.volume = currentValue;
}
Answer by thekingofclubs · Aug 21, 2014 at 11:05 PM
I played around with this issue too and after trying all kinds of things the best result I got was using FixedUpdate. I realized that the gap occurred because Update is called only once per frame and that meant the new track loaded at the beginning of the new frame. So until the new frame loaded there was a slight but noticeable gap. FixedUpdate is called multiple times per frame, not always, but most of the times. This code might help:
var bgMusicArray : AudioSource[]; //Add audiosources in the inspector
private var bgMusic : AudioSource;
var playNext : boolean = false;
function FixedUpdate()
{
if(!bgMusic.isPlaying)
{
playNext = true;
}
if(playNext)
ChangeMusic(2);
}
function ChangeMusic(musicNumber : int)
{
if(playNext)
{
playNext = false;
bgMusic = bgMusicArray[musicNumber];
bgMusic.Play();
}
}
The result is not completely satisfactory, I will keep working on this but for now it suffices.
You shouldn't use FixedUpdate; it's only for physics, and typically is called less often than Update since the default is 50fps.
Your answer
Follow this Question
Related Questions
How to play several audio cllips one after another. 3 Answers
Slowly fade audio's pitch on key press? 3 Answers
Play audio on keyboard click? 1 Answer