Disabling physics pushing and demo scene

http://xelnath.com/xelnath/Assets.zip

Create an empty 2d preview project. Replace the assets folder with the above.

What happens:

  • Load SomeScene
  • Hit Play
  • Press “A”
  • Soldier travels through the other collider.

What I want:

  • Open this scene, click on the Soldier (Player) and change the BodyType to “Dynamic”.
  • Load SomeScene
  • Hit Play
  • Press “A”
  • Soldier travels up to and goes “clunk” against the brick and stops.

Why cant I do it this way?

What I really want is for this to happen when one soldiers pushes on another that is standing still, neither moves.

However, when you select both objects and change to “Dynamic”

  • Load SomeScene
  • Hit Play
  • Press “A”
  • Soldier pushes the immobile one left.

Kinematic
2928359--216478--DEMO_Bug_Kinematic.gif

Dynamic (Soldier only)
2928359--216479--DEMO_Bug_Dynamic.gif

Both Dynamic
2928359--216480--DEMO_Bug_DynamicBoth.gif

@MelvMay I feel like this is as minimized + documented an example as I can make at the present. Let me know if there’s some thing I can clarify.

Disabling the ‘Skeleton Animation’ stops the problem. Presumably it’s modifying the transform of the collider which causes all existing contacts to be removed as the collider will be recreated. I’m not even sure how the collider is being created; persumably by all these scripts.

I’m not an expert on these scripts but if it’s doing this during fixed-update or update then you’ll not see any contacts you can use. Having physics perform the col-de using a Dynamc body won’t suffer from this because it’s all done during the update, not after when your ‘Skeleton Animation’ script runs and causes the collider to be recreated.

Anyway, this isn’t really a simple set-up as it’s using a pretty complex set of scripts to which I have no idea how it works.

:expressionless:

This is why I want to disable the ability for physics objects to modify each other’s velocities. Then everything can be dynamic.

So… what are my options? Do I just need to throw away unity’s physics and collision detection? The only time I want info about if a collider is intersecting or touching another collider is after it’s been moved.

Unity physics is not at fault here, it’s the fault of the script constantly updating the Transform between the Collider2D and the Rigidbody2D it’s attached to every frame during LateUpdate. If you do this, the collider is recreated which causes its contacts to be deleted and regenerated next fixed update. Colliders live in the local space of the Rigidbody2D so if you move the colliders and not the Rigidbody2D itself then they need to be recreated.

Your movement scripts are based upon counting contacts, which there’ll be NONE as you check them in fixed-update (and start the thing moving downwards) which is before the physics system runs. It then runs, following which the callbacks happen and you set the velocity to zero. Then the ‘animation’ scripts run in LateUpdate (potentially several times recreating the colliders) then eventually a fixed-update happens and you check for contacts (and start the thing moving downwards again) but there are none because your scripts causes the colliders to be recreated wiping any contacts then, again, the physics updates and regenerates the contacts and it goes on and on.

If they are animating Transforms on GameObjects which have Colliders that are attached to a Rigidbody2D not on the same GameObject then you should add another Kinematic Rigidbody2D for that ‘node’. This is what kinematics is about.

Effectively what you have here is a kinematic rag-doll. When you do this, you should have a Kinematic Rigidbody2D at every animated position so that the Transform change updates the Rigidbody2D and not the Colliders attached to it. You typically nest Kinematic bodies like this. Moving a parent Kinematic body moves all the children with it.

I did this on your project by adding a Kinematic Rigidbody2D onto the ‘GameObject’ under the ‘Spine’ game object. When I did this I saw contacts when overlapping stuff (I checked in the Info Rollout / Contacts).

You cannot have a single Kinematic root body with colliders attached on chidlren GameObjects and animate their Transforms.

There’s nothing stopping your script from grabbing all Rigidbody2D children and simply checking them for contacts.

