How can I optimize this loop

Hello!, Currently I am trying to make a Music queue, but I have a problem when a song ends the script removes the Index of the corresponding song in the table, but there comes a time when the loop recognizes the Index as nil, then this generates an error and as a consequence the script breaks and stops working, I would like to know a way to solve it or optimize it

while wait()do
	for Index = 1,#MusicQueue do
		if #MusicQueue >= 1 then
			if PlayDebounce == false then
				PlayDebounce = true
				Sound.SoundId = "rbxassetid://"..tostring(MusicQueue[Index][1])
				Sound.PlaybackSpeed = tonumber(MusicQueue[Index][2])
				Sound:Play()
				repeat wait() until Sound.TimePosition == Sound.TimeLength
				table.remove(MusicQueue,Index)
				PlayDebounce = false
			end
		end
	

Thank you, I hope your help !!!

Could you just have 2 tables, one with all the songs, and the other one would be the table that you use. Then loop through the entire table1, when it is empty just duplicate everything from table2 back into table1. Like this:

local originalMusic = {} --should be filled with all the songs

--keep the MusicQueue the same

while wait()do
	for Index = 1,#MusicQueue do
			if PlayDebounce == false then
			PlayDebounce = true
			Sound.SoundId = "rbxassetid://"..tostring(MusicQueue[Index][1])
			Sound.PlaybackSpeed = tonumber(MusicQueue[Index][2])
			Sound:Play()
			repeat wait() until Sound.TimePosition == Sound.TimeLength
			table.remove(MusicQueue,Index)
			PlayDebounce = false
		end
    end

     for ii, song in pairs(originalMusic) do
             table.insert(MusicQueue, song)
     end
end
1 Like

You would do

while wait()do
	for Index = 1,#MusicQueue do
		if #MusicQueue >= 1 then
			if MusicQueue[index] then --checking if the element in the table is not nil.
				if PlayDebounce == false then
					PlayDebounce = true
					Sound.SoundId = "rbxassetid://"..tostring(MusicQueue[Index][1])
					Sound.PlaybackSpeed = tonumber(MusicQueue[Index][2])
					Sound:Play()
					repeat wait() until Sound.TimePosition == Sound.TimeLength
					table.remove(MusicQueue,Index)
					PlayDebounce = false
				end
			end
		end
	end
end

Tell me if that works.

Though, I thought I should mention that the code you wrote skips 1 song each time the iteration runs.
This happens because when you use table.remove() on a table, not only does it set the index element to nil, it also shifts the rest of the elements to the left.

If your first iteration is something like
index = 1

MusicQueue = {sound1,sound2,sound3,sound4}
print(MusicQueue[index])
table.remove(MusicQueue,index)

it will output sound1.

But, the second iteration will be
index = 2

MusicQueue = {sound2,sound3,sound4}
print(MusicQueue[index])
table.remove(MusicQueue,index)

which will output sound3, instead of sound2, because table.remove shifted the rest of the elements to the left.

To prevent this from happening, you should instead use MusicQueue[Index] = nil. It will not shift the elements.
Or, you could just change all the “Index” in your code, to 1, so it always uses the first index of the MusicQueue. table.remove() will shift your elements to the left each iteration so you don’t need to increment Index.

Edit: if you need the MusicQueue to reset after the table is nil, then do what @XdJackyboiiXd21 said, though you still need to add my if condition and fix the problem I mentioned.

Edit2: Actually, I found out that you will never get nil if you just fix that problem I was talking about.

1 Like

Remove the for loop and always use position 1. I also optimized it a little bit since that’s what you asked.

while true do
	if #MusicQueue >= 1 then
		Sound.SoundId = "rbxassetid://"..tostring(MusicQueue[1][1])
		Sound.PlaybackSpeed = tonumber(MusicQueue[1][2])
		Sound:Play()
		repeat wait(.25) until Sound.TimePosition == Sound.TimeLength
		table.remove(MusicQueue,1)
	else wait(1)
    end
end
1 Like

I just tried but there is a problem when I add another element to the table the table reads the next element, for example in the table it has an index of 0 so when I add the music to the table the index increases to 1 so everything remains normal in this point but if I add another song to the table it skips the first song that was there and plays the one that was added, How do I fix this? It even plays the song completely ignoring the Debounce

I don’t quite understand what is the problem. What has the index of 0 in the table? Could you send me the script that you have got after all the modifying?

This should work.

--1 == ID, 2 == PlaybackSpeed.
local PlayDebounce
local MusicQueue = {}
local Sound = Instance.new("Sound")

while wait() do
	--table.getn(Table) is the same as #Table.
	if table.getn(MusicQueue) > 0 and not PlayDebounce then
		local Music = table.remove(MusicQueue, 1)
		
		PlayDebounce = true
		Sound.SoundID = "rbxassetid://" .. Music[1]
		Sound.PlaybackSpeed = Music[2]
		Sound:Play()
		Sound.Ended:Wait()
		PlayDebounce = false	
	end
end

--To add music to queue, use table.insert().
local Music = {123231444, 0.5}
table.insert(MusicQueue, table.getn(MusicQueue) + 1, Music)

Sound has an Ended event, so you don’t need to repeat wait until the TimePosition equals TimeLength. Also, table.remove shifts the list to the left and returns the value at the position. Concatenating strings with numbers makes it a string so you don’t need to use tonumber().

And, you don’t really need an infinite wait loop. Just play the music once the queue is filled. When the music stops, play the next item in queue.

local PlayDebounce = false
local MusicQueue = {}
local Sound = Instance.new("Sound")

local function PlayQueue()
	--table.getn(Table) is the same as #Table.
	if table.getn(MusicQueue) > 0 and not PlayDebounce then
		local Music = table.remove(MusicQueue, 1)

		PlayDebounce = true
		Sound.SoundID = "rbxassetid://" .. Music[1]
		Sound.PlaybackSpeed = Music[2]
		Sound:Play()
		Sound.Ended:Wait()
		PlayDebounce = false	
		
		PlayQueue()
	end
end

local function AddToQueue(ID, Speed)
	local Music = {ID, Speed}
	table.insert(MusicQueue, table.getn(MusicQueue) + 1, Music)
	PlayQueue()
end

1 Like

And you were right, the Index goes to the left, Good observation, Thank you very much!

You are a god, thank you very much!, I put you in the credits of the script, again thank you very much

I found something weird in the script, I added 4 songs to the queue but in song number 2 I started it when the song was almost finished and then it stopped working for several seconds and the script had a delay of several seconds and started the process again and it was restored but from there on out it does not do the same as before