Handle 100 humanoids NPC

I am using MoveTo to handle NPC movements for 100 humanoids with at a rate of tenth of a second. My server script activity is on average 5%. Are the only alternatives using Tweens? If that seems reasonable and it’s other parts of my code please let me know.

5 Likes

You could use lerping, whatever that is. But yes, tweens are definitely the best way to go. You could also use BulkMoveTo()

1 Like

BulkMoveTo is of no help as well as Lerp. Handling tween was a bit tricky because I need precise movements on set location but I’ll figure that out on my own.

I have another question. Is Cloning naturally performance heavy seems to spike every time I spawn in an NPC. Around 0.4% for just spawning one NPC. Does it matter the contents inside of it? What if I clone something and destroy some of the contents before it’s parented to something? Are there tools or documents that goes more in depth on what and how much things puts stress on the server.

Since you were using humanoids, you should get rid of those first. Meshes and unions would probably cause the most performance issues, so you should probably lower the count of those as well. Also, the models should be anchored, and preferably cancollide false with no shadows if that works for your game.

Performance issues not on client. I meant on server. The script stats is the only thing I use to identify any potential issues server sided. I will look into micro profiler but that sees confusing. The client maintains at 60fps

I’m not sure what you mean. All those thing will increase overall performance. If the scripts are running slowly, then you are best reorganizing your code.

I don’t think it’s how I organized my code, it is more so how I approach it. If I clone a model with 100 parts and parent it, would it be the same, activity wise, as cloning a model with 10 parts 10 times and parent it.

So the cloned model is the issue. Lower part counts if the game is laggy. But I have never seen a game that cloned a model, and the player thought- “Uh-oh, script performance is up by .4% (which is very low), so this game is bad.)” If this is an issue, removing some of the stuff in the models should help.

2 Likes

Is 5% script activity for the NPCs causing an issue with the whole game? If not, it’s reasonable and I suggest you keep to it. With 100 Humanoid NPCs I’d be more concerned about network receive/send.

3 Likes

While I would love to delete contents inside of player cloned models I just can’t. I did see a significant reduction in activity by half from 20% to 10% when I spawned 100 humanoids using for loop. I’ll need find ways to add timers/cooldowns and if I don’t see any other solutions I’ll mark this as solution

No issues with the game. I did not spot any drops in frames or script slowing down. I’ll do more research on what the network thing is. I’m not sure what you’re referring to

Sorry I got received on average 61KB

1 Like

Short answer: don’t use Humanoids,
Long answer: you gotta reprogram/program your own humanoid that only operates what’s required, humanoids in general run constant raycast checks for ladders and floor/surface materials. I’d recommend first making a robust movement system, preferably not using body forces, but that should be better then moveto(), then add only the features you require, not want.

2 Likes

I just want to confirm a player model with humanoid affects activity? Cloning a model with bunch of parts apparently does.

What I’m trying to say is any difference using tweens or linear velocity on a humanoid vs non humanoid. I’m seeing if its worth all effort when some features were made available. I’ve already disabled most states. Any way to I disable the raycast checks? My map don’t have hills

I got over that by parenting the NPC in the server camera, and just welding a part in the server workspace that’s used to send over only the root part’s CFrame – then just rendering the NPC model in the client with the occasional signal for whatever action needs to be shown. Had to do it that way since it’s zombies that move really, really fast, but still maintains physical interactions with the world. There were other optimizations I did, but I saved a lot of time by just using normal Humanoids instead of having to create something which would really just end up being like Chickynoid.

Humanoids get a bad rep for sending over more info than necessary, but in my experience it’s usually fine if you’re not doing anything too intensive.

Here’s what that looks like, for anyone curious:

4 Likes

Recommended is below 50, so you may need to do what I did in my reply above – server might end with a clogged network and cause latency if that level of activity is kept like that for too long. Can you tell me more about what you’re using the NPCs for? Is it something super intensive like aggressive hostile NPCs or are they just background NPCs?

Otherwise, I honestly wouldn’t bother and move on to the next thing to work on. Using MoveTo() is alright unless you’re seeing real problems in the game. It’s a whole lot of work and time to spend on a system, and the effort put in (which would be worth it if your game really needs it) might be better spent on other things. This is the same for the cloning issue you mentioned. If the server can handle it and the game keeps running with nothing noticeable to any of your players or testers, then it’s something you don’t have to deal with - at least for now.

2 Likes

I like the idea of rendering the actual npc model on the client (not sure it will be intensive on the client) but I’m a little confused on how to handle server side. If I’m not mistaken, a placeholder part is made on the server and I’ll have to handle its movements?

EDIT [Feb 7, 2024]: Since UnreliableRemotes were released a month after this reply, you might benefit from just using those to stream the CFrame data you need instead of welding a part in the Server workspace to replicate it. This technique is technically a hack. Feel free to read it anyway.

Yep. What I did was:

  1. Make a “Server” and a “Client” version of the NPC. Server version is as barebones as possible, in my case since they needed to interact with the environment and with each other, it’s a zombie with a head, torso, an arm, and a leg – probably not the best, but it worked and I was good with it. This is also the easiest way that I could utilize the zombies we already had, since I was very much satisfied with the way they moved. Client version has all the visuals.
  2. When spawning an NPC, you’ll need to put it in the server’s Camera. This allows it to still be physically simulated in the workspace, but not replicated meaning no data will ever be sent over the network to any player.
  3. You’ll need to send the necessary information yourself. RemoteEvents are the go-to for sending information, unfortunately being “reliable” isn’t the best way to send information that’s streamed per frame. In my case, I just used a copy of the HumanoidRootPart, turned CanCollide/CanTouch/CanQuery off, made it invisible, set its network owner to the server every frame, parented it inside a folder in workspace named “Replicators”, welded it to the Server model root part in the Camera so that it’s always in the position of the actual simulated NPC, then have the clients listen to the ChildAdded event of that folder. This way, I’m using Roblox’s physics replication to handle the CFrame being streamed to every player, which is better than any remote at data that needs to be always up to date (for now).
  4. The only other info I needed from the humanoid was health, I just used an attribute in the part and updated it whenever the actual Server humanoid’s health changed.
  5. Client code is basically when a replicator part is added, clone the Client NPC model, anchor it and CFrame it into position every frame, then run animations. You could see the performance in the videos I linked, that’s 100 zombies being CFramed into place at the “Replicator” part’s CFrame.
  6. I already said it, but you’ll handle all the networking for this setup. I’m still not sure about your use case, but for mine it was just zombie attacks and player weapon hit registers. Health changes weren’t really necessary, and zombie deaths happened when the replicator part was cleaned up and the client code would know that.
  7. Cleanup is just destroying the Server model, destroying the associated Replicator part, the client listening to the .Destroying event, disconnecting any RunService connections, and that’s it.

That’s about it. What I like to do further is to wrap it in a ReplicaService “Replica” so I can just send state updates that way for more complicated things, but I didn’t need to do that for this one since it was pretty simple and straightforward.

16 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.