Add a Kinematic Rigidbody2D to the ‘GameObject’ GO under the Spline Object then replace the ‘body1.cs’ script with the following I hacked together for you:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Body1 : MonoBehaviour {

    private Rigidbody2D[] mybodies;
    private Rigidbody2D rootBody;

    public virtual void OnCollisionEnter2D(Collision2D coll)
    {
        rootBody.velocity = Vector2.zero;
    }
    public virtual void OnCollisionStay2D(Collision2D coll)
    {
        rootBody.velocity = Vector2.zero;
    }
    private Vector3 _lastVelocity;
    private ContactPoint2D[] contacts = new ContactPoint2D[20];

    private void Start()
    {
        mybodies = GetComponentsInChildren<Rigidbody2D>();
        rootBody = transform.root.GetComponent<Rigidbody2D> ();
    }

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

        rootBody.velocity = _lastVelocity;

        foreach (var b in mybodies)
        {
            int contactCount = b.GetContacts(contacts);
            if ( contactCount > 0 )
            {
                Debug.LogFormat("Contact count: {0}", contactCount);
                rootBody.velocity = Vector2.zero;
                break;
            }
        }
    }

    public Vector3 GetCurrentVelocity()
    {
        var velocity = Vector3.down;
        return velocity + Vector3.right * Input.GetAxis("Horizontal") * 5f;
    }
}

This works perfectly. It collides with the other box and the ground. By adding the Kinematic body you also stop the collider from being recreated so contacts are available to be checked.

I would also recommend setting both Kinematic bodies to use Continuous collision detection to stop overlaps.

Note that the above script is something I quickly modified; it makes various assumptions such as assuming the root has a Rigidbody2D. You can customise this part yourself.

Hope this helps.

Thank you. This was a very complex description and you systematically talked me through it.

I appreciate you going into detail on it. I had no idea every non-trigger collider needed a rigidbody 2d attached to it - or what the purpose of Kinematic was.

The impression I had from the tutorials was “use Kinematic when you want the physics system to be affected by it, but generally ignored by physics too.”

So now, I can change my game to auto-add a kinematic rigidbody 2d, and stop movement whenever there’s a contact normal whose dot product is < 0 with the velocity. That will let objects move away from each other and not towards each other.

1 Like

To be clear, this has nothing to do with triggers or non-triggers nor do you have to add a Rigidbody2D to every collider as some fixed rule. I’ve tried to explain it a few times above and granted it might be better with a picture (that I don’t have)!

I’ll try to be clearer; Collider2D live in the space of the Rigidbody2D. For example, all the vertices of a BoxCollider2D are stored as a relative position from the Rigidbody2D. When you XY-position or Z-rotate the Rigidbody2D, the colliders attached to it do not require any attention so it’s fast as it’s only the Rigidbody2D that moves. However, if you adjust the collider offset or if the Collider2D lives on a child GameObject relative to the Rigidbody2D and you modify the Unity Transform inbetween the Rigidbody2D and Collider2D (the one on the Rigidbody2D is obviously fine to modify) then you’ve changed the relative position of the Collider2D with respect to the Rigidbody2D. Box2D is fairly immutable for stuff like this and such a change requires that the collider be destroyed and recreated so this is what we have to do.

When you animate the Transform XY-position or Z-rotation on a GameObject that has a Rigidbody2D and a Collider2D, we know to ignore all the Collider2D on that GameObject and only adjust the Rigidbody2D because of the above. Likewise, if we had a GameObject that has a Rigidbody2D but the Collider2D is on a child GameObject and we animated the Transform XY-position or Z-rotation of the Transform on the parent Rigidbody2D we would still ignore the Collider2D on the child GameObject because they have not changed position/rotation relative to the attached Rigidbody2D. In this parent/child split, if we were to instead animate the Transform on the child GameObject (that contained the Collider2D only) then we’re changing the relative position of the Collider2D with respect to its parent so it needs to be recreated in its new position.

Recreating a collider involves destroying it then creating it. When you destroy a collider, Box2D immediately removes all its contacts. Those contacts will be recreated in its new position during the next physics update. We then have to match up the old deleted contacts with the new incoming ones so we don’t end-up reporting new OnCollisionEnter2D or OnTriggerEnter2D which is a real PITA to do and has been the source of bugs in the past.

