Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

ComputePenetration returning false negatives on Capsule Collider

Discussion in 'Physics' started by esmith1234, Jun 2, 2020.

  1. esmith1234

    esmith1234

    Joined:
    Apr 13, 2020
    Posts:
    19
    I'm working on a depenetration method for a 3D equivalent of the Cast() function for the Collider class (for a character controller that uses a capsule collider), and for some reason the ComputePenetration() method will return false on collider returned by the OverlapCapsule() function. I actually I use this method twice in my character collider FixedUpdate() loop; one for the initial movement and the other for the ground checking, but I mostly have this issue with call in the initial movement code oddly enough.

    I'm currently testing the capsule collider against other primitive colliders (mostly box colliders), and the controller's capsule collider isn't offsetted in any way, and the parent gameobject (controller) is unrotated. I'm using Unity version 2018.3.13, so I'm wondering if this is a bug thing (and I would have update to a new version) or if I'm doing something wrong and not realizing it.

    Here is the depenetration function is question

    Code (CSharp):
    1.  private static Vector3 DepenetrateCollider(Collider collider, Vector3 position)
    2.         {
    3.             Collider[] colliders = null;
    4.  
    5.             switch (collider)
    6.             {
    7.                 case CapsuleCollider capsule:
    8.                     Vector3 offset = position - capsule.transform.position;
    9.  
    10.                     colliders = Physics.OverlapCapsule(capsule.GetPoint(false) + offset, capsule.GetPoint(true) + offset, capsule.WorldRadius(), GetAntiColliderMask(capsule));
    11.                     break;
    12.                 case BoxCollider box:
    13.                     colliders = Physics.OverlapBox(box.bounds.center, box.bounds.extents, box.transform.rotation,
    14.                         GetAntiColliderMask(box));
    15.                     break;
    16.                 case SphereCollider sphere:
    17.                     colliders = Physics.OverlapSphere(sphere.bounds.center, sphere.WorldRadius());
    18.                     break;
    19.                 default:
    20.                     break;
    21.             }
    22.  
    23.             Vector3 minimum_translation_vector;
    24.             float minimum_overlap;
    25.  
    26.             foreach (Collider other_collider in colliders)
    27.             {
    28.                 if (Physics.ComputePenetration(collider, position, Quaternion.identity, other_collider,
    29.                     other_collider.transform.position, other_collider.transform.rotation, out minimum_translation_vector,
    30.                     out minimum_overlap))
    31.                 {
    32.                     position += minimum_translation_vector * Mathf.Max(minimum_overlap, Physics.defaultContactOffset);
    33.                 }
    34.                 else
    35.                 {
    36.                     throw new UnityException("Failed to depenetrate " + collider.name + " from " + other_collider.name);
    37.                 }
    38.             }
    39.  
    40.             return position;
    41.         }
    And here the helper functions (in case that might be relevant somehow)
    Code (CSharp):
    1.         public static float WorldHeight(this CapsuleCollider collider)
    2.         {
    3.             return collider.height * collider.transform.localScale[collider.direction] -
    4.                 collider.WorldRadius() * 2f;
    5.         }
    6.  
    7.         public static float WorldRadius(this CapsuleCollider collider)
    8.         {
    9.             int horizontal_axis_1 = collider.direction != 0 ? 0 : 1;
    10.             int horizontal_axis_2 = collider.direction != 2 ? 2 : 1;
    11.  
    12.             return collider.radius * Mathf.Max(collider.transform.localScale[horizontal_axis_1],
    13.                 collider.transform.localScale[horizontal_axis_1]);
    14.         }
    15.  
    16.         public static Vector3 GetPoint(this CapsuleCollider collider, bool getUpperPoint)
    17.         {
    18.             Vector3 capsule_up = collider.transform.up;
    19.  
    20.             if (collider.direction != 1)
    21.             {
    22.                 capsule_up = collider.direction == 0 ? collider.transform.right : collider.transform.forward;
    23.             }
    24.  
    25.             return collider.bounds.center + (getUpperPoint ? capsule_up : -capsule_up) *
    26.                 collider.WorldHeight() * 0.5f;
    27.         }
    28.  
     
    Last edited: Jun 15, 2020
  2. esmith1234

    esmith1234

    Joined:
    Apr 13, 2020
    Posts:
    19
    Really? Nobody else has this problem?
     
  3. RunrunSoftware

    RunrunSoftware

    Joined:
    Dec 24, 2020
    Posts:
    1
    I am running on a similar case and I have no idea what's going on.