I would like to be able to stop playing a sound when the TimePosition property of a sound reaches or exceeds a given value without resorting to a wait loop. I propose adding a callback to the Sound object that would be called when the TimePosition exceeds a provided value.
Today:
sound.TimePosition = 3.84
local endPos = 6.97
sound:Play()
while sound.TimePosition < endPos do wait() end --Busy wait loop here. Ew.
sound:Stop()
(âFeature Requestsâ > âClient Featuresâ would be the right category.)
Based on this post I donât think they will add additional properties just for looping:
Also you can improve the busy-waiting in your code a bit like this:
sound.TimePosition = 3.84
local endPos = 6.97
sound:Play()
wait(endPos - sound.TimePosition - 0.1) -- solve most of busy waiting
while sound.TimePosition < endPos do wait() end
sound:Stop()
while sound.TimePosition < 5 do
wait(0.1)
end
print(âfinishedâ)
100 millisecond resolution should be enough for almost all game-related cases (we wonât be running any lua on the audio-processing thread obviously).
Thanks for your remarks @EchoReaper. Itâs important to be specific so I will provide more info.
Iâm referring to the software engineering term âBusy waitingâ. Itâs what I was demonstrating in the âTodayâ example in my original post and is generally considered an anti-pattern. My concern is that slower processors may perform poorly with a busy loop. In my scenario, if the sound plays 0.05 seconds beyond the calculated TimePosition the userâs experience will be degraded.
Iâd test it out (best platform for this would be mobile) and see if there were any problems. Unless you are doing hundreds of these at once, there shouldnât be.
Waits in ROBLOX arenât busy waiting, theyâre yields. This means that you check your condition, and if itâs false, you yield and something else runs. Iâm not sure youâd get much of a hit on performance on the slowest of toasters doing that. You can also just bind something to RenderStepped or Heartbeat if you want to be as precise as the engine will ever allow.
I am not claiming that a wait() in ROBLOX is a busy wait. Iâm saying that the code to examine the condition, wait and then loop is a busy wait.
while sound.TimePosition < endPos do wait() end
This while loop is a busy wait.
Yes, there are workarounds. My intent with this FR is to improve the API to avoid anti-patterns. As the primary introduction to programming that ROBLOX is to many burgeoning programmers, weeding out anti-patterns seems worthwhile.
Thatâs not a busy wait, nor is it an anti-pattern. Itâs no different than checking something each frame (if you wait for RunService.Heartbeat), which happens in games all the time. Like I said, ROBLOXâs wait() is not spinning. Itâs yielding. Spinning would be this:
while sound.TimePosition < endPos do end
This is a busy wait, and you donât want this. Yielding, however, solves the complaint that your own Wikipedia link claims:
In general, however, spinning is considered an anti-pattern and should be avoided,[1] as processor time that could be used to execute a different task is instead wasted on useless activity.
There is no need to add a callback for this, either. TimePosition is constantly changing in a predictable manner. Check it on RenderStepped or Heartbeat if you need this. That is literally the canonically correct way. Since TimePosition is changing, a callback would be called every frame anyway.