Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

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

Asked by 7 years ago

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
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? iamnoamesa 674 — 7y
0
^ Yeah, that works AstrealDev 728 — 7y

1 answer

Log in to vote
3
Answered by 7 years ago
Edited 6 years ago

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.

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 arthurgps2 67 — 7y
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? arthurgps2 67 — 7y
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. ScriptGuider 5640 — 7y
Ad

Answer this question