Is 'while true do' fine to use in this situation?

Hi.

I have scripted a function that chooses a random event.

I want this function to run every 5 minutes.

Is a simple while true do script secure and safe enough?

Example:

while true do

functionNameHere()

Wait (300) -- 300 seconds = 5 mins.

end

OR is there a better approach to this?

1 Like
while true do
    functionNameHere()
    task.wait(300)
end

This is probably the most efficient, and safe.

2 Likes

You could have a BoolValue represent the state of the event.

local Bool = script.BoolValue

local function functionNameHere()
	Bool.Value = true
	--Round code here.
	Bool.Value = false
end

Bool.Changed:Connect(function(Value)
	if Value then --In progress.
	else --Not in progress.
		functionNameHere()
	end
end)

Bool.Value = true --Toggle value once to start the chain.
Bool.Value = false
1 Like

Sorry, but why all the hassle just to do the same thing that could basically be done the same with this:

local Bool = false
Bool = true

if Bool then
    while Bool do
        functionNameHere()
        task.wait(300)
    end
end

Bool = false
task.wait(1)
Bool = true

That method is safer and more efficient…

You could also do something like this.


function event()
      --event code here.
end

while true do
      event()
      task.wait(300)
end
1 Like

If you want to make random events try doing this

local events = {"Test1","Test2"}

function startEvent(Name)
	if Name == "Test1" then
		--Event code here
		--Example : print('Hello world')
	elseif Name == "Test2" then
		--Event code here
		--Example : print('Hello world')
	end
end

while true do
	startEvent(events[math.random(1,#events)])
	task.wait(300)
end

Because you’re utilizing yielding code.

Lua is an event-based programming language, you shouldn’t need to rely on indefinite loops.

Not to mention your implementation would only work for a single round, after that the loop would be broken out of.

3 Likes

It’s fine to use it like this to do something every five minutes. But as pointed out it’s better to use indentation and task.wait()

However do keep in mind that any code after this will not execute, unless you put the while loop in a task.spawn.

Similarly, if your function is yielding (that means waiting or other functions that take time), it won’t execute every 5 minutes unless the function call is wrapped in a task.spawn()

The other problem is that now there is no way to stop the loop. If needed you could put it in a function, and add a flag to help it stop. Here’s an untested example I quickly came up with, but in general I personally like this hacky tag pattern for ‘practical’ code.

local waitTime = 300
local tag

function doLoop()
  local myTag = {}
  tag = myTag
  while tag == myTag do
    task.spawn(myFunction)
    task.wait(waitTime)
  end
end

task.spawn(doLoop)
task.wait(999)
task.spawn(doLoop)
task.wait(999)
tag = nil

In any case, do keep in mind that a while-loop is fine to do something simple at a regular interval, but normally most code is part of a larger whole - it can often be more elegantly made part of the ‘flow’ of your game than as a simple static top-level loop. So using this pattern too much (and too high-level) may make it hard to alter that flow (such as stopping the loop). Personally I usually use while(true) without breaks at most once per place, for the core game loop. Because it almost never happens that I want something to go on uncontrollably forever. (and if it does, as @Forummer points out, the implementation generally ends up as a sequence of events triggering each other instead).

1 Like

I disagree with this approach. Just because it uses events doesn’t mean it’s event based programming. The code you have above is basically just sequential programming that fires an event to run a function, instead of just running the function in the first place.

If something is sequential, like waiting 300 seconds then running code, you should just wait 300 seconds then run code.

If you’re really looking for the closing thing to an event based version of this code, a Heartbeat connection might be your best bet. I would just use task.wait(n) though.

1 Like

Apologies for the potential pedantia but events don’t exist in vanilla Lua, you need to create a handler for that (which Roblox abstracts for us with RBXScriptSignal). Lua itself is multi-paradigm and you can adopt an event-driven paradigm in your coding events but aren’t native to Lua so you’re not entirely right there.

Lua isn’t just about, or even at all, about events. Yielding patterns are just as fine as event patterns. In a serious project you ideally do want to use events as much as possible but there are some cases where non-terminating loops are what you need. Experiences that have continuous round timers as a core gameplay loop are often going to fit this bill.

See: Lua: about / Comparison of multi-paradigm programming languages (Wikipedia) / What are events in lua functions (StackOverflow)

CMIIW. Don’t want to offset the thread’s focus too much for this though.


Ultimately for OP’s case it’s completely fine to use while loops since it’s for a round-based system but they may want to consider incorporating events into it so that the round can progress as in when certain things are triggered and not a static amount of time. For example, they can still have a while loop, but an event prevents the next iteration from occurring until its fired.

8 Likes

Events do exist in Lua, they come in the form of hooks.

https://www.lua.org/pil/23.2.html

They allow for you to build reactionary code (event-based).

I’ve removed the “task.wait(300)” line from my previous snippet as it doesn’t fit the example, ideally any code would be executed where that line occupied (of an arbitrary length of time), with the BoolValue acting as a state indicator.

I would be sufficiently worried if you were trying to implement an event-driven paradigm in any Lua-supported language by misusing a debugging function. Hooks being reactionary to VM instructions doesn’t mean it’s opening the door for event-driven programming. You’re welcome to give an example if you think so though.

1 Like

https://www.lua.org/pil/23.3.html

Despite its name, the debug library is useful for tasks other than debugging.

You could just do

functionNameHere()
while wait(300) do
    functionNameHere()
end

Also, you should probably use the new task library for waits, it’s much more accurate. Example: task.wait(300) instead of wait(300)