for _, v in pairs(Boosts:GetChildren()) do
if v:IsA("ValueBase") then
coroutine.resume(coroutine.create(function()
while true do
task.wait(5)
if Player then
if v.Value > 0 then
v.Value -= 1
else
v.Value = 0
-- break
end
else
break
end
end
end))
end
end
So the valuebases are basically boosts like ‘X2EXP’, that reduce every 5 seconds by 1, is there a way I can do this without a while loop?
They won’t be. A while loop is just like a for loop. It’s just one “step” in the code, and it chains together the “steps” contained within. If you don’t have any pauses, then you basically get a really long sequence of steps. With an infinite loop, that’s an infinitely long sequence of steps. But this isn’t infinite, and it’s not even very long. You see, you’re waiting five seconds in between executions. So every loop, the sequence of steps takes a break for other scripts on the thread to run for 5 seconds, an eternity in computer time. Then this code runs 10 more steps taking about a microsecond, then another eternity of computer time for other tasks to run. This is about as non-intensive as you can get.
Uh there is an alternative way to achieve the same functionality without using a while loop. Instead, you can use a combination of a Timer and a Heartbeat connection to periodically decrease the Value of the ValueBases.
local function decreaseValue()
for _, v in pairs(Boosts:GetChildren()) do
if v:IsA(“ValueBase”) then
if v.Value > 0 then
v.Value -= 1
else
v.Value = 0
end
end
end
end
local function startDecreasingValues()
local timer = 0
local interval = 5 – Decrease every 5 seconds
local heartbeatConnection
heartbeatConnection = game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
timer += deltaTime
if timer >= interval then
timer -= interval
decreaseValue()
end
end)
Assuming it’s something like the player has 2x EXP for x amount of time it depends on how complicated you wanna get with it. The best way I can think of efficiency wise if you have nothing displaying the remaining time you can probably get away with just using a task.wait with no loop and if your saving it on the player leaving you could get the os.time at the beginning of the wait and than on playerleaving check the current os.time and subtract them to get the remaining time of the wait to save if the wait hasn’t ended. Though I recommend just looping it since it’s really not that intensive when you have a 5 second wait between each loop anyway.
I want to point out that this type of system in this scenario has similar or worse efficiency compared to a while loop. Not that it’s inefficient, and it’s a perfectly reasonable approach. I just want to point out that there’s nothing wrong with while loops.
You’ll also need to adapt the system to reset the timer whenever the value is changed.
This is actually worse. Instead of letting the high-performance C++ backend resume the code every 5 seconds, you’re running several lines of low-performance Lua code approximately 300 times before the timer even expires.
Again, I don’t want to knock your code. It’s not an unreasonable approach and it won’t harm performance much, if at all. But if we’re being ultra-concerned about efficiency here, a simple loop is probably the way to go.