How many parts is too many parts?

Greetings,

I have a general question regarding how many parts is too many. I am looking at these trending tycoon games like OOF tycoon and Slime Tycoon which have noobs/slimes respectively that produce little spheres that roll down into the collection pit. Each player can have hundreds of noobs/slimes at once, meaning you’d potentially be spawning 10000(the uppermost extreme) parts every few seconds.

Now these games handle this by either creating the spheres on the client of the nearby players, or by just not animating other tycoons than the players at all and spawning nothing. But i dislike both solutions as the first is just lying to the player and when you compare your and your friends screen looking at the same tycoon it looks different, and if you don’t animate other tycoons it just feels kinda lonely on the map.
With all that said, I have been considering just using PartCache to cframe the spheres for each tycoon as needed and using streaming enabled to limit the stress on the client.
My question is, what is like best practice or a known soft limit in roblox for how many moving parts you can have in a relatively small space before it becomes too laggy to be considered practical/playable?

Thanks for your time

2 Likes

Unfortunately, while perhaps you can create a system that works the way you’re wanting, it’s really not worth the effort. There’s no reason to render anything that you can’t even see to begin with. It’s also a bit ridiculous to compare screens when you’ll normally never see the other person’s screen. I also wouldn’t really call it lying when everything about a game can technically be called a lie.

In short, don’t worry about things like that. As developers, we must make the necessary sacrifices in order for our games to run the way want them to. The only time syncing needs to be super accurate is for something like player or enemy positions. Even then, nothing can be 100% synced, but there are ways to make it pretty close and hardly noticeable.

May I ask which approach you would choose in this situation? Or, rather, what would you sacrifice?

1 Like

Well it depends exactly what you’re talking about. If you’re talking about little balls being dropped onto a conveyor, then I would definitely only do that client-side and only if near enough to the machine/tycoon.

Now there are some things you could do to keep it more in sync and even resume so it doesn’t appear like it’s been off the entire time. You could have the server have a list of timestamps of when a given dropper has dropped something. The server would only be generating timestamps in a list, not actually spawning anything else, and it would do that in whatever intervals you give it. The client can then read off the list of any given dropper and spawn the ball where it should be given the time difference between the listed timestamp and the current time. Also make sure to clear items in the list that would have reached their goal already.

2 Likes

This is kind of a fun thought experiment. I’d be curious though if having the parts being physically simulated is a requirement?

Is it possible to use a CFrame based movement instead? If so syncing the “slime balls” would be very feasible. The server could be responsible for “spawning” a pseudo slime-ball object reference with a spawn time as workspace:GetServerTimeNow() so you’re able to determine where the slime-ball would be mathematically and with information about where they spawned and whatever you need to simulate the movement on the client then you can send these pseudo slime ball objects in batches to the clients and then on the client you can spawn the slime ball (perhaps if its spawn location is within a reasonable distance) and then simulate the slime balls with a custom tweening function using something like workspace:BulkMoveTo(). Given a know time to goal you could clean up the objects on a timer as well. Obviously this is a very technical solution but it would be significantly faster than using anything physics based. I would add that PartCache is definitely a beneficial thing to use here since instantiating objects is rather expensive (so is destroying them).

I wrote all of this not realizing that @MightyDantheman basically said the same thing but with less detail. Anyway, fun problem to solve.

Depends on how powerful your computer and internet are, 10K+ parts is meh but anything over 25k parts could cause some lag

Part count doesn’t matter at the slightest. Worry about server memory only. Don’t use terrain either, as it causes major performance drops.

  • Make sure the parts are anchored and they aren’t welded.
  • Make sure the parts aren’t meshparts.
  • Turn on StreamingEnabled
  • Make sure that the parts don’t have any child (like a decal) parented to them.

This will make your game faster. Part count doesn’t matter very much.

2 Likes

Part counts definitely do matter. The number of vertices and triangles that the GPU has to render can most definitely cause performance issues. However, this only applies to the client as the server isn’t doing any rendering. Also physics simulations are what cause the most “lag” for processing.

I know that your points mostly solve those issues and are good guidelines, but it’s important to not discount the reality and details of it. You can tell somebody to do something, but if you never tell them why, it’s hard for them to truly learn from that. Also StreamingEnabled isn’t always the best option and requires a different thought process when writing code (because object persistence will no longer exist and WaitForChild is no longer a solution on the client, plus it may break certain systems that weren’t made for that). But it’s definitely a good system to use if you can write functional client-side code with it as it bases it’s content streaming on the client’s specs, performance, and availability.

tl;dr:
Part counts most definitely do matter, especially the more complex the parts are, and if physics are being applied. If you use the points that @SubtotalAnt8185 gave, you’ll mostly avoid those limitations, however it’s important to understand those limitations as there’s more than one way to optimize and still get the outcome you wish (even without using StreamingEnabled or even having many physics objects).

3 Likes

Just wanted to give some advice about the correct way of using streaming on the LocalScripts:

This is something I considered when writing my post. However, you should not be relying on waiting for something in Workspace to begin with. All parts you want should be created from the client or parented under the client’s character.

For generic objects (such as one-way doors), ChildAdded or DescendantAdded should be used, since you aren’t directly pointing to an object.


Physics simulation is not a valid concern. If performance issues still persist, turn off CanCollide, CastShadow, CanTouch, and CanQuery as needed.

GPUs that render this can be solved with streaming. If it looks bad, an atmosphere is what will fix that.

Now, if you have many parts in the same area, that’s a problem. A way to solve that is to remove PBR textures and change the lighting technology to Compatibility.

Now, if you say I’m crazy, I actually preferred Compatibility over Voxel any day back in 2019. When shadowmap came out, I switched to that. If you want a good result with Compatibility, add a ColorCorrectionEffect and change the contrast up to 0.1 or 0.25. A good result will come from it.

1 Like

I’m not sure what you mean about WaitForChild not being used, unless you mean not using them for StreamingEnabled, in which case yes. Otherwise, WaitForChild should most definitely be used outside of that.

Also on the second part, even non-physics objects can cause lag. This is more so for lower-end devices, but complex models/meshes can be a big source of lag. Streaming can definitely fix this, but so can zoning, among other methods. If you want to be particularly clever, you can use a custom streaming system that is based on visibility, or just go with an LoD system. My point mainly being that there are other options other than StreamingEnabled. I’d rather use those when applicable as Streaming doesn’t look that great for my projects. But that just means that there are options to choose from, so it’s just a matter of whichever is best for the given project.

1 Like