Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Can you make a collider ignore force FROM another?

Discussion in '2D' started by LoupAndSnoop, Oct 16, 2023.

  1. LoupAndSnoop

    LoupAndSnoop

    Joined:
    Jun 23, 2023
    Posts:
    34
    upload_2023-10-16_9-49-25.png

    What I want (see pic): Dynamic RBs (red blocks) can ride on either kinematic RBs (moving blue platforms) or other red blocks, and still take forces from static RBs (green terrain).

    Moving/parenting transforms do not work. Force override for whole layer and IgnoreCollision aren’t specific enough.

    Question: Is there a way to either 1) Make collider A not receice force from collider B (if both have same layer)? OR 2) Make a collider ignore incoming forces from a specific direction that involve colliders of a given layer(s)?

    If I could do either, then each block would respecte terrain, support blocks above it (send force), and not affect trajectory of blocks below. Assume my code can figure out what collider/obj is “riding” another. (Same problem as another thread, but this is a different aspect of that problem)
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,710
    Yes but you just said...
    ... which is exactly what you asked for. Force Overrides are for that specific Collider2D/Rigidbody2D.

    https://docs.unity3d.com/ScriptReference/Collider2D-forceSendLayers.html
    https://docs.unity3d.com/ScriptReference/Collider2D-forceReceiveLayers.html

    Is there a way to programmaticaly say when a force (presumably you mean due to contacts) can be applied based upon some of your own custom logic? No. if you're applying forces then you can do what you like.
     
  3. LoupAndSnoop

    LoupAndSnoop

    Joined:
    Jun 23, 2023
    Posts:
    34
    Thanks so much for taking time to reply.

    To clarify: Since force overrides take in a layer mask, if the block in the middle stops receiving forces from the block layer, then it’s not affected by the top block (good), but falls through the bottom block (bad). Send force overrides and Physics2D.IgnoreCollision() have the same issue. I want to block force recieve (or send) between two specific colliders, without influencing how it interacts with the whole layer.

    Bummer. Another clarifying question, given I can’t get into the physics simulation step or modify contacts. You mean there’s no way to tell the physics simulation (before it runs) to request it ignore all force from colliders A to B but include B to A?

    Alternatively, do you have any suggestion to achieve this desired behaviour? I’ve been going mad trying to get one dynamic RB to ride another without affecting it, AND allowing the rider to move normally with AddForce in the reference frame of the thing it is on.
     
    Last edited: Oct 16, 2023
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,710
    If you block force send/receive between two colliders, that's ignoring the collision which is what IgnoreCollision does. I presume you mean one or the other.

    "Riding" another IS affecting it. It's as if you're suggesting there's more than sending/receiving forces (because of contacts) going on here, there isn't. :)

    No, there's no feature for that. It could be added but controlling force send/receive itself only just came into 2023. It's possible to add it although I'm not sure how the sending/receiving of forces would solve this TBH.

    Because this is a Rigidbody physic simulation, the only thing that keeps things in contact like is contact friction. It can be tricky keeping perfect contact with another surface that is moving and there's no one-size-fits-all. Certainly the Transform system isn't the answer here, it's not in control of the physics; it's the other way around.
     
  5. LoupAndSnoop

    LoupAndSnoop

    Joined:
    Jun 23, 2023
    Posts:
    34
    Thanks. This helps a lot, as it’s so hard to know what doesn’t exist.

    I’ve been trying to break up collision callbacks, sending forces, and receiving forces. Unfortunately, I think the workaround is to give each block two duplicate colliders. One has collisionCalbacks/recieve forces, and a duplicate one with only send forces. This way I can tell Physics2D to ignore collisions between blockA forceSendCollider and blockB forceReceiveCollider. This way B can ride A without affecting A’s trajectory. Sounds expensive, but from this convo, it sounds necessary.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,710
    I really don't understand how that split helps you here. If you're ignoring collisions between two colliders, it doesn't matter what force send/receive you set-up, they'll never have any anyway (it won't even get that far) because they're ignoring collisions hence there'll be no contacts hence there'll be nothing to solve for the solver to apply impulses to the bodies (no "forces").
     
  7. LoupAndSnoop

    LoupAndSnoop

    Joined:
    Jun 23, 2023
    Posts:
    34
    My thinking is that IgnoreCollision is a function of two colliders, not rigidbodies. If I duplicate a collider into one collider that only receives force (send force layermask = 0), and one collider that only sends force (receive force layermask = 0) on the same rigidbody, then I can call Physics2D.IgnoreCollision(blockARecCol, blockBSendCol, true).

    This way, for blockB riding blockA, if blockA moves around (flying, riding, etc), it moves as though blockB isn’t there (Physics solver ignores blockArecCol-blockBsendCol, so B can’t send force to A’s rigidbody), blockA still sends forces to blockB (blockBrecCol-blockAsendCol collisions not ignored), and they still send callbacks (blockAsendCol-blockBsendCol not ignored). Repeating for blocks B/C/D would let me make stacks where force only transmits to the block riding, and not down. Then B can ride A by friction (+ rigidBodyB.AddForce to maintain contact with A), and all these extra forces don’t affect A’s trajectory (because it ignores forces from B). That’s the sort of behaviour I’m aiming for.
     
    Last edited: Oct 17, 2023
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,710
    IgnoreCollision stops two colliders from producing contacts, they don't interact at all then. The only time the physics system applies forces is to solve a contact or joints.

    It doesn't just arbitrarily apply forces for no reason.

    These two colliders will never produce contacts and will never interact. Any force/send is pointless as it'll never have contacts to produce forces in the first place.
     
  9. LoupAndSnoop

    LoupAndSnoop

    Joined:
    Jun 23, 2023
    Posts:
    34
    Isn’t that right then? I might simplify by making blockArecCollider ignore both block B colliders. Whenever A and B collide:
    • BlockASendCollider - BlockBSendCollider: Makes contacts, sends collision callbacks. Both have recieve force layer = 0 => no forces.
    • BlockASendCollider - BlockBRecCollider: Makes contacts, send + recieve layers match up for contacts to generate force on B, but no forces on A.
    • BlockARecCollider - BlockBSendCollider: Ignored => no contacts => no forces
    • BlockARecCollider - BlockBRecCollider: Ignored => no contacts => no forces
    Net result: A sends force to B, and both get collision callbacks. And all of this doesn’t impact ignoring/excluding collisions from other RBs in the same layer.

    To be clear, I’m proposing giving each RB two colliders of the exact same shape, size, and offset.

    Is there something I’m missing here?
     
    Last edited: Oct 17, 2023
  10. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,710
    No, I'm missing the point here and what/how it solves the problem but it doesn't matter really. Go ahead and do it and see how it turns out. :)
     
  11. LoupAndSnoop

    LoupAndSnoop

    Joined:
    Jun 23, 2023
    Posts:
    34
    Update: It kind of works. If you make a duplicate collider, and set it up like I explained, it will allow you to send (and not receive) force from another specific RB.

    I do need to abandon it since I have no way to go into the physics system to make the edits I need to apply proper forces for the blocks above to ride during the physics sim step. My next plan is to make everything kinematic, and effectively code all my dynamic RBs to work with kinematic RBs that calculate next position in sequence. This way I can mostly avoid the physics simulation doing any of the real work, since I clearly don’t have enough access/control via the normal API.

    If only I had a Joint2D that would only apply force to one of the two objects. Or the ability to modify contacts during physics simulation. Without either, I need to do my physics in a fundamentally different way.