When you have a rag-doll set-up where you typically have colliders in a hierarchy of GameObject, some of which you animate XY-position or Z-rotation then you need to have a Kinematic Rigidbody2D at those GameObject which you animate. You do not need to have a Rigidbody2D at every GameObject, just ones where you animate.

Also, Kinematic Rigidbody2D automatically move relative to any parent Kinematic Rigidbody2D so modifying a root Rigidbody2D causes all children Rigidbody2D to move relative to it as you would expect in a normal Transform hierarchy; in this case it’s also a Kinematic Rigidbody2D hierarchy as well but the difference being that there isn’t a need to have a Rigidbody2D at every Transform position in that hierarchy, just the animate ‘joint’ positions.

Finally, I’d like to add that amongst the plans this year is to investigate making major modifications to Box2D rather than living with its shortcomings. One of which is to remove/reduce the need to recreate a Collider2D if you transform it relative to its Rigidbody2D. The other is to either defer recreation of Collider2D and therefore the contacts and/or allow the contacts to be updated immediately, either by a global option or per-Collider2D/Rigidbody2D.

That’s it!

Hope this explanation helps.

I wanted to add to this part as well; I see all the time, especially in docs where the docs guys/gals have ‘simplified’ the description for the sake of being concise at the loss of accuracy and I believe that in some cases, such as this, it adds long-term confusion or at least lack of real understanding which is, of course, not the users fault at all.

All 2D components when added to the scene affect the physics system, full stop. A Static body may not be moved by the physics system but it affects it as it’s considered when things overlap or touch it. A Kinematic body is the same except for the fact that like a Static body, forces do not move it. Forces include global gravity, user-applied forces or contact forces. They will move if you directly set their velocity but they’ll keep moving unless you explicitly change the velocity. Dynamic bodies are obviously affected by forces.

The only exception to this is when a Rigidbody2D has its Simulated property set to false. The body, its colliders, its joints (etc) are ignored by the physics system in this and only this case.

Don’t want you to feel like I’m jumping on you here, not at all, just my way of trying to clarify and I had some time on my hands to do so. Hope it all helps you. :slight_smile:

Absolutely hate dumbing down docs with a passion. Gets right on my tits. There should be a

Advanced Information Section that goes into maximum detail. For everything.

1 Like

I couldn’t agree more with this.

Not trying to blame the docs guys/gals at all. It’s very difficult to write good documentation that provides enough information for everyone in one place though. Also where to put it can be a challenge. Most of this kind of info should go into the manual and that’s something I’ve got on my plate in 2017. Going to put a lot of work into the 2D physics manual. Heck, I almost wrote a book as a GDoc which I need to revamp into a 2D physics manual.

1 Like

Even programmer notes would help. Heck even stubs and comments. Something. It does not help that sometimes the terminology used in Unity doesn’t quite reflect what it is actually doing at times.

I get it, it’s good business to be easily understood but IMHO you can have both. Whoever decided you couldn’t is just wrong.

I’m dedicated to getting a bunch of manual & docs work done early in 2017 hence it being in my top 5 things TODO and it’s a big ol’ list. :wink:

2 Likes

I agree, mind you the programmers changed iskinematic to simulated, in 5.5 and it’s still a stupid name, live or something to that nature, would of been better(as it confused the heck out of me until the docs played a part), mind you we have all done this from time to time I bet? :slight_smile:

This is not true. I am ‘the programmers’, I’m the dev for 2D physics here at Unity. Simulated has nothing whatsoever to do with a body being kinematic.

The body-type defines the behaviour of the body and its colliders. Simulated simple turns on/off the physics system from simulated the body as the documentation states.

I use simulated on/off to save processing and/or for pooling purposes.

Yes, that’s a pretty good use for it.

I appreciate the clarity brought to bear here. The specific stepping not only through intended setup but also explanation for how you expected things to work was very helpful. I had no idea that you expected multiple rigidbodies on a character, let alone that moving colliders caused a refresh of the physics state.

The details added to this thread has benefited multiple people here, so thank you for your patience and precision. I feel like I far more deeply understand what’s going on.

The way you helped diffuse the frustration, then step through how to achieve a beneficial result helped a lot here too - appreciate your maturity and attitude.

1 Like