Search Unity

Question Getting "this" Collider During OnCollisionEnter/OnTriggerEnter

Discussion in 'Physics' started by Zullar, Jan 13, 2022.

  1. Zullar

    Zullar

    Joined:
    May 21, 2013
    Posts:
    651
    I have an object with a hierarchy...

    -Root GameObject w/ Rigidbody & Capsule Collider (Torso)
    ---Child object with Sphere collider (Head)
    ---Child object with Sphere collider (Legs)

    OnTriggerEnter is always called on the root Rigidbody object (not the child object) and I have no way of knowing *which* object triggered. (Torso, Head, or Legs)

    Any help would be appreciated. Thanks.
     
    Last edited: Jan 14, 2022
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,497
    I'm not a 3D physics dev but like 2D, the GameObject with the Rigidbody the Collider is attached to will receive the message callback and if the Collider itself is on a different GameObject (child) then it too will receive a message callback.
     
  3. Zullar

    Zullar

    Joined:
    May 21, 2013
    Posts:
    651
    Thanks for the quick response.

    I agree that root GameObject with the Rigidbody does receive the OnTrigger callback. However that callback is ambiguous because we don't know which child object invoked the OnTrigger callback.

    I just made a small project and bug reported it. Let me know if that helps.
    1395187
    "OnTrigger Collider Callback Ambiguity"

    I also just uploaded a Youtube video to try and make it more clear.


    Here are some links discussing other people with the same issue with some pictures. They describe it more clearly than I did.
    https://gamedev.stackexchange.com/q...ct-collider-name-when-ontriggerenter-is-fired
    https://bladecast.pro/unity-tutorial/distinguishing-multiple-trigger-colliders-same-object-unity
    https://answers.unity.com/questions/24809/how-do-i-get-the-source-collider-on-an-ontriggeren.html
     
    Last edited: Jan 14, 2022
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,497
    That's not what I was replying to though. You stated it's not called on the child; I stated it was. Now you're saying you agree and the subject now is that you think the one called on the Rigidbody is ambiguous. Yes, it only tells you which collider was hit but that's how it's always been for triggers. It's not a bug so not sure why you're reporting it as such though.

    If you need to know which one, put your script on the child one isolation.

    It's not like we can just changed the signature of the OnTrigger callback to pass something else too.
     
  5. Zullar

    Zullar

    Joined:
    May 21, 2013
    Posts:
    651
    Sorry I haven't stated the issue correctly. In most cases things work fine, but I spent some time and I mapped out all the combinations of hitting colliders and it appears only Case 4 has the issue/bug.

    upload_2022-1-16_1-26-54.png

    In Case 4 OnTriggerEnter is not called on the child GameObjects.

    This only works in Case 1 and Case 2. This does not work in Case 4 because OnTriggerEnter is not called on child GameObjects.

    Case 1:
    Self Object: Child Trigger Colliders (with parent Rigidbody)
    Other Object: Trigger Collider
    Result:
    OnTriggerEnter called on Parent Rigidbody GameObject?: YES
    OnTriggerEnter
    called on Child Collider GameObject: YES
    -Since the Self Object receives OnTriggerEnter callback both at the parent Rigidbody object and at the child collider object the ambiguous callback at the parent Rigidbody can be ignored. Placing a script on each child object lets you listen for OnTriggerEnter callbacks and allows you to differentiate which collider was hit. This works as expected.

    Case 2:
    Self Object: Child Trigger Colliders (with parent Rigidbody)
    Other Object: Non-Trigger Collider
    Result:
    OnTriggerEnter called on Parent Rigidbody GameObject?: YES
    OnTriggerEnter
    called on Child Collider GameObject: YES
    -Works as expected (same as Case 1)

    Case 3:
    Self Object: Child Non-Trigger Colliders (with parent Rigidbody)
    Other Object: Non-Trigger Collider
    Result:
    OnCollisionEnter called on Parent Rigidbody GameObject?: YES
    OnCollisionEnter
    called on Child Collider GameObject: NO
    -OnCollisionEnter callback is invoked only on the parent Rigidbody GameObject and not the child. However, the Collision data class that is passed in the parents OnCollisionEnter callback contains contact information that provides information on both self and other colliders. Self and other collider information can be extracted by collision.contacts[0].thisCollider and collision.contacts[0].otherCollider respectively. This works as expected.

    Case 4:
    Self Object: Child Non-Trigger Colliders (with parent Rigidbody)
    Other Object: Trigger Collider
    Result:
    OnTriggerEnter called on Parent Rigidbody GameObject?: YES
    OnTriggerEnter
    called on Child Collider GameObject: NO!!!!! (THIS IS THE ISSUE!)
    -Case 4 does not behave like Case 1 and Case 2. This is a OnTriggerEnter callback, and not an OnCollisionEnter callback, there is no Collision data to allow access to collision.contacts[0].thisCollider like in Case 3. This is not working as I would expect because you are told that your object triggered with another collider... but you have no idea which self collider hit it (it could be the parent or any of the children).

    After some searching it seems other people have ran into this same problem. Not sure where it ranks in priority in your list of issues/bugs. If you do see this as a significant enough issue to warrant a change I would suggest a new overloaded OnTriggerEnter (TriggerData) callback where TriggerData contains information about both self and other colliders similar how the OnCollisionEnter callback provides a Collision data class.
     
    Edy likes this.
  6. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    As explained in the video, OnTriggerEnter() is not invoked at the child level in the hierarchy when non-trigger colliders contact the trigger cube.
     
  7. migwellian

    migwellian

    Joined:
    Mar 20, 2018
    Posts:
    16
    I have a workaround, it's a bit weird but it works:

    1. When OnTriggerEnter fires on your first object, call `other.gameObject.AddComponent` to add a custom script to the second object
    2. When OnTriggerEnter or OnTriggerEnter or OnTriggerEnter fires on that custom script, inspect `other` to find out which child of the first object was involved in the collision
    3. Execute any logic you need
    4. Call GameObject.Destroy to tidy up the custom script you added in step 2