Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Let us know a bit about your interests, and if you'd like to become more directly involved. Take our survey!
    Dismiss Notice
  4. Don't miss out on the Unite LA Keynote for the latest information from Unity! Set a reminder!
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

OnCollisionEnter() fires too early?

Discussion in 'Physics' started by Max_van_Hell, May 29, 2017.

  1. Max_van_Hell

    Max_van_Hell

    Joined:
    Jan 22, 2016
    Posts:
    17
    hey,

    I am having a Hand Skeleton here consisting of 1 box and several capsule colliders for the finger bones. Those colliders all have a RigidBody and are Kinematic. All of the capsule bones have OnCollisionEnter() attached.

    The virtual objects (cube, sphere) also have a RigidBody but are all non-kinematic.

    The collision detection between the kinematic Skeleton and the non-Kinematic objects works, but the "OnCollisionEnter()" or "OnCollisionStay()" fires wayyy too early. I am using the Physics Debugger and I manually deactivate the corresponding bone colliders when "OnCollisionEnter()" fires for them I've took a Picture exactly when that Event was fired. In the Physics Debugger, I can clearly see that when OnCollisionEnter() fires, the white (sleeping) cube gets woken up and the corresponding bone colliders are disabled. However, it just happens wayy too early and I dont know why.

    I've attached a picture which shows the Hand Skeleton with blue (kinematic) colliders, and a virtual cube colored white (sleeping Body) from the Unity Physics Debugger. Yellow colliders represent the same (copy) Hand skeleton with same capsule colliders, however they only serve as triggers. The red plane (static collider) is simply used as a Floor.

    Any thoughts?

    cheers,
     

    Attached Files:

  2. FMark92

    FMark92

    Joined:
    May 18, 2017
    Posts:
    1,063
    Maybe the scale you are working at is too small.
    There is always a margin with physics. (in 3dsMax, for example, it's - by default - 0.1 units around object)

    But unless you are dealing with high speeds it shouldn't be a problem AFAIK...
     
  3. Donay

    Donay

    Joined:
    Apr 28, 2017
    Posts:
    70
    Is the hand colliding with itself first?
    Try adding some debug
    Code (csharp):
    1.  
    2.  void OnCollisionEnter(Collision collision)
    3.     {
    4.         foreach (ContactPoint contact in collision.contacts)
    5.         {
    6.             Debug.DrawRay(contact.point, contact.normal, Color.white);
    7.             Debug.Log("Name=" + collision.collider.name);
    8.         }
    9.     }
    10.  
     
  4. Max_van_Hell

    Max_van_Hell

    Joined:
    Jan 22, 2016
    Posts:
    17
    hi again,

    Wow first of all many thanks for your fast replies!

    Yeah the margin should not be a Problem, since the Picture is visualizing the actual physics colliders within Unity.

    I tried the Debug you suggested and attached here. The Skeleton bones do not collide with itself. OnCollisionEnter() fires only when near the cube and only the Cube is printed as a Collision object in the debug output. It is also pointed out here [1] that kinematic rigid Bodys don't collide with other kinematic rigid Bodys, so that should not be the case.

    It is really weird, according to the physics Debugger, the cube is White when sleeping and when woken up it is set to green, like in the Picture. The Moment the cube gets woken up from the physics engine is then the Moment where OnCollisionEnter() or OnCollisionStay() fires and the cube turns green.

    What confuses me really is that the actual collision resolution is properly triggered on EXACT contact Point from the PhysiX engine, which means I can push the cube really ONLY on exact Surface contact. However OnTriggerEnter() fires way earlier? This can be seen in the Attachement photo I have added aswell.

    Something is odd here, I just don't know what am I doing wrong here.

    cheers and thanks alot :)[

    [1] Unity Collision Matrix: https://docs.unity3d.com/Manual/CollidersOverview.html
     

    Attached Files:

    Last edited: May 29, 2017
  5. Donay

    Donay

    Joined:
    Apr 28, 2017
    Posts:
    70
    Are all the hand parts at the same level in the Hierarchy tree?
    I would try creating a few more objects with different collider types and play about with it to see if it’s consistent.
    Try detaching a finger part from the hand and seeing if you get the same issue.
     
  6. Max_van_Hell

    Max_van_Hell

    Joined:
    Jan 22, 2016
    Posts:
    17
    Interestingly, I attached the OnTriggerEnter() Event aswell and let the Cube fire a trigger Event, instead of a collision Event and it seems PhysiX is fireing the OnTriggerEvent() precisely on Surface contact Point.

    So this is basically all I changed now, let the Cube fire trigger Event and catch that upon my bones. Image is attached aswell. I dont understand why OnCollision*() fires that much earlier than the actual Surface hit, but OnTrigger*() does it precisely at actual contact Point. I can't imagine this behavior is normal in Unity, seems very odd to me. Does that give you any ideas maybe?

    Yes, the bones are on same hierarchy Level, it's structure is like:
    • Hand -> Thumb -> BoneCollider1
    • Hand -> Thumb -> BoneCollider2
    • Hand -> Thumb ->-> BoneCollider3
    • Hand -> Index -> BoneCollider1
    • Hand -> Index -> BoneCollider2
    I will try your suggestion tomorrow, excluding one collider indipendently from the hierarchy structure and test again, also probably with different Kind of collider.

    cheers,
     

    Attached Files:

  7. Max_van_Hell

    Max_van_Hell

    Joined:
    Jan 22, 2016
    Posts:
    17
    okay, I have cut out my skeleton bones from the "equation" as a possible "error variable", since I now did collision Tests with simple Unity cubes only and I can see exact same behavior.

    As one can see from the debug Output with the White contact rays in normal direction, the upper box (no gravity) fires continuously the OnCollisionStay() with the lower box but in fact there is no Surface collision.

    What is going on here?
     

    Attached Files:

  8. Donay

    Donay

    Joined:
    Apr 28, 2017
    Posts:
    70
    Your objects are very small. I think you need to scale them up a bit or increasae the fixed timestep.
    Try somthing aroun 0.002
     
  9. Max_van_Hell

    Max_van_Hell

    Joined:
    Jan 22, 2016
    Posts:
    17
    I have found another thread[1], where the Problem between Frame rendering (Update()) and physics cycle (FixedUpdate()) is pointed out. It seems the Explanation is that the physics cycle is much more frequent then the Frame rendering, so far so good.

    So, OnCollision*() Events happen during the FixedUpdate() cycle of the PhysiX engine and thus happen to be quite ahead of the actual Frame rendering. This means, if a (fast) Object_A is moving towards a static Object_B, and the collision is processed within OnCollision*(), the actual collision happens far ahead in a cycle while the Frame rendering is some time behind and it Looks for the Frame rendering that the objects in fact did not collide visually. So far it makes perfectly sense actually.

    However, since i am moving a kinematic Hand very slowly, the actual collision NEVER happens, even if I stand quite still with my Hand, the Collision in OnCollision*() keeps fireing but for the Frame render it doesnt happen.

    Also with the 2 cubes example above, doesnt make sense to me since both cubes were static, not moving, so the actual collision NEVER happens for the Frame render, but only for the physicX cycle.

    I think I have found the right trace here, but in my case (both objects Standing quite still) that does still not explain it entirely to me.

    cheers,

    [1] OnCollision*() vs Frame rendering: http://answers.unity3d.com/questions/1067291/oncollisionenter-is-called-before-the-actual-colli.html
     
  10. Max_van_Hell

    Max_van_Hell

    Joined:
    Jan 22, 2016
    Posts:
    17
    yeah the Objects are around real world scale. 1 unit in Unity is 1 meter. The Hand Skeletons match real Hands scale and thus the cubes are around 10cmx10cmx10cm (0.1, 0.1, 0.1) as a real world grabable object. So for the sake of my Project I can not really scale them down. Though, I attached an Image where I used a Default (1, 1, 1) scale Cube in Unity. As one can see, the OnCollision*() still happened visually too early, namely exactly when I have frozen the corresponding blue bone collider.

    I have tried to set the fixed timestep to 0.002 as you suggested but I can not see any difference. Increasing the fixed timestep to 0.2 however SOMETIMES it yields collisions closer to the actual visible contact Point. As I said, sometimes but it drops the physics framerate tremendously.
     

    Attached Files:

    Last edited: May 30, 2017
  11. Donay

    Donay

    Joined:
    Apr 28, 2017
    Posts:
    70
    It may be worth thinking about how you are moving the hand. If you are doing it from some sort of input it may look slow but in reality is more of a stay still then a short move followed by staying still. From the physics engine it sees a high velocity object and predicts it will collide but on the next update it is standing still again. Try doing the move using lerp?
     
  12. Max_van_Hell

    Max_van_Hell

    Joined:
    Jan 22, 2016
    Posts:
    17
    This may be an interesting Point, Sir! The bone colliders are from a periphery sensor (Leap Motion) and are entirely kinematically driven. So there is no force applied on the Hand movement but handled only via the transform.

    But I dont think the Problem is related to the Hand bones, my latest test actually Shows that there is some General Problem with the OnCollision*() of physiX. I placed 2 cubes next to each other, both with rigid Bodys, both non-kinematic. The right cubes without gravity moves really slowly on the X-Axis towards the left cube. The movement is applied in this case within the Update() to be synchron with the render Frame. One can clearly see that OnCollisionStay() fires also here much too early.

    I did the movement within the Update() once by Setting the <Transform> and once by applying <Force> to the RigidBody of the cube. both yield collision detection at same distance, both much too early.

    Right now, I am pretty out of ideas actually..

    cheers,
     

    Attached Files:

    Last edited: Jun 1, 2017
  13. Max_van_Hell

    Max_van_Hell

    Joined:
    Jan 22, 2016
    Posts:
    17
    oh god yeah Baby, I finally found the issue!

    Appearantly the PhysicsManager.DefaultContactOffset was too high for my scale. The Default contact Offset was about 0.02 and with virtual objects which are around 10cm it yields a HUGE error margin obviously.

    That never was a Problem for me, since in most graphics or game projects the scale of the objects is actually much larger so that such a contact Offset does not have a huge influence.

    However, since this is a HoloLens Project and I am working with virtual objects which are around 10cm - 100cm the contact offset is more sensible.

    Anyway, thank you much for your help!

    cheers,
     
    Karolion and efge like this.
  14. s3asfour

    s3asfour

    Joined:
    Jan 26, 2018
    Posts:
    1
    Thanks a lot Max_van_Hell! This was the same issue for me, and I'm using ARCore to make a ARJenga game on android. Was pulling my hair out until i found your post!