Going to start of a loop

So, out of pure interest of testing my capabilities, I started replicating an interactive website on Roblox (more details on this will be on a different thread when it’s finished).

One of the things I need to do is make sure that during a specific time period, when something is clicked, the loop that function is in will be “reset”, so to speak.

I can think of doing this by utilising a click event with connection and disconnections, though it’s a bit finicky.

This part of the code, in a simplified form, is essentially doing this, so far:

while true do
    button.MouseButton1Click:Wait()
    -- appropriate code
    local clicked = false
    local connection = button.MouseButton1Click:connect(function()
	    clicked = true
        -- appropriate frame control code
        connection:disconnect()
	end)
    wait(x) -- where x is the time period
    if clicked then connection:disconnect() break end
    -- more code
end

In this code snippet, I’d be required to somehow restart the loop from within the function. I can think of this via wrapping the loop in a function and call the function when the button is clicked. Is there any better way to go about restarting the loop?

2 Likes

The only plausible way I can think of going back to the start of a loop would be something like this:

function RunLoop()
	local Index = 0
	
	while true do
		if Index >= 3 then
			print("Restarting loop, index will start a 1.")
			RunLoop()
			break
		end
		Index = Index + 1
		print(Index)
		wait(1)
	end
end

RunLoop()

If you were to let that code run you will notice this output:

  1
  2
  3
  Restarting loop, index will start a 1.
  1
  2
  3

Essentially you would want a function that starts the loop, and whenever you plan to restart the loop you would run the function (which will rerun the loop) and then do a break which stops the active loop.

7 Likes

There’s no point for the break with my knowledge of functions? Do correct me if I’m wrong!

When you run a function like in your case, it’ll never break, because when you run a function, it immediately goes through the function, then when it finishes, it’ll continue the code after it. Your code will constantly run the function again before the break.

Also, the question was asking if there was a better way to do this rather than “wrapping the loop in a function and call the function when the button is clicked”. Though, thanks for at least confirming that this method would work (unable to access studio right now to test my theory).

1 Like

You’re actually correct, the break seems to not be required as the new loop will prevent the rest of the code from running in the first place.

I primarily quickly read over your post, but yes your current idea would work, I can’t think of many other solutions as programming languages like C++ have something called continue which gives this functionality whilst Lua does not.

I’ll try to think of some other solutions to make this functionality happen but currently what I’ve posted here is all I can think of.

6 Likes

Alright, you’re contribution is appreciated. Considering how many people have programmed in lua, I’d expect someone to at least have thought of a possible work-around. Worst comes to worst, I can just run it as a function.

For now, I’ll be going offline for at least 9 hours. Good luck!

2 Likes

You could wrap the loop in an outer loop and call break or have the click toggle a script on and off to restart it. But depending on what you’re trying to do perhaps there’s an easier way to achieve that.

1 Like

So disabling a LocalScript and re-enabling it will cause it to restart? Didn’t realise that! (though it was probably obvious…)

I’m trying to make it so that if the players clicks a UI button before they’re meant to, the UI changes to say that it’s too soon and to click again in order to restart the “timer”/wait, however if you call a break within a function thats within a loop, it errors since there’s technically no loop to break.

1 Like

I don’t think that turning a script on and off is the ideal solution.

What you should aim for is some kind of global count variable. When you click the button, it sets this to an arbitrary number and also begins a while loop that counts down from the variable to 0.

Since the variable is global, you can “go to the start of the loop” simply by resetting the variable to its original value anytime.

However, you do eventually need an end condition so you don’t have an infinite loop on your hands. That was the purpose of the break earlier. Alternatively, you can bake a conditional statement into a while loop

variable = 0
— function that triggers loop only if one isn’t already running

while variable > 0 do
    — do stuff    
    wait(1)
    variable = variable -1
end
3 Likes

Correct me if I’ve misunderstood what you’re trying to say.
Your code will essentially go to the “start” of the loop in the sense of how many times it runs.

What I wish to achieve is that it goes to the physical start of the loop, i.e. not running the rest of the code, but instead running the loop again.

In your snippet, even if you were to edit this variable’s value, it’ll continue the rest of the code before restarting the loop.

Also, the idea is that it’s exactly that, an infinite loop! This isn’t designed to go into a “playable” game, more like something I’m creating out of pure interest - hence it keeps repeating the same process until a (different) button is pressed to break the loop - which is already covered.

2 Likes

Sounds like you just want to store a timestamp then, no need for loops at all. If current time - stamp is not large enough you update stamp to be current time.

3 Likes

Hm, so going off the original code, it’d be something like the following?

local currentTime = tick()
local timeStamp = currentTime

local function updateStamps(val)
    currentTime = tick()
    if (currentTime - timeStamp) < val then
        timeStamp = currentTime
        return false
    else
        return turn
    end
end

while true do
    button.MouseButton1Click:Wait()
    -- appropriate code
    local connection = button.MouseButton1Click:connect(function()
        if not updateStamps(5) then
            -- appropriate frame control code
        else
            connection:disconnect()
        end
	end)
    
    while tick()-timeStamp < 5 do game:GetService("RunService").RenderStepped:Wait() end
    connection:disconnect()
    -- more code
end

(Wrote this on the spot, may be logic errors etc, just an idea of how to implement)

2 Likes

Are you trying to make something detect a double click?

2 Likes

You can do a loop in a loop, like a true gamer scripter. Wrap a while true do in a while true do. When the inner loop is broken using break, the outer loop resumes, and then promptly starts the inner loop again.
Like so:


while true do
    --outer
    while true do
        wait()
        --inner
    end
    print(”broken”)
end
4 Likes

How cheat-like! Nice idea - it revokes the need for having to wrap it in a function and call said function (as requested), though just replaces it with wrapping in a loop and adding a break.

@gullet That depends on what you mean by double click. I can see how you’d think that seeing as the loop first waits for a click, before later adding in another click event - however, there’s actually a delay in these two periods, sure players can double click to get past said two periods, but they can also wait between the two clicks and still get the same outcome - which is the idea.

After the first click, there’s a bunch of visual changes on the screen, they then have to wait an unknown period of time for another visual change to click again - if they click too early, the function assigned to the variable “connection” runs.

I’ll test both ideas (from gullet and konlon15) once I can get on studio (probably 30 mins - 3 hours).

Sounds like the easiest thing is to just have a click event that then checks if it’s the first or second click and how well timed it is, no need to to disconnect any events.

There is one solution you could use to achieve going to the start of a loop with what Lua has, you can possibly use repeat which would look like this:

a = 10

repeat
   print("value of a:", a)
   a = a + 1
until(a > 15)

It pretty much goes to the start of the loop each time if a condition is not met and once the condition is met it will end the loop. I don’t know if this would help your use case though.

Here is a flow diagram for how this works though:
image

This is probably not the most ideal solution though.

There are more clicks afterwards, if I don’t disconnect, I’ll have to make the function with it account for multiple scenarios - which I don’t particularly want to do. I intend to make the project open-source when it’s finished, and, honestly, that doesn’t look very pretty :P.

Feel free to explain in detail if you want possibly better methods to build it. In my mind it still sounds easier to have one event always connected and just handle that dynamically.

Yeah, I know how repeat statements work, I would have used one, but a prior post on a different thread has encouraged me to not use repeat statements as much because it can cause unnecessary yielding

i.e.

 clicked = true
repeat wait(1) until clicked

Even though clicked is true, it still waits. Hence, I used another while loop with a RenderStepped:Wait() to minimise yields.

This is what events are for, no need to poll for it.