Basically it all boils down to how much code you are running at any given time. To really increase the amount of enemies you can have before the game slows down, you need to find a way to reduce the amount of resources each enemy takes up. So let’s break down what each enemy is doing.
Firstly you have this tofind function
local function tofind()
for i,v in pairs(workspace:GetChildren()) do
if v:FindFirstChildOfClass('Humanoid') and v:FindFirstChild('HumanoidRootPart') and v ~= script.Parent then
return v.HumanoidRootPart
end
end
end
This is slow. You are asking your code to run through every item in workspace. Doing this once or twice is ok. (though the fact it returns once it finds one is good) But you are doing this every time in the loop later. That means for every enemy in the game, they have to go through all the items in workspace. That leads to a ton of wasted time. To improve this, we need to reduce the search space.
You seem to be interested in finding players. A better solution for this is to just search for characters of players
for _, player in pairs(game.Players:GetChildren()) do
if player.Character and player.Character.Parent ~= nil and player.Character.PrimaryPart then --Just make sure it's a valid character before proceeding
return v.HumanoidRootPart
end
end
It’s worth noting that the code as you presently have it will just find the player that comes first in the list, not the closest player like most games do. But that’s a bit aside from the optimization point.
Now for the next part
while wait() do
if hum.Health <= 0 then break end
local enemy = tofind()
if enemy then
hum:MoveTo(enemy.Position)
end
end
The only problem I really have with this part is that you are doing wait() with no parameter. The problem is this will wait the minimum amount of time. Is it really necessary to run your code at 30 times per second? (I think that’s about the default wait, but maybe it was 60) You can make your code run a lot less with barely any impact on how it works by telling it to wait for a quarter or a third of a second.
while task.wait(0.25) do
if hum.Health <= 0 then break end
local enemy = tofind()
if enemy then
hum:MoveTo(enemy.Position)
end
end
From how your code is, that’s about the best I think I can do. There are some things that are a bit more complicated to optimize, but those tend to be game specific like despawning enemies that don’t need to be active at the moment.