Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Feedback Best deformable terrain collider

Discussion in 'Physics' started by crysicle, Aug 23, 2019.

  1. crysicle

    crysicle

    Joined:
    Oct 24, 2018
    Posts:
    87
    Hello, i'm making a terraformation system which manipulates millions of heightmaps on the terrain each frame and am looking for the best method to update physics. Thus far the only options i've seen are the mesh collider and the terrain collider.

    Assigning new vertices to the mesh and letting the mesh collider rebake CollisionData is the most limitting as i hit about 2ms per 1k vertices manipulated on the high end. Using the terrain collider and updating it through SetHeights() is more efficient by about a factor of 7-8 making that about 2ms per 7k-8k heights manipulated. Both of these methods do their calculations on the main thread, however, further limitting the amount of possible data you can update for physics.

    Does anyone have any idea how to crank more performance out of these methods or perhaps a different idea alltogether?

    Here's a vid of the system in motion. Ideally Im looking to synchronize about 50000 verts/heights per 2ms. Having that much wouldn't make me create all kinds of workarounds and limitations for my project.
     
  2. benthroop

    benthroop

    Joined:
    Jan 5, 2007
    Posts:
    144
    Hey did you get anywhere with this? I wonder if you can gain some efficiency by not deforming your entire terrain at once? :)

    Also wondering if you're using TerrainData.CopyActiveRenderTextureToHeightmap and how that's working out.
     
  3. crysicle

    crysicle

    Joined:
    Oct 24, 2018
    Posts:
    87
    @benthroop after searching for about 2-3 months for this, i concluded that Unity does not offer a way of synchronizing heightmap data on even a relatively small area in realtime without incurring heavy performance costs. The fix for this for my own project right now is to copy back the heightmap data from the GPU using AsyncGPUReadback and create custom RayCasts/SphereCasts against the terrain from which character controllers/bullets and the like can infer collision data. However, i haven't figured out a fix for NavMesh based AI because rebuilding a navmesh in realtime is very costly and Unity's NavMesh is not open source, making custom building of the NavMesh impossible. Perhaps with A* Pathfinding it could be possible, but i haven't investigated it further yet. With this approach i'm capable of synchronizing about 20k objects in an area of 1kx1k heightmap resolution + controllers.

    Here's a video of the object positions/rotations changed in realtime. The lag is from rendering the trees, not from changes to transforms or the heightmap.


    Depending on what you need to do with your project you could try:
    -Using SyncHeightmap() after CopyActiveRenderTextureToHeightmap(). It's the slowest of approaches, but if you don't need to terraform lots every frame, and are fine with 5-10+ms spikes it might be fine. Using this will automaticly synchronize the terrain collider, reducing any overhead you'd have to do with creating custom code for the terrain and is the only way to have Unity's vert/tris LOD compression work after updating the heightmaps.

    -Partition the terrain into multiple colliders and keep 1 visible huge terrain without a collider which you would update with CopyActiveRenderTextureToHeightmap(). Then only update the partitioned colliders in places where necessary with SetHeights by retrieving the heightmap data from the GPU. This works well up to 5-10k heightmaps changed constantly at runtime. However, this will mean you wont be able to synchronize many NPC/bullet interactions with the terrain, because if you did, you'd require a much greater amount of heightmaps to be synchronized. It's still possible to infer the heightmap information for trees/details from the extra heightmaps copied from the GPU.

    Here's a video of how that would look. The checkboard pattern terrain is the 1 huge terrain which has no collider and is manipulated through CopyActiveRenderTextureToHeightmap(). The dark red is partitioned from the huge terrain and only updated in areas where the controller is currently running.
     
    Last edited: Nov 9, 2019
unityunity