- Home /
Music Player Problems
I have written a music player script that plays an array of songs. So far it only has two issues:
When it gets to the end of the array, it says the Index is out of range, even though the array is set back to "0". If you click it multiple times it works.
The first song will play till the end and go to the next song, but then the rest just stop playing at the end.
Heres the script:
var CurrentSong : AudioClip = null;
var SongList : AudioClip[];
var gSkin : GUISkin;
var SongName : String;
var SongNumber : int = 0;
function Start(){
CurrentSong = SongList[SongNumber];
Music = gameObject.GetComponent(AudioSource);
Music.loop = false;
Music.playOnAwake = true;
Music.clip = CurrentSong;
Music.volume = 2;
audio.Play();
NextSong();
}
function Update () {
SongName = CurrentSong.name;
Music = gameObject.GetComponent(AudioSource);
Music.clip = CurrentSong;
if (SongNumber > SongList.length){
SongNumber = 0;
}
if (SongNumber < 0){
SongNumber = SongList.length;
}
}
function OnGUI(){
GUI.skin = gSkin;
GUI.Box(Rect(10, Screen.height-75, 140, 65), SongName);
if(GUI.Button(Rect(15, Screen.height-55, 40, 40), "<<")){
SongNumber -= 1;
CurrentSong = SongList[SongNumber];
Wait();
}
if(audio.isPlaying){
if(GUI.Button(Rect(60, Screen.height-55, 40, 40), "||")){
audio.Pause();
}
}
if(!audio.isPlaying){
if(GUI.Button(Rect(60, Screen.height-55, 40, 40), ">")){
audio.Play();
}
}
if(GUI.Button(Rect(105, Screen.height-55, 40, 40), ">>")){
SongNumber += 1;
CurrentSong = SongList[SongNumber];
Wait();
}
}
function Wait(){
yield WaitForSeconds(0.05);
audio.Play();
}
function NextSong(){
yield WaitForSeconds (audio.clip.length);
SongNumber += 1;
CurrentSong = SongList[SongNumber];
Wait();
}
The Wait()
function is in there to assure the songs play with no error when switching songs.
The first song plays because it is called in the Start()
function but after that, how can i call the NextSong()
function again, without getting a loop error by playing it in the Wait()
function?
All help is much appriciated, and feel free to use this script.
FPSyndicate
Answer by Oliver Eberlei · Jun 18, 2011 at 09:49 AM
You should copy this piece of code
//Edit: As pointed out by aldonaletto, this check should use SongList.length - 1
//otherwise you will also allow the SongNumber to be 3 in a playlist of 3 songs
if (SongNumber > SongList.length - 1)
{
SongNumber = 0;
}
if (SongNumber < 0)
{
SongNumber = SongList.length - 1;
}
And paste it everytime just after you do a SongNumber += 1, or SongNumber -= 1 Better yet, do not update the variable SongNumber diretly, but create a function for it which includes the check.
function UpdateSongNumber( int offset )
{
SongNumber += offset;
if( SongNumber ....
//and the rest of the check
}
If you don't do this, the following situation may occur, which produces the error:
Imagine you have a playlist of 3 songs
You are playing the 3rd song, so SongNumber = 2
You call NextSong()
It waits till the song finishes, then increases SongNumber by one
SongNumber is now 3
You call CurrentSong = SongList[ 3 ], which is out of bounds since your array only holds 3 songs, at index 0, 1 and 2
By the time you check for out of bounds in the Update() function, you already used the too big SongNumber to access the array
Another thing, please format your code properly if you want to get help. Its tedious to read your code which may prevent others from helping you. Ident everytime you open a {
@OliverEberlei, the range checkings at the beginning are doing what you told @FutchProductionsSyndicate not to do; they should be:
if (SongNumber >= SongList.length){
SongNumber = 0;
}
if (SongNumber < 0){
SongNumber = SongList.length-1;
}
Obviously it was a mistyping, since you've pointed out this issue a few lines below.
By the way, another good alternative to cycle an index inside an array is using the modulo operator (%):
SongNumber = SongNumber % SongList.length;
It's more compact, but somewhat cryptic.
Wops. I missed that. Edited for comprehension.. thank you
Thanks for the help, but how can i make the song change when it gets to the end of the song, even if it is paused. Is there a way to pause a courotine?
The same as you are doing right now. Just add the protecting checks to the NextSong() function right after SongNumber += 1;
Your answer
Follow this Question
Related Questions
How to stop audio in a scene when DontDestroyOnLoad was already called? 1 Answer
prevent unity from cutting phone music off? 0 Answers
Use player imported songs? 1 Answer
Background Music 3 Answers
Music Zones play music with tags? 0 Answers