So, the game I’m making has a zombies folder in the workspace. When a round start, I add zombie models to the folder which are then handled by a single while loop like this:
local RunService = game:GetService("RunService")
local PathFindingService = game:GetService("PathfindingService")
local ZombiesFolder = game.Workspace.Zombies
local Path = PathFindingService:CreatePath()
while true do
RunService.Stepped:Wait()
for _, v in pairs(ZombiesFolder:GetChildren()) do
if v:IsA("Model") and (v.Humanoid.Health > 0) then
local target = getClosestPlayer(v.HumanoidRootPart)
if target then
Path:ComputeAsync(v.HumanoidRootPart.Position, target.Character.HumanoidRootPart.Position)
local waypoints = Path:GetWaypoints()
if waypoints[3] then
v.Humanoid:MoveTo(waypoints[3].Position)
else
v.Humanoid:MoveTo(target.Character.HumanoidRootPart.Position)
end
end
end
end
end
I left out my get closest player script because when I removed it and set it to a single player, lag still occured.
To clarify, what is happening now is that the zombies will move, then pause for a few seconds, then move again. As the player I don’t experience any lag and the zombies move smoothly they are moving
I think it may lag because of how many times your loops repeats. RunService.Stepped(Wait()) means that the while loop runs wait() every single frame. Note that each Wait() is extremely short and this would thus affect performance of the game. I would thus recommend reading this Roblox Blog article on how long you should wait before looping.
In the post, it talks about waiting a longer time such as 5 seconds before the zombie decides to change direction. This reduces the number of calculations per second from a whopping 1500 for just 50 zombies to just 10 calculations per second! This is also similar with reality where zombies are not that smart and would usually choose to follow their target for a while before changing their mind.
Therefore, instead of Stepped, you should wait a longer time before recalculating who is nearer.