Recently I’ve been working on overhauling a buoyancy system that I made. In the old system, the buoyancy was provided by a VectorForce constraint, a LinearVelocity constraint, and an AngularVelocity constraint. Thanks to an improved understanding of physics and coding, my new system uses a VectorForce and a Torque. It works (almost) perfectly, except from the fact that it caused much lowered frame rates on clients.
In my use case, these forces act upon a single assembly with upwards of 10000 parts. While attempting to find the cause of the lag, I noticed some odd behaviour with the physics sleep visualisation. In my new system, when the player contacted the assembly, it was highlighted red despite being network owned by the server. I checked on the server and verified that network ownership was being held by it and not switched over. In the server view, it appears red.
This does not happen in the old system. The ship remains unhighlighted at all times. In the server view, it appears highlighted red, as expected.
After some debugging I was not able to work out the cause but I was able to find a work around. By applying a LinearVelocity constraint with a max force of 1 to the ship, the performance issues suddenly went away completely. The strange sleep highlighting on the client stopped happening.
In some instances, this nearly doubled my FPS. I am under the impression this behaviour is not intended due to the sharp performance decrease for seemingly no reason.
Expected behavior
The physics performance should be high even without a LinearVelocity attachment.
Could you please make a repro that demonstrates the issue? Specifically, could you make one with the “old” and “new” behavior with steps on how to reproduce what you’re observing?
It seems like the network ownership of the ship is flickering between the client and server. You should only see the parts highlighted as red if they are awake and simulated by the client. There was a recent change with how we assign ownership, I’m curious if this is related.
Ok, finally had some time to work on this! Here’s what I found: assemblies can either be simulated by the client, the server, or both. You can visualize who is simulating an assembly by going to Studio Settings and checking “Are Owners Shown”. Green is client, white is server, and red is both. We refer to assemblies that are simulated by both client and server as being in the simulation “buffer zone”. The server still has authority of these assemblies, but the client sends its simulation result to help correct the server simulation.
When a player contacts an assembly that is owned by the server, it will usually trigger that assembly to be in the buffer zone, so both client and server will simulate and the server will ultimately update the assembly’s position. There is an exception (which you discovered): if the assembly is connected to certain constraint types (including LinearVelocity constraints), the assembly will exclusively be simulated by the server.
This explains the performance boost you saw. By adding a zero-force LinearVelocity constraint, you can ensure that the ship is never simulated by the client. It pains me to say it, but I recommend this work-around for the time-being. We currently don’t have any other mechanism for preventing local simulation on contact.