While loop VS Heartbeat - Help!

Hi. I would like to know if this is an appropriate use of Heartbeat.

My goal is to create tiles that will fall from the sky during the round. This is the best way I could imagine to do this. This does work, but I need to know the best way to do this.

From what I understand, using Heartbeat on the server means it is not affected by the client’s frame rate therefore it will run 60 times per second. However, if I want to create a tile when the amount of time interval has passed then would a while loop be more effective as it would only be looping whenever the amount of time interval has passed as opposed to Heartbeat which would still run 60 times per second? (I guess?)

For example:

while can_Run do
    task.wait(interval)

    -- creating tile
    create_Tile()
end

I see many developers saying that they never use while loops because they are “inefficient” or that they “can’t remember the last time they had a use for one”. The negative things I’ve read of them is the reason why I try to stay away from them, but I don’t understand why they are “bad”.

Any help/feedback would be greatly appreciated.

local game_Module = {}

local rep_Storage = game:GetService("ReplicatedStorage")
local run_Service = game:GetService("RunService")

local game_Status = rep_Storage.Values.game_Status
local round_Status = rep_Storage.Values.round_Status

-- tile config
local tile_Debounce = false
local interval -- this will change as the round progresses

function create_Tile()
	print("running")
	
	if not tile_Debounce then
		tile_Debounce = true
		
		-- creating tile (just printing for testing)
		task.wait(interval)
		print("creating tile")
		
		tile_Debounce = false
	end
end

function game_Module.game_Loop(dur)
	interval = 1
	
	local tile_Connection = run_Service.Heartbeat:Connect(create_Tile)	
	
	for i = dur, 0, -1 do
		round_Status.Value = i
		task.wait(1)
	end
	
	tile_Connection:Disconnect()
end

return game_Module

Your approach to creating tiles that fall from the sky using the Heartbeat event in Roblox is generally a good start, but I understand your concerns about efficiency and timing. Let’s break down the concepts involved and find the best approach for your needs.


Heartbeat:

The Heartbeat event runs 60 times per second (or close to it), which is great for tasks that need to be synchronized with the game’s frame updates.

Using Heartbeat can be advantageous if you want smooth movements or actions that should be consistent with frame rates.


Using while Loops:

A while loop can be used for timed events, but it can be problematic if not handled correctly, especially if you run it continuously without yielding (e.g., with task.wait()). This can cause performance issues, leading to unresponsive or laggy behavior.

When you say developers avoid while loops, it’s often because they can lead to infinite loops or excessive resource usage if not properly managed.


For your scenario of creating tiles at regular intervals, using a combination of the Heartbeat event for smoother gameplay and controlled timing logic might be more effective than a straightforward while loop. Here’s an alternative approach:

Use Heartbeat for Timing: Create a timer using a variable that tracks time since the last tile was created. This way, you can leverage the frame rate while still having control over when to create the tiles.


Here’s an adjusted version of your code that utilizes Heartbeat with a timing mechanism:

local game_Module = {}

local rep_Storage = game:GetService("ReplicatedStorage")
local run_Service = game:GetService("RunService")

local game_Status = rep_Storage.Values.game_Status
local round_Status = rep_Storage.Values.round_Status

-- tile config
local tile_Debounce = false
local interval -- this will change as the round progresses
local elapsed_time = 0

function create_Tile()
    if not tile_Debounce then
        tile_Debounce = true

        -- creating tile (just printing for testing)
        print("creating tile")
        
        -- Simulate tile creation
        task.wait(interval) -- This line can be removed in real implementation.

        tile_Debounce = false
    end
end

function game_Module.game_Loop(dur)
    interval = 1 -- Adjust this based on your game logic

    local tile_Connection = run_Service.Heartbeat:Connect(function(deltaTime)
        elapsed_time = elapsed_time + deltaTime
        
        -- Check if enough time has passed to create a new tile
        if elapsed_time >= interval then
            create_Tile()
            elapsed_time = elapsed_time - interval -- reset the elapsed time
        end
    end)

    for i = dur, 0, -1 do
        round_Status.Value = i
        task.wait(1)
    end

    tile_Connection:Disconnect()
end

return game_Module

This approach combines the benefits of using the Heartbeat for smooth execution with effective timing control, allowing you to create tiles without running into the inefficiencies commonly associated with continuous loops. This should serve your purpose well, providing a balance between performance and responsiveness in your game.

happy coding!

1 Like

Since you are yielding, it would be better to run in a while loop because yielding in a callback is expensive.

You can spawn a thread and then break out of the loop when you are done:

local IsRunning = false

local function Loop(Interval: number)
	while IsRunning do
		task.wait(Interval)
		CreateTile()
	end
end

task.spawn(Loop, 3) -- Start Loop
IsRunning = false -- Stop Loop

Don’t worry about cancelling the thread since it will die once the last yield resumes. This way it won’t cancel before spawning the last tile.

1 Like

Just use whichever is more convenient. The performance difference is very much insignificant

It is a lot more important to optimize parts of code that will have significant impact on execution time, for example, if you are looping a lot of times (and I mean a lot), the core of the loop should be optimized, but what runs the core of the loop (a while loop, or using heartbeat as an alternative, although this doesn’t allow for running things multiple times) this is done once per frame in your case, so the difference, well basically doesn’t exist

Are you using AI, or just sound like a bot? Not to be rude.

3 Likes

You are not wrong to misunderstand because my summary is similar to AI.

I have never used this task.spawn thing so I will look into it. Thank you!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.