Is there a certain number of loops that can cause lag?

I just want to know if having many loops such as while loops, or using the RunService Heartbeat or RenderStepped can cause lag. I’m asking this since a swimming system I’m making uses two heartbeat functions from the RunService, and they always run, and then a while loop comes in when certain conditions are met. These are all in one LocalScript. Would several players each having this script get lag, or something like that?

local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local OceanHeight = 395.74
local Swimming = false
local HRP = char:WaitForChild("HumanoidRootPart")
if workspace.CurrentCamera:FindFirstChild("BlurEffect") then
	workspace.CurrentCamera.BlurEffect:Destroy()
end
local Blur = Instance.new("BlurEffect")
Blur.Parent = workspace.CurrentCamera
Blur.Enabled = false
local Underwater = false
local SpacePressed = false

game:GetService("RunService").Heartbeat:Connect(function()
	wait(1)
	if HRP.Position.Y > OceanHeight then
		Swimming = false
	elseif HRP.Position.Y <= OceanHeight then
		Swimming = true
	end
end)

game:GetService("RunService").Heartbeat:Connect(function()
	if Swimming == true then
		Blur.Enabled = true
		script.Parent.Frame.Visible = true
		char.Humanoid.JumpPower = 0
		if HRP.Position.Y < 395 then
			Underwater = true
			Float = game:GetService("UserInputService").InputBegan:Connect(function(input,gameProcessed)
				if gameProcessed then return end
				if input.KeyCode == Enum.KeyCode.Space then
					if Swimming == false then return end
					if HRP:FindFirstChild("UnderwaterForce") then
						HRP:FindFirstChild("UnderwaterForce"):Destroy()
					end
					local UF = Instance.new("BodyPosition")
					UF.Parent = HRP
					UF.P = 50000
					UF.MaxForce = Vector3.new(0,math.huge,0)
					UF.Name = "UnderwaterForce"
					print("Space pressed")
					SpacePressed = true
					while Underwater == true do
						if HRP.Position.Y >= OceanHeight or SpacePressed == false or Underwater == false then 
							UF:Destroy()
							break
							
						end
						if SpacePressed then
							UF.Position = Vector3.new(0,HRP.Position.Y + 6,0)
						end
						wait()
						print("Space pressed, underwater") 
						
						
					end
					
					
					
				end
			end)
			if Swimming == false then
				Float:Disconnect()
			end
			FloatDestroy = game:GetService("UserInputService").InputEnded:Connect(function(input,gameProcessed)
				if gameProcessed then return end
				if input.KeyCode == Enum.KeyCode.Space then
					
					SpacePressed = false
					if HRP:FindFirstChild("UnderwaterForce") ~= nil then
						HRP:FindFirstChild("UnderwaterForce"):Destroy()
					end
				end
			end)
			if Swimming == false then
				FloatDestroy:Disconnect()
			end
		elseif HRP.Position.Y > 395 and HRP.Position.Y <= OceanHeight then
			Underwater = false
			if HRP:FindFirstChild("SwimForce") then
				HRP:FindFirstChild("SwimForce"):Destroy()
			elseif HRP:FindFirstChild("SwimForce") == nil then
				local SF = Instance.new("BodyPosition")
				SF.Parent = HRP
				SF.Name = "SwimForce"
				SF.Position = Vector3.new(HRP.Position.X,OceanHeight,HRP.Position.Z)
				
			end
		end
		
		
	elseif Swimming == false then
		Blur.Enabled = false
		script.Parent.Frame.Visible = false
		char.Humanoid.JumpPower = 50
		if HRP:FindFirstChild("SwimForce") then
			HRP:FindFirstChild("SwimForce"):Destroy()
		end
	end
end)
--while Swimming == true do
	--print(Swimming)
	--if HRP.Position.Y < 395 then
		
	--elseif HRP.Position.Y > 395 and HRP.Position.Y <= OceanHeight then
		
	--end
	
	
	--wait(1)
--end

No, as this LocalScript only affects the client, it generally won’t afect Server Performance to my understanding.

And also, it’s not really a certain number of loops, as the only aspect that causes the “lag” is the content inside the loop.

For example, I can have a million loops, but if there isn’t anything in there, there can’t be anything causing the lag vs. Animation or Tweening etc etc.

Loops don’t cause lag at all. It’s what you’re operating in them that causes latency. With this in mind though, I’d still be fairly cautious of how many loops you set up - you don’t want to be looping unnecessarily and reinventing the wheel with things that can be done without loops. The buildup may eventually cause issues.

The rule of thumb regarding loops is that you don’t run computationally expensive functions in short bursts of time. For example, some games with the legacy zombie/enemy AI script lag because their follow logic scans through all children of the Workspace at the minimum interval that a wait expression can take. You can imagine how costly that’d be if it goes through thousands of children at one time.

Lag isn’t the only thing to consider though - there is also efficiency that you must account for. For example, your current loop connects a UserInputService.InputBegan every frame. You could have that input logic moved out of the scope and have statements that only proceed with functionality as in when the player enters your swimming state.

3 Likes

Heartbeat is not a loop - it is a clock function. This is very different, because with a loop it yields until the next execution whilst a clock function does not yield. This means that you can very easily overlap function calls.

Hopefully this awful diagram gives you an idea of the problem.

9 Likes

Thanks, everyone. These really were great in depth replies.