Multiple heartbeats for different enemies, or same heartbeat for all enemies?

My game has enemy NPCs, and my current way of handling them is to connect a new heartbeat event everytime their target changes (for instance, when a player hits them they switch target to that player) and disconnect the old one. I am unsure if the way i’m handling them is going to become an issue once a big number of players are all fighting different NPCs.

One of the places of my game currently has reached over 70 NPCs, and will get more soon enough. Is my method fine as it is currently, or is there a better method? As I asked in the title: is it better the way I am currently using, or having one single connection that manages all the NPCs (i’d be using a table) would be better in terms of performance and lag?

Note that each NPC performs a new action every 0.1s, not every actual heartbeat. I use os.clock() and, in each heartbeat, I check if the last action was performed more than 0.1s ago (and in that case tell the NPC to execute a new action).

This is an example of how the code works currently:

for _, NPC in ipairs(workspace.NPCs:GetChildren()) do
   local Target = NPC:WaitForChild("Target");
   local Module = require(NPC.Actions);
   local LastTarget = nil;
   local Connection = nil;
   Target.Changed:Connect(function(NewTarget)
      if NewTarget == LastTarget then
          return;
      end;
      if Connection ~= nil then
          Connection:Disconnect();
      end;
      local Clock = os.clock();
      Connection = RunService.Heartbeat:Connect(function()
          if os.clock() - Clock >= 0.1 then
             Clock = os.clock();
             Module.Perform(NewTarget);
          end;
      end);
   end);
end;

As you can see, a new connection is done singularly per NPC instead of using a single connection and manage all of them.
*Forgot to mention that the game isn’t out yet so I can’t test it on a large scale.

3 Likes

It won’t be much different either way. The best way to prevent lag in this case is to decrease the amount of times per second you need to call Module.Perform(). Also you should be using tick() instead of os.clock().

I see. Then I might just switch to a table system so my code gets cleaner.

Why tick()? Isn’t it deprecated, and isn’t os.clock() pretty much the same thing?