Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Is there a way to break a while loop outside it?

I want to make a while loop that breaks when a function is called,but i don't know how to do it! Here is the while loop of my script and the function that breaks the loop

while true do
	script.Parent.TweenableValue.Tween:Invoke(thing,'InOut','Quad',20,true)
	repeat
		wait()
	until value.Value==thing
	script.Parent.TweenableValue.Tween:Invoke(-thing,'InOut','Quad',20,true)
	repeat
		wait()
	until value.Value==-thing
	print'done'
end

function play()
	print'play'
	killplayer:FireServer()
	menuSound:Stop()
	button.Visible=false
	con:disconnect()
	script.Parent.ImageLabel.Visible=false
	script.Parent.Frame.BackgroundTransparency=0
	--Break while loop
end

2 comments

0

Have a variable set to true, and instead of while true do, use while VarName do. Then set the bool to false in the function?

0

^ Yeah, that works

1 answer

✓ Accepted answer

Yes, but not in the same way you're trying to do. Loops won't execute the next line of code until whatever condition they're given is met. Therefore, using an infinite while true statement will run the loop forever, never executing the code after the loop's block, meaning your function play was never evaluated.

Synopsis


You typically don't want while loops running in different places (for this to even be possible, coroutines would be involved, which is a whole other story). Whatever it is you're trying to do, there's probably a much better solution for it.

Answer


To answer your question, though, you would want the condition of your while loop to be mutable (not constant). That way, you can change the variable the while loop is using as a condition, to terminate the loop next iteration. Example:

local running = true -- Create condition

-- This is what I was talking about before, with the involvement of coroutines. While this is a solution, I highly don't recommend it for anything other than practice.
spawn(function()
	while running do
		print("Loop is running")
		wait()
	end
	print("Stopped running")
end)

-- Some function that stops the loop outside of itself by setting 'running' to false
local function stopRunning()
	running = false
end

-- Wait 1 second before stopping the loop
wait(1)
stopRunning()

The code above is just for practice, I don't recommend using it in any project you're working on. However, this would be the answer to your question. If need help understanding anything, just let me know.

Edit:

Adding a "pause and play" mechanic

Creating a "pause and play" mechanic to a loop, would implement coroutines. You don't have to use them directly, but they're being used one way or another (with other functions like spawn), so I'm going include them in my example.

-- ~ ScriptGuider
-- Library functions
local create = coroutine.create
local resume = coroutine.resume
local yield = coroutine.yield
local status = coroutine.status
local floor = math.floor

-- A pseudo instance to provide interface for a loop
local loop = {}

-- Local pause function, to be used within the loop's code.
local function Pause()
	print("Loop paused from internal coroutine")
	loop.Running = false
	return yield()
end

-- Code that will be run within the while loop.
loop.Code = function(t)
	print("Loop birth time: "..t.." seconds")
	Pause() -- Calling "Pause" to stop the loop until ran externally
	print("Picking up") -- Picks up where it left off when ran again
	wait(1) -- Wait 1 second each iteration
end

function loop:Run()
	local coro = self.Coro
	-- Using a debounce here so we can't resume and already running coroutine
	if not self.Running then
		self.Running = true
		-- Make sure we always have a coroutine to resume
		if not coro or coro and status(coro) ~= "suspended" then
			coro = create(function()
				local timestamp = tick()
				-- The actual running loop
				while self.Running do
					local elapsed = floor(tick() - timestamp)
					-- You could just "return true" from within the loop's "Code" function to stop the loop
					if loop.Code(elapsed) == true then
						print("Loop stopped from internal coroutine")
						break
					end
				end
			end)
			self.Coro = coro
		end
		resume(coro)
	end
end

-- Stop the loop from outside it's coroutine
function loop:Stop()
	print("Loop stopped from external coroutine")
	self.Running = false
end

-- Run the loop
loop:Run()
wait(5)
-- Stop the loop
loop:Stop()
wait(5)
-- Run the loop again
loop:Run()

Looks a bit complicated, as it should for a situation like this. This is probably the closest I could get to giving an example without making an entire task-scheduler. This basically just utilizes the yield function of the coroutine library, which exits the code block's running state, and can be used to queue it up to later be resumed. During this intermediate state, the program can spend time handling other tasks so no time is wasted.

3 comments

0

I got it. Thank you for helping me. I was going to ask another thing about the tween in the loop,but i see i can stop it. Here is your accept :D

0

Also,with this while loop example,you gave me another question (3,actually). Is the code above going to be executed when the condiction is false in the loop? If it does,is the while loop going to execute again if the condiction is true? And the above code?

0

That's something I thought you might ask, but left it out to keep things short. It's pretty easy, you'd just spawn a new function when you call play. Again, wouldn't recommend it, but I'll edit the answer and include it.

This discussion is preserved as it was. New answers, comments, and votes are closed.