How do i make npc optimized?

i use runservice.Heartbeat to constantly move the NPC towards the player and attack them but it’s very unoptimized especially with alot of enemy NPC constantly doing checks so is there a way to make this more optimized?

example code

local function moveToTarget(target)
	local path = pathfindingService:CreatePath({
		AgentRadius = 2,
		AgentHeight = 5,
		AgentCanJump = true,
		AgentJumpHeight = 5,
		AgentMaxSlope = 45,
	})

	local targetHRP = target:FindFirstChild("HumanoidRootPart")
	if not targetHRP then return end

	path:ComputeAsync(HRP.Position, targetHRP.Position)
	if path.Status == Enum.PathStatus.Success then
		for _, waypoint in ipairs(path:GetWaypoints()) do
			Hum:MoveTo(waypoint.Position)
			Hum.MoveToFinished:Wait()

			local distance = (HRP.Position - targetHRP.Position).Magnitude
			if distance <= StopRange then
				return
			end
		end
	end
end

local function StartAI()
	updatePlayers()

	Alive.ChildAdded:Connect(updatePlayers)
	Alive.ChildRemoved:Connect(updatePlayers)

	connection = runservice.Heartbeat:Connect(function()
		local closestPlayer = findClosestPlayer()
		if closestPlayer then
			local distance = (HRP.Position - closestPlayer.PrimaryPart.Position).Magnitude
			if distance > StopRange then
				moveToTarget(closestPlayer)
			else
				M1(closestPlayer)
			end
		end
	end)
end

i don’t know if this would be more optimized, but instead of calling heartbeat for every enemy, you could try using heartbeat and then moving every enemy

runservice.Heartbeat:Connect(function()
    for i, enemy in pairs(enemyFolder:GetChildren()) do
       -- do something
   end
end)