I'm trying to make a zombie wave type of game inspired by COD but I have been stuck on a lag problem when npc's pathfind. When there's one zombie pathfinding, it works well, but the more Zombies there are pathfinding, the more they lag and start to break.

Any ideas on fixing or optimizing this problem?

I'm currently using one script to control all zombies in a folder in the Workspace.

local Debris = game:GetService("Debris")

function followplayer(zombie)
	local players = game.Players:GetPlayers()
	
	-- Get nearest player --
	
	local nearestPlayer = nil
	local nearestMag = math.huge
	
	if not zombie then
		return
	end

	for i, player in pairs(players) do
		if zombie:FindFirstChild("HumanoidRootPart") == nil then
			return
		end
		
		local playerCharacter = workspace:WaitForChild(player.Name)
		local magnitude = (playerCharacter.HumanoidRootPart.Position - zombie.HumanoidRootPart.Position).Magnitude
		zombie.HumanoidRootPart:SetNetworkOwner(nil)
		
		if magnitude < nearestMag then
			nearestMag = magnitude
			nearestPlayer = playerCharacter
		end
	end
	
	-- Check if that nearest player exists, then pathfind to that player --
	
	if nearestPlayer ~= nil and zombie then
		local pathfindingService = game:GetService("PathfindingService")
		local path = pathfindingService:CreatePath()
		path:ComputeAsync(zombie.HumanoidRootPart.Position, nearestPlayer.HumanoidRootPart.Position)
		
		if path.Status == Enum.PathStatus.Success then
			local waypoints = path:GetWaypoints()

			for i, waypoint in pairs(waypoints) do
				if zombie:FindFirstChild("HumanoidRootPart") then
					zombie.Humanoid:MoveTo(waypoint.Position)
					zombie.Humanoid.MoveToFinished:Wait()
				end
			end
		else
			if zombie:FindFirstChild("HumanoidRootPart") then
				zombie.Humanoid:MoveTo(nearestPlayer.HumanoidRootPart.Position)
			end
		end
	else
		return
	end
		
	if zombie:FindFirstChild("HumanoidRootPart") then
		local magnitude = (nearestPlayer.HumanoidRootPart.Position - zombie.HumanoidRootPart.Position).Magnitude
		
		if magnitude < 5 and not zombie:FindFirstChild("Debounce") then
			local debounce = Instance.new("BoolValue", zombie)
			debounce.Name = "Debounce"
			nearestPlayer.Humanoid:TakeDamage(20)
			
			Debris:AddItem(debounce, 0.8)
		end
	end
end

local zombies = game.Workspace.ZombieFolder:GetChildren()
	
for i, zombie in pairs(zombies) do
	game:GetService("RunService").Heartbeat:connect(function()
		followplayer(zombie)
	end)
end

game.Workspace.ZombieFolder.ChildAdded:connect(function(zombie)
	game:GetService("RunService").Heartbeat:connect(function()
		followplayer(zombie)
	end)
end)

Any help would be great!