Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Optimization of Complex Raycast-Only Colliders

Discussion in 'Physics' started by 3dHomer, Apr 29, 2021.

  1. 3dHomer

    3dHomer

    Joined:
    Jun 6, 2015
    Posts:
    13
    Hello!

    We have vehicles with complex colliders (3D physcs). A compound collider is made of primitives with a few simple convex mesh colliders:
    * 134 box colliders.
    * 23 mesh colliders.
    * 6 capsule colliders.

    All the colliders are inside of a kinematic rigidbody. All they are in a layer that doesn't collide with anything (including itself). The rigidbody is moved via Rigidbody.MovePosition, MoveRotation.

    When I spawn 100 such vehicles (they just move and rotate without any contacts), Physics.Processing takes approximately 3-4 ms. Not that bad but I wonder is there any way to improve the performance?

    We cannot simplify the compound collider but we only need to do raycasts against it. Physical simulation can be done with a single collider but we need the detailed collider for hit detection, picking etc. And we only need those complex colliders in game logic, they don't need to be updated in every fixed update (i.e. multiple times per frame).

    Is there any way to make a collider available for raycasting but disable unnecessary functions like physical simulation in every fixed update, callbacks like OnTriggerEnter, OnCollisionEnter?

    Just in case: I've tried to replace mesh colliders with primitives, it doesn't make a difference. Tested Unity versions: 2018.4.2f1 and 2021.1.3f1.
     
    Last edited: Apr 30, 2021
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,425
    Maybe you could use separate physics scenes? I have no experience on this, but perhaps you might have a separate physics scene with those colliders where you update their positions only and then run queries against them. You may not even need to actually simulate that physics scene.

    https://learn.unity.com/tutorial/multi-scene-physics
     
  3. 3dHomer

    3dHomer

    Joined:
    Jun 6, 2015
    Posts:
    13
    I though about it too but I'm afraid that a separate physics scene won't let me to decrease those 3-4 ms of "Physics.Processing" (in the profiler). The processing takes significant time even on an isolated test scene that contains nothing but those compound colliders with kinematic rigidbodies.

    Probably it would allow me to enforce one fixed update of those colliders per frame because simulation of the physics scene can be started manually and separately from the other physics.

    But it would be even better to find a way of making Physics.Processing faster by avoiding calculations I don't need.
     
  4. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,425
    Note that in a separate physics scene you have to call Physics.Simulate() explicitly. You may simply not call it in your separate scene. Simply set the transforms of your colliders in the separate scene and run the queries against them.

    Again, I have no experience here but I think it should be enough to have Physics.autoSyncTransforms = true so the modifications to the transforms are immediately applied to the physics system.
     
  5. 3dHomer

    3dHomer

    Joined:
    Jun 6, 2015
    Posts:
    13
    We will try physics scenes but I'm almost sure that it's required to call Simulate or colliders won't move at all. I'm expecting to get the same results in the profiler.

    Automatic syncing of transforms is turned off for optimization purposes and probably this option wouldn't affect kinematic rigidbodies that are moved via Rigidbody.MovePosition/MoveRotation. SyncColliderTransform is the other known source of huge performance problems and we try to get rid of them as much as possible. They appear in the profiler if you move colliders inside of a rigidbody or if you move transofrms of rigidbodies directly (instead of using Rigidbody.MovePosition). Or if you move colliders that are not in a rigidbody. The overhead of direct modification of transforms with colliders if much higher than 3-4 ms.

    I saw threads related to moving of "static" colliders that are not parts of rigidbodies. It used to be a forbidden thing and was optimized in Unity 5. But still, if I move all those colliders without a rigidbody, I get a veeery long SyncColliderTransform, it takes much more time than Physics.Processing if I put all those colliders to rigidbodies and move them via Rigidbody.MovePosition. Now it seems to be the fastest method but it's still not fast enough (considering that we need those colliders for raycasts only).
     
  6. 3dHomer

    3dHomer

    Joined:
    Jun 6, 2015
    Posts:
    13
    By the way, I saw interesting threads like these ones:
    https://forum.unity.com/threads/wha...d-raycasts-hitting-disabled-colliders.996644/
    https://forum.unity.com/threads/spherecastall-hitting-inactive-colliders-is-this-a-bug.374620/

    Colliders are disabled (they are on active game objects) but they are still returned by SphereCastNonAlloc. Probably it's a bug because the behavior is confusing and it doesn't work like this for RaycastNonAlloc and maybe it's going to be fixed. But if it would work properly, it would be exactly what we need: colliders are excluded from physical simulation but available for raycasting. (Using triggers and disabling collisions for the assigned layer seems to have no effect on Physics.Processing)
     
    Last edited: Apr 29, 2021
  7. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    In case you only execute a Raycast when the user clicks (eg. for user interface only), you could just not update anything in the separate physics scene until the user input starts with mousedown. This obviously doesn’t work if you need hover effects etc.

    Another method is to render the scene with a second camera and render all objects with a replacement shader, that color codes the objects. You can then query the rendered image at the mouse position for the color and find the original object in a color->object you maintained.

    the process is illustrated here:
    https://threejsfundamentals.org/threejs/lessons/threejs-picking.html
     
  8. 3dHomer

    3dHomer

    Joined:
    Jun 6, 2015
    Posts:
    13
    Thanks, but raycasting is needed for many things like aiming, projectile simulation, AI, simplified obstacle detection for spotlights etc. They are needed on both the client and the server (which doesn't have a camera). Some raycasts are needed every frame. And even on the client many of these raycasts do not depend on the camera position.
     
  9. 3dHomer

    3dHomer

    Joined:
    Jun 6, 2015
    Posts:
    13
    That's right: if I don't call Simalate, "real" colliders stay on their initial positions like ghosts.
     
  10. 3dHomer

    3dHomer

    Joined:
    Jun 6, 2015
    Posts:
    13
    We've solved the problem by placing all those hundreds of colliders to separate physics scenes. The main trick is to make them static. When a raycast hits a vehicle, the ray is transformd to local coordinates and a second raycast is performed against the static colliders.
     
    tjmaul likes this.