I wouldn’t give each AI entity their own set of scripts. I would imagine 200 AI trying to run their own logic would become dreadful. I’ve mentioned in a separate thread on how I achieved a large number of NPCs with little backlash performance wise. The way I went about it is by having a single server and local script designated with handling different things regarding your AI
Before all of that…
The method I’m talking about is what I used for civilians walking around to random nodes I serialized to CollectionService…
Avoid Humanoids as much as you can. Like what everyone has been saying above me :). But if you cannot live without them (For clothing), I’d advise setting their HumanoidState to Physics. It will reduce the number of resources they eat quite a bit. In my case, I went with no Humanoid and simply placed ImageLabels on the body for clothing and used AnimationControllers.
For each AI entity, they are represented by a single 1 x 1 x 1 brick that is anchored. I can still use PathfindingService with this so it works out well. Next, I insert StringValues and BoolValues inside the part for the client to be able to read. Like for instance, what type of model is it, its current state, etc etc. Afterwards, once I spawn the Entity I do some math to offset it from the ground and begin Pathfinding. I’d advise Tagging the Entity into CollectionService so if you spawn Entities at random intervals it will be a breeze. Afterwards, I simply CFrame each Entity to their next waypoint, keeping their offset from the ground using the position of the waypoints. Since they just walk around and interact with random things, a simple logic check is quick! Although if you want to get more advanced with the logic you can. I run through the CFrame Update randomly for each object I get too in the Tagged list If I recall correctly. Helps visually keep them from all moving from node to node at the same time. Realism!!!
The client is simply responsible for spawning the humanoidless model. Of course, in order for them to have clothes I had to use ImageLabels (still having nightmares about that). Basically, I had the client set up a few events to each entity to get real-time updates about the entity (change in logic/position). Once the Position event fires, I run a Tween using TweenService to tween the model to the updated position. Of course, you’ll have to time it with when the server updates the part (pretty easy). To top it off, another Event to listen to a StringValue (AnimationState or whatever you want to call it) that tells the client to play a specific animation.
Finally, you type too much Dysplexus…
I never went beyond the threshold of 175 NPCs with this method of mine, however, it never really gave me a problem in terms of performance. Perhaps it is my rig? I’ve tested 90 on an older PC and it handles surprisingly well… unless I’m bugging.