Is it possible to pause a loop?

I’m making a timer script that runs on mm:ss for my live song player script. I was wondering how I could accomplish to pause the for loop when done song:Pause()

Example
for i = 0, math.round(songTimeLength), 1 do
    Duration.Text = timer(i)
     if pause == true then
        --idk what to  put here:
     end
end

The Example shown is just an example, please do note that this is not the script I’m really using

2 Likes

Probably not the best practice and i’m sure someone will give you a better answer but:

You could nest a loop inside of another loop and break the second loop when pause == true.

1 Like

An easy method is using a bool which you added. Here is what it would look like

local paused = false
for i = 0, math.round(songTimeLength), 1 do
    Duration.Text = timer(i)
     if paused == true then
        repeat wait() until paused == false
     end
end

Feel free to ask me if you have questions. There are other ugly ways for example using WaitForChild on something that doesn’t exist then making it exist. Anyways, hope this helped.

Edit the script and add paused = true to alter when the paused part will occur.

7 Likes

Generally polling is regarded as a bad way to wait for things. A better way would using a bindable event or an your own listener class.

function QuickSpawn(f) coroutine.resume(coroutine.create(f)) end


CreateYielder = function()
	local Yield = {Bindable = Instance.new("BindableEvent"); Paused = false}
	Yield.Bindable.Event:Connect(function() Yield.Paused = false end)
	return Yield
end


local Yield = CreateYielder()

-- example usage
QuickSpawn(function()
	wait(7)
	print("started")
	Yield.Paused = true
	wait(8)
	Yield.Bindable:Fire("stop BEING PAUSED PLAYERS ARE LEAVING CAUSE THEY THOUGHT THE GAME BROKE ")
end)
--------------

for i = 0, 1000 do
	
	if Yield.Paused == true then
		local ReasonIGotWokeUP = Yield.Bindable.Event:Wait()
		print(ReasonIGotWokeUP)
	end
	print("Running")
	wait()
end

And when your done with your yielder just do

Yeilded.Bindable:Destroy() and the GC will take care of cleaning up the table

4 Likes

Too much work man, I’d honestly rather poll, your way would be very efficient compared to mine but mine takes 3 seconds to write :flushed:

1 Like

The CreateYeilder() function would usually be in some common Utility module

    QuickSpawn(function()
    	wait(7)
    	print("started")
    	Yield.Paused = true
    	wait(8)
    	Yield.Bindable:Fire("stop BEING PAUSED PLAYERS ARE LEAVING CAUSE THEY THOUGHT THE GAME BROKE ")
    end)

This wasn’t really part of the yielded though it was an example how to use it.

if Yield.Paused == true then
		local ReasonIGotWokeUP = Yield.Bindable.Event:Wait()
		print(ReasonIGotWokeUP)
	end

Honestly this is the only part, with CreateYielder(). In a real game usually it would only take one more line to use then the polling system.

For your usecase, you should just listen to Sound.Ended:Wait() and Sound:GetPropertyChangedSignal(“TimePosition”):Connect()

But to answer your quesiton. To make a loop yield, you can either use the two following methods

  • Use repeat wait() until condition syntax, however this is both slow and ugly
  • Create a custom yielder system to listen to a bindable’s signal using :Wait()

We also have Coruntinue.Yield() now (which can be used to create this). The reason I know this is in my signal class I have

Listener:Wait() and it uses corunintinie.yield() and corunitnue.running(). In this case I would actually rather use Corunintie.yield() with a custom signal class then using a bindable event.