Big physical assemblies with CanCollide and CanTouch set to false cause extreme fps drops

Reproduction Steps

Short explanation: setting CanCollide and CanTouch to false on big physical assemblies (around 1000 parts) causes them to replicate to other clients a lot more (because physics stop throttling and can update a lot faster), which kills fps of other clients to who these assembly updates get replicated

Long explanation:
My game OneSkyVed's Trolleybuses Place (indev) - Roblox has vehicles with pretty big part count (around 1000 parts per vehicle)

Originally these vehicles were not optimized: a lot of parts had CanCollide and CanTouch set to true, which caused physics to sometimes be pretty slow/be on the edge of throttling (this part will be important later)

When roblox released CanTouch property, I decided to optimize my vehicles collision. I did it by disabling CanCollide and CanTouch on almost all parts of the vehicle (leaving around 20 parts with collision). That optimization worked well, which caused the bug I’m reporting here

The issue is, because now player computers have to process around 20 parts instead of 1000, physics do not have any throttling at all, and that means my vehicles physical assembly was replicating a lot more than it did before. This means other clients have to update position of 1000 parts a lot more often than they had to before I optimized physics, which resulted in extreme fps drops for everyone on the server. I do not have screenshots of this, but I did look into microprofiler, and this information is based on what microprofiler was showing

Expected Behavior

Replication should respect amount of BaseParts in a physical assembly, and replicate bigger assemblies less frequently, meaning FPS will not drop from replication

Actual Behavior

FPS drops severely as huge 1000 parts physical assembly gets replicated and its position gets updated too frequently for an assembly of such part count

Workaround

This issue has 3 solutions on my side:

  1. Enable streaming (this is what I did). Enabling streaming does not fix the issue, but avoids it most of the time, as most of the time you are not near other player vehicles
  2. Optimize the model to not have 1000 parts. While this is possible in theory, I dont have that much time, and because my models have a lot of animation/script related things, the bare minimum of parts is around 200 - 400
  3. Make it so the model will have physical throttling again by re enabling CanCollide and CanTouch on most of its parts. This is the worst solution out of the 3, but it can work as a workaround

Solution on the side of roblox might be simpler, as if replication becomes slower when physics get trottled, it’s probably possible to make it slower based on amount of BaseParts in a model too

Issue Area: Engine
Issue Type: Performance
Impact: Moderate
Frequency: Constantly

3 Likes

I managed to find a very old screenshot of microprofiler before I enabled streaming

On the screenshot I’m intentionally looking into the ocean, meaning there are around 0 parts that should be rendered. As I remember I had around 20 fps when taking this screenshot

1 Like

Thanks for the report. I filed a ticket to our internal database.

1 Like

Coming back to this old report - The profiler is consistent with a ton of parts moving, which is expected if there are massive assemblies moving around. This is tough to prescribe a solution for besides moving fewer parts.

FWIW, this does not have to do just with large assemblies - There could be many parts moving with or without physics.

We recently optimized this codepath, so you should see reductions in updateInstancedClusters when there are thousands of parts.

Hi, if you wonder, I had to make a completely custom rendering system for the models in order to avoid this issue. It was pretty complicated to do, but in the end it avoided all of the issues, because now the server has basically only the wheels to which the client locally attaches the actual visual model, meaning there are no thousand of parts to replicate, and the client can also dynamically unload the models. It is however nice to see that you also made improvements to it on your side, and I think I will still be able to feel performance gain from it, even with that custom system on my side

This issue also affects the game Multicrew Tank Combat 4 which has vehicles with a lot of moving parts and updateInstancedClusters taking a lot of frame time due to this issue. But the last time I talked to a Roblox engineer about this issue, he said it is a problem with the way the content is authored and that it was on the plan to fix it for multiple years so I think there is still something to fix on Roblox’s side unless it is already fixed.

If I may ask, how did you go about this?

I have a game with fully automatic train systems. Problem is, this means 5-10 trains could be moving at any given time entirely controlled by the server. I’ve done everything that’s easy to try to optimize them, but there’s still a lot of physics and such happening.

I’m now wondering if replicating the visual aspects of the train bodies to the clients manually would be a decent way to help this, but I have no clue where I’d even start.

One method I’ve experimented with previously is to have clients use a local copy of the vehicle’s body and then either :PivotTo() the body onto the replicated chassis, or weld the base to an invisible part at the world origin and move it around by adjusting the weld’s C1. I set this up by separating the vehicle into body and chassis sections, with the chassis being spawned in by the server and clients cloning the relevant body from ReplicatedStorage and moving it as needed using either of those methods.

:PivotTo() is nice to work with and fairly performant for most cases. If your models are particularly part intensive though, welds become the fastest option by far, although they’re a bit of a hassle. In my testing I was able to get a 12,000 part ship moving at ~120hz without noticeable performance drops, but your mileage may vary.

The downside is mostly just losing out on body-related physics, for example players being able to stand on/in the train. If that’s desired you can mitigate that by setting the .Velocity of the body’s parts to whatever speed it should be going, which will push players along as if it’s moving. Depending on part count that could slow things down, so you might want to only update velocity if a player is nearby, or only for parts where it matters such as the floor or roof.

1 Like

I did end up doing something like this, and it actually worked out very well getting all of those parts off of the server. Fortunately, all of the player interaction with the A.I. trains requires no humanoid collision physics anyway, so it was a win win.