-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
After enabling BVH in 2d physics, set monitorable to true for more than 4000 area through the Physic2DServer will cause an instantaneous permanent huge drop in performance #54171
Comments
This will require a minimum reproduction project. |
I experienced the same thing making my plugin Native Bullets. |
Ah unfortunately I can't see a This may well just be a result of different collision margins in BVH and the old implementation (BVH will by default report more collisions). The parameters are configurable but they aren't exposed to the user, I think @pouleyKetchoupp did some tests on the 2D parameter settings. But we'll know more once we can replicate. |
Bullets is set as an autoload in the examples, should work once you set it. EDIT: alright, nothing seems to change. With 7000 objects I get pretty consistent 400+ fps with hash grid, but only around 120 with bvh with huge occasional drops to around 30 fps. |
It's very probably the collision margin. We may have to think about whether to expose it to the user. It's pretty much this: Say you have 1000 objects moving, in theory you need to collision test each object 999 times after each move. This is very expensive. If those 1000 objects aren't moving, you don't need to collide test them, super cheap. If they are only moving a tiny amount it seems unlikely they would collide, so it seems silly to do full check. So instead we add a collision margin around each object. When it first adds, the collision testing is done with the expanded bound. Then when it moves, providing the new AABB doesn't move outside the expanded bound, there is no need to do a collision check. When it does move outside, you create a new expanded bound, do a full collision check etc. This means you can usually cut down the number of moving objects by quite a large amount on any particular tick / movement, which saves a shedload of processing. The flipside is, as the collision margins are larger, any two close objects are going to be registered as in collision at a further distance. This isn't a problem in many cases, and especially in physics, this broadphase check should be followed by a narrowphase check, which takes into account the shape of the object, not just the AABB. For instance two rods may not be in collision even though their AABBs overlap. What seems to be happening is that there is no narrowphase going on here, and the broadphase collision is being reported as a collision. There's a few ways of addressing this:
So you can see that the collision margin is a trade off. In most cases having a margin will be beneficial, but in particular special cases (e.g. bullet hell with collision) it could have negative effects. I did initially expose this in the first PR (for 3d rendering) but removed the project settings to avoid confusion, and because they didn't seem hugely important to reduce for rendering. Another option which I did try but ran out of time to finish is like an auto-adjusting system that varies the collision margin on the fly. This also can help because to some extent the best collision margin depends on the world size and the average speed of movement of objects. Anyway that is very likely what you are seeing - the other systems (physics / monitoring) are unable to cope with large numbers of collisions. |
I haven't run any tests yet, but just to add two things to @lawnjelly's insightful explanation:
|
I was about to open an issue on this, but after a search I believe this is also the issue I'm experiencing. In my case I am doing it all through the Physics2DServer while the BVH Collision Margin is 1. This results in significantly worse performance than using the Hash Grid. I worked around this in my project: since all the testing in my game is done by the bullet testing their motion against enemies and enemies never actually collide, using a high collision margin (which I assumed would reduce collision accuracy) seems to have no effect so I can use that to gain back lost performance. Attached is a video of the performance and the associated MRP for v3.5.beta5.official [815f7fe]. To test with, apply some of these changes:
x264.2022-05-30_11-22-33.mp4 |
Godot version
3.4.rc(62f56af)
System information
Windows 11, RTX 2060, GLES2/GLES3
Issue description
After enabling BVH in 2d physics, set monitorable to true for more than 4000 area through the Physic2DServer will cause an instantaneous and permanent huge drop in performance.
Steps to reproduce
Enable Bvh in 2D physics settings, and then use Physic2DServer to create some areas (more than 4000). Then gradually set monitorable to true for these areas. When the number of active areas reaches 4000 or more, the original 144fps will instantly drop below 15fps, and will drop below 5fps within 3 seconds.
After disabling BVH, the FPS does not start to decrease from 144 until there are 7000 active areas, and until 12000 active areas the FPS are still able to remain above 60.
Minimal reproduction project
I am using a C++ custom module to control the behavior of the area through Physics2DServer, so it may not be possible to provide a minimal project.
But I can guarantee that there is nothing in my module that will affect the physical behavior of Godot, because it simply calls Physic2DServer-related functions. And after many comparative tests, it is confirmed that this problem is caused by BVH
2021-10-24.01-50-27.mp4
(In the video, due to screen recording, the base fps dropped to 90-100, but this problem is still very obvious)
The text was updated successfully, but these errors were encountered: