To be honest this question is based on a misconception. Loops aren’t slow. Computers run on loops. Loops are actually really fast.
Sometimes loops appear slow. To show you why let’s make a very simple game loop.
while true do
physics()
userCode()
drawPicture()
end
This is a very simple loop that will run the game. The frame rate you are going to get in this game is determined by how long it takes for the game to reach and complete drawPicture. Of course rendering is super complicated at times and so is physics. So to make everything easier we aren’t going to handle any of that. Instead we will write userCode. Now let’s put this in
local userCode = function()
while true do
print("a")
end
end
After running that, the application will stop responding. This is because that code never stops to allow the rest of the code (like the drawPicture function) to run. Though the game is still running, it’s essentially useless now since you will never see an update.
But if your loop only went a handful of times instead of forever, the game would be fine. Additionally if you could somehow tell your loop to pause itself so the rest of the code could run, the game would still run fine as well. This second option is basically what wait(x) is doing. It’s letting Roblox know your code is ok to stop for x seconds so it can do the stuff it needs to do like rendering and physics.
So an infinite loop will break the game if you don’t yield. Since you have a wait though, there is no issue.
Also when you consider the recursive function that you accepted as your answer, it’s just a loop with extra steps. The most you could optimize that function to behind the scenes is going to be the same as a while loop. So you will save no time. In fact, depending on if and how it’s optimized, it might be worse. It can’t be better though.
Also if you are wondering why events are generally better to use, it’s because Roblox is determining somewhere in its game loop when to run the code you connected. So in the end connections are loops too, it’s just taking advantage of information roblox already has and only running your code when needed.
Though I would recommend styling your wait like @domboss37 does so you’re waiting for the audio to end based on when it decides it’s over. It will just make your code more resilient. For example if you were to change the playback speed at all, your current code would break, but the event:Wait() code would still work flawlessly.
tldr; Your code is fine how it is originally. It’s just a misunderstanding causing this question.