Lag in my game because a for i,v loop is inside of a while loop

i have a gui system where if the player dosent touch a gui element it make them fall like physics . but the problem is everything is fine until you play the game for like 2 minutes and then it starts lagging insanly i figured the problem is that theres a for i,v loop inside of a while true loop . i tried to change it to a runservice. heartbeat but the problem is the same, i dont know how to fix it because it is neccecary for the for i,v loop to be there and the while true loop also. heres the script anyways this was possible using guicollisionservice made by the community

while true do
	task.wait()
	
	if Jumping == false then
	
	for i,v in group:getColliders() do
	
			if not GuiCollisionService.isColliding(player, v) then
			
			falling = true

			player.Position -= UDim2.new(0,0,0.0025,0)
	
		else
			falling = false
			
			break	
			end
		end
	end
end

This is very inconsistent.

What your script is doing, is every frame your client surpasses, that while loop will activate, and not only it runs code inside, but that code has a for loop, which takes more power, resulting in lag.

The actual reason why it lags is because the game has to lower your framerate, so the while loop is more slower, considering it runs every frame.

If it checks if your player is colliding with something, then I’d use an event, probably using :GetPropertyChangedSignal() whenever the player moves.

it says maximum re-entry for instance.changed exceeded

because you are checking if the player moved and if so then move it so its stuck in a loop

The solution I was about to type was similar to yours. Probably should scrap that.


My best option is to make the delay much longer, but short enough. It can be task.wait(0.2) or shorter if you don’t experience lag.

but as i said i need to check every frame because i dont want the player floating for a couple of milllisecs

It doesn’t have to be every millisecond, you don’t have to worry about that. Some games make it quite literally 2-3 seconds.

Firstly this doesn’t run every frame. task.wait() waits for every CPU frame, which usually is below 3ms on modern CPUs.

But anyways, OP, you are doing this wrong. You dont usually use while loops in programming, expecially in games. You need to use a event for this.

To detect if a player moves, there’s no accurate way to do this.

humanoid.MoveDirection

Works but a player might be able to walk without changing direction, to not fire the changed event. And someone can be teleported without the client moving by keyboard or touchpad.

:GetPropertyChangedSignal("Position")

It would work but Roblox decides to not allow this for physics-related properties, for some reason.


You will need loops, but they must not be recurring so quickly, probably every split second.

this is what @DiamondDrencher1 was referring to
I’m assuming you’d want to check if the player’s position changes, based off of your code.
If not, change it

local co

player:GetPropertyChangedSignal("Position"):Connect(function()
    if co then coroutine.yield(co) coroutine.close(co) co = nil end
    co = coroutine.create(function()
    	if not Jumping then	
	        for _, v in group:getColliders() do
    			if not GuiCollisionService.isColliding(player, v) then		
	    	    	falling = true
	        		player.Position -= UDim2.new(0,0,0.0025,0)
    	    	else
    	    		falling = false		
	        		break	
	    		end
    		end
    	end
    end)
    coroutine.resume(co)
end)

based off of the code, it’s probably gui physics and not vector3s

UIs don’t have physics, the position is really just defined as a position on your screen.

like a 2d game, with gravity. I’m not necessarily referring to literal physics

but the problem is your stuck in a loop where the script checks if the player moves and if so then move down it so it gets stuck in a moving loop

I’ve edited it with coroutines.

sadly its still not working the player is still floating in the air it dosent go down