Full Kinematic Contacts solves contact normal impulse / tangent impulse

Hi! I’m working on a platformer where I’m finding that it would be super great to be able to have a kinematic body behave like a normal dynamic body except in a very few corner cases.

If we had contact.normalImpulse / tangent impulse we could apply this force in a script to get the body to behave like a dynamic rigidbody, but have the option of modifying this or ignoring this based on certain conditions. For instance, right now when using a dynamic rigidbody i get jittering when moving from ground on to slopes and if I could control the direction of the normal in the collision response (or just eliminate the vertical component), I’d be able to get the behavior i’d like.

as it is right now, when full kinematic contacts is enabled, contact.normalImpulse is always zero which doesn’t do me any good. I’m having to do all kinds of hacks now like casting a capsule every frame to see if I’m about to run into a slope, or even using a kinematic body with full contacts, and then trying to do my own collision response solving in C# and of course it’s not going to be as nice as the one that box2D already has.

1 Like

Well spotted. I believe you’ll get impulse info when the kinematic body is touching a dynamic body, maybe when the kinematic body iself has an actual velocity but I’d have to check that. I presume this is happening when the kinematic body is touching another kinematic/static body, the most common case probably being in contact with a static body i.e. the ground.

I agree though, this is not only nice to have but essential. The next step for me alongside full-kinematic-contacts is to look at the ability to ask Unity to solve (provide you with the new position/velocity) the contact(s) for you upon your request which of course will require some of this information. This would work iteratively and be as stable as the dynamic body is.

Again, thanks for the heads-up on this. Be sure that I’ll take a look at this ASAP!

awesome! i spoke with you on slack a few weeks ago ( @ ) about something similar, but i am glad it’s getting some attention.

thanks again!

I’d love this contacts upon request feature. Would make life a lot easier for doing hitboxes / area enemy detection without needing to be on all of the time.

If you mean the ability to retrieve contacts, it’s in the 2D previews and is on its way to 5.6 as we speak.

1 Like

I’m not sure. What I want is to define a ColliderPolygon2D IsTrigger and be able to get a list of everything inside or touching it on demand.

That’s in the experimental preview since first release. You can perform a .GetContacts call on a specific collider or rigidbody. You can also see contacts live from the collider/rigidbody ‘info’ rollout in the inspector.

Release #2 added a ContactFilter2D that allows you to filter .GetContacts by trigger/collision-normal-angle, layer-mask & depth. In Release #3 this filtering has also been added to .IsTouching as well as to every other physics query i.e. .Cast, .LineCast, .RayCast, .OverlapXXX etc. I tweeted about that here (should give you some idea about it): x.com

Thank you I had no Idea :slight_smile:

1 Like

Hey @MelvMay , I started looking into this: (using Preview 2)

Here’s a BoxCollider2D that’s overlapping with terrain, but no contacts are in the list:

2868846--210164--Screen Shot 2016-11-30 at 3.54.40 AM.png

You will note the box clearly is overlapping the ground beneath it - and I tried cycling the layers too.

There were actually a bunch of problems in preview 2 but preview 3 is nealy ready however, note that the inspector shows actually collision contacts and not trigger contacts because it’s showing ContactPoint2D detail; triggers do not have contact points. If you require that then do not use a trigger and use a Kinematic body instead with full kinematic contacts checked. That way, the kinematic body does not react to collisions but you get full contact points.

Preview 3 massively improves the use of ContactFilter2D; it’s effectively used in all 2D physics queries. The new contacts API as well as the Composite collider feature has gone into 5.6 alpha which will soon be in its beta phase.

In addition: If you perform a GetContacts (the one with the Collider2D array arg) on the Rigidbody2D or on the trigger collider itself you will get the collider(s) of the ground returns though.

Okay. So to be sure I’m understanding correctly:

If I just need a ‘hit box’ - something that tells me every other Collider2D which is contained Within or Intersecting with a given Is Trigger Collider2D (We’ll call it X), calling X.GetContacts() will return the Collider2D of the ground rectangle. (or Tilemap collider in this case)

Yes, just look at the documentation for the overloads of GetContacts; the one that returns a list of colliders rather than conact points.

@MelvMay here’s an abbreviated version of what I’m doing:

Kinematic, Use Full Kinematic Contacts, Simulated, etc. Just like you mentioned in the 2d build thread

... class... MonoBehaviour etc
{
    
    public virtual void OnCollisionEnter2D(Collision2D coll)
    {
        MyRigidBody.velocity = Vector2.zero;
    }

    private Vector3 _lastVelocity;

    void FixedUpdate()
    {
          // Apply the final velocity
        _lastVelocity = GetCurrentVelocity();
        MyRigidBody.velocity = _lastVelocity;

        // I actually want to freeze movement if the body's velocity is almost zero... 
        if ( _lastVelocity.magnitude <= 0.05f ) 
            MyRigidBody.constraints = RigidbodyConstraints2D.FreezeAll;
        else
            MyRigidBody.constraints = RigidbodyConstraints2D.FreezeRotation;

        int contactCount = MyRigidBody.GetContacts(contacts);
        if ( contactCount > 0 ) 
        {
            Debug.LogFormat("Contact count: {0}", contactCount);
            MyRigidBody.velocity = Vector3.zero;
        }
}

However, instead of the objects stopping (see Physics - how do I set the following: - Unity Engine - Unity Discussions) - the two colliders slowly push through each other like molasses.

I. Just. Want. Hard. Stops.

Why is this so complex to achieve.

(BTW, I realize this thread is being conflated with the other one - and this GetContacts() function solves the issue of a hitbox described above. Thanks for that. I am frustrated)

For starters, I have to say that Experimental 2 isn’t for production so maybe your problems relates to this. If you want to work with the ‘GetContacts’ then I’d recommend at least trying 5.6-beta as it landed there a while ago. Also, Experimental 3 has been released with many fixes and updates. Bugs fixed in 5.5 and 5.6 are not automagically backported into experimental releases. It’s just not supported as a production release. We’re hoping that the next experimental released will be based upon 5.6.

Anyway, moving forward; I’m not sure what the constant changing of constraints is all about and I certainly wouldn’t recommend it. Changing ANY physics property has consequences, it’s not just a data change. Changing constraints means constraint joints are added/removed each fixed update in your script. Box2D doesn’t support constraints like this so they’re implemented as internal joints. Freeze rotation is fine as that is supported in Box2D however Freeze position is done with joint(s).

I don’t follow the logic above really and don’t see how it stops overlaps or colliders sinking into each other. If you have a contact you zero the velocity. What if it’s overlapped?

As to colliders overlapping slowly; it’s impossible to figure that out from just looking at the code above. It just sounds like you’re trying to perform contact processing with kinematic bodies to produce what Box2D does which won’t work unless you have an overlap solver; don’t see that above.

Note for overlap solving; that’s coming as I tweet here:

https://twitter.com/melvmay/status/819909676586467328

I can try to debug the issue in the latest experimental 3 release for 5.6-beta (unless you’re using other experimental features like TileMaps of course).

I upgraded to experimental release 3 the day it came out so that should be fine.

If you want to try out what I have, I can add you to the project permission on GitHub or mail you a ZIP. Do you have a preference, @MelvMay ?

I removed the freeze position constraint - it was just me struggling to get objects to stop pushing each other away.

@MelvMay

Can we see a legible screen cap of the documentation in that tweet? This sounds like exactly what I need and could eliminate quite a bit of my less elegant work-arounds. Could you clarify, will I be able to ask if two triggers are touching but not overlapping, i.e. sharing an edge?