For Loop Crashes Game

Hello, I have a for loop that loops through NPCs, but only problem is after a second the game crashes. There’s 50 NPCs which isn’t extremely a lot. So what’s the issue?

Error:

Script timeout: exhausted allowed execution time

Script:

for _, target in pairs(enemyTeam:GetChildren()) do
	coroutine.wrap(function()
		if target and not target:IsA("Model") or not target:FindFirstChild("HumanoidRootPart") then return end

		local targetRoot = target:FindFirstChild("HumanoidRootPart")
		local targetHumanoid = target:FindFirstChild("Humanoid")

		local distance = (rootPart.Position - targetRoot.Position).Magnitude
				
		if targetRoot and targetHumanoid then
			if targetHumanoid.Health > 0 and distance < current_distance then
				current_target = targetRoot
				current_distance = distance
			end
		end
	end)()
end

Also it could be because the for loop is in a while true do loop. So a loop inside a loop would most definitely crash a game. If this is the issue how could I fix it? I could use task.wait(), but this will cause stuttering which I don’t want.

Thank you.

3 Likes

You may add a very small delay so it won’t throttle.

for _, target in pairs(enemyTeam:GetChildren()) do
	coroutine.wrap(function()
		if target and not target:IsA("Model") or not target:FindFirstChild("HumanoidRootPart") then return end

		local targetRoot = target:FindFirstChild("HumanoidRootPart")
		local targetHumanoid = target:FindFirstChild("Humanoid")

		local distance = (rootPart.Position - targetRoot.Position).Magnitude
				
		if targetRoot and targetHumanoid then
			if targetHumanoid.Health > 0 and distance < current_distance then
				current_target = targetRoot
				current_distance = distance
			end
		end
	end)()
    task.wait()
end
1 Like

As he said, task.wait() will cause stuttering, but as far as I know there isn’t really any other workaround to this

2 Likes

Hmm, would separating the loops work? Like if I had another script would it lessen the strain?

I would assume so, however I haven’t been through this situation before so I can’t tell you.

2 Likes

You could make it wait only once every like 10 npcs for example

2 Likes

Try pulling the 3rd line logic into the for loop and pass if it resolves as false. It’s not performant to create coroutines unnecessarily. You could also consider using a run service function. Ideally you’d probably want to find an event driven way to do what you’re doing, though.

How are you deciding when to generate the NPCs? Or are they just generated when a new game instance is made?

2 Likes

As of right now I just have an admin button where you click it and it generates 50 NPCs.

Here’s the updated script:

for _, target in pairs(enemyTeam:GetChildren()) do
	if target and target:FindFirstChild("HumanoidRootPart") then
		local targetRoot = target:FindFirstChild("HumanoidRootPart")
		local targetHumanoid = target:FindFirstChild("Humanoid")

		local distance = (rootPart.Position - targetRoot.Position).Magnitude
					
		if targetRoot and targetHumanoid then
			if targetHumanoid.Health > 0 and distance < current_distance then
						current_target = targetRoot
						current_distance = distance

				end
			end
		end

		if i == 5 or i == 10 or i == 15 or i == 20 or i == 25 then
			task.wait()
		end
	end
end

Edit: After testing the game doesn’t crash with some stuttering. But, I’m curious can I optimize it even more for lower end devices?

1 Like

you can use “if i % 5 == 0 then task.wait()” for small code optimization =)

2 Likes

I found a solution! Instead of always finding for a target I just decided to find a target at one time. If there’s no target it will loop. This is much better optimized and for me I don’t need it to constantly look for target so it works out great. Thank you so much everyone! Combined it works great!