CesiumGS / cesium-unreal

Bringing the 3D geospatial ecosystem to Unreal Engine
https://cesium.com/platform/cesium-for-unreal/
Apache License 2.0
906 stars 288 forks source link

SetCollisionEnabled can be very slow #1316

Open ftrx opened 9 months ago

ftrx commented 9 months ago

I noticed an performance CPU issue regarding collision with 3dTiles (Google): As far is i see it its mostly the enable / disable of the collision during the RemoveCollisionForTiles and ShowTilesToRenderer in the Tick() function of the 3DTiles. While the whole updateView() takes usually about the same every frame (with my settings ~10ms), enabeling/disabling the collisions (SetCollisionEnable) can take up to 120ms and more which leads to huge stalls.

And unfortunately the CreatePhysicsMeshes does not change a nothing on the collision enable/disable side. (Physics meshes seems still there but, collision is not checked)

kring commented 8 months ago

Do you have CreateNavCollision enabled? You may be running into https://github.com/CesiumGS/cesium-unreal/issues/1264.

ftrx commented 8 months ago

No no CreateNavCollision enabled. Enable / disable CreatePhysicsMesh funnily also doesn't do a lot (except no colliders anymore). I changed some of the code and removed the Gltf->SetCollisionEnabled() from the showTilesToRender() and removeCollisionForTiles() function in the Cesium3DTileset.cpp and the issue is gone.

Maybe some info that might help:

For the tilset:

I kinda hacked a fix for my issue for now, in that I now use two tilesets, one with low ScreenSpaceError for visuals and one with very high one for collision. With the changed code above + additional disabling of the visibility of the second one, I kind of get a more stable result; with more overhead from the additional tile set and double loading (pricier), but still much less impact than with full collision enabled.

here a screenshot of insights (3 frames, one with the spike) : Screenshot 2023-12-11 104017

I'll try to reproduce the issue in a clean project if I have time.

kring commented 8 months ago

Oh that's interesting. In older versions of UE, "enabling" collision on something that didn't have any was seemingly harmless. But in newer versions, it seems to generate the necessary collision meshes right there. Ouch.

ftrx commented 8 months ago

I also need to say that some parts of the issues i had were related with a corrupt level / tileset blueprint after updating to 2.1. After creating a new level and re-added the same actors it is much better now (not completely gone tough)

There are still some heavy spikes on the CPU when there is heavy loading in/out of tiles (especially when moving and rotating at the same time). But its only the showTilesToRender (EnableCollision), the RemoveCollisionFoTiles spikes as shown above is almost completely gone except when changing the georeference location. it gets worse the lower the MaxScreenSpaceError is (bigger collision meshes too).

But i would say that now the most limiting factor is the Cesium::updateView() which has some calls on the Cesium::LoadModel() on the GameThread.

It still would probably be nice to have an LOD (either bias or a minimum MaxScreenSpaceError) option for the collision like proposed in: #1159

csciguy8 commented 8 months ago

Thanks for the report and Insights view @ftrx . Really helpful to see details like this.

Makes me think we need performance tests to catch loading frame spikes. Would help us repro this problem (and potentially others). Right now, we only have "wall-clock" style tests that just measure total time.