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. Dismiss Notice

Resolved Collider2Ds Sinking into Each Other

Discussion in '2D' started by CodeUnit07, Aug 15, 2023.

  1. CodeUnit07

    CodeUnit07

    Joined:
    Aug 10, 2023
    Posts:
    11
    Hello everyone,

    I... have a problem...

    THE GAME
    I'm a new unity programmer learning about all the features and methods in unity. I'm currently building a ball and paddle game in which a ball bounces off the walls at the angle that you launch it. Because I am new I am having a lot of problems and although I can solve most of them with tutorials, experimentation and the unity docs, here is one problem that I just can't figure out.

    Disclaimer: Go ahead and leave this thread if you don't have time to explain a possibly simple concept. I don't want to waste your time but I am having a lot of trouble.

    THE PROBLEM
    I have successfully made the game to where the ball will bounce off the walls and change the direction correctly. My issue though, is that as I move the rigidbody2D of the ball collider2D sinks into the walls instead of stopping immediately after touching a wall collider. This can be solved by switching the collision detection of the ball rigidbody2D to continuous but this doesn't cause the ball to stop after touching an edge but instead move along the edge. This is a problem because I need to take a reading of the ball position immediately after the ball touches the edge.

    How do I stop the ball from sinking into the edge colliders?

    MY SOLUTION (failed)
    My idea to solve this problem was to as soon as I received OnCollisionEnter I would back the ball out of the wall instantly by using a while loop that stops once the ball isn't touching the edge collider anymore. This began the hunt of finding a property that was able to detect if the ball collider was touching another collider. The only method I found was IsTouching(); but I wasn't able to get it working because of my failure to understand the docs.

    Definitely let me know either how to use IsTouching(); or another method or property that returns the number of colliders it's touching.

    IDEA #2 (also failed)
    With the first idea failing, my next idea was to make a boolean that switched to true when OnCollisionEnter was called and switched to false when OnCollisionExit was called. In OnCollisionEnter using the same while loop I would repeat until the boolean was false.
    Code (CSharp):
    1. void OnCollisionEnter2D(Collision2D collision)
    2.     {
    3.         touchingCollider = true;
    4.  
    5.         for (int i = 0; i < 100 || !touchingCollider; i++)
    6.         {
    7.             ballRigidbody.MovePosition(ballRigidbody.position + velocity * Time.fixedDeltaTime / 5);
    8.         }
    9.     }
    10.  
    11. void OnCollisionExit2D(Collision2D collision)
    12.     {
    13.         touchingCollider = false;
    14.     }
    (I used a for loop just so that if something when wrong there was a "breaker" that killed the code after too long)

    There's no surprise this didn't work because while(and for) loops happen in one frame leaving no time for OnCollisionExit to trigger.

    HELP
    Thanks so much for taking the time to read my problem. My question ultimately is how do I stop collider2Ds from sinking into each other. (Code examples would be highly appreciated)

    Final Disclaimer(feel free to skip): If you tell me that it's clear in the docs then this is the reason that they only help me some of the time. I am unfamiliar with a lot of the terms that they use, and if I try to learn those terms I will have to learn more terms to learn those and it sets me on a rabbit trail ultimately getting nothing done. Also the fact that they have few code examples makes it nearly impossible for me to visualize what they are saying. I think the docs are useful, but this is the reason that I have trouble with them.
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    With discrete collision detection, this is how it works, it moves in a velocity-time-integrated way and solves any overlaps albeit not necessarily immediately in that simulation step. This is the default as it's very fast but can cause collision tunnelling. Continuous collision detection will always stop this as it checks for the impact point and moves the body there. It's much more expensive so shouldn't be used for hundreds/thousands of things if you can help it.

    I'm not sure what you mean here. If you mean there's no bounce but only when it's moving slower then that'll be because it's determining it's an inelastic collision (for stability). For brick/ball games you should consider setting the following inelastic collision velocity threshold to its lowest value: https://docs.unity3d.com/ScriptReference/Physics2D-velocityThreshold.html

    If this isn't it then you should demonstrate what you mean.

    They don't unless you're doing something that the solver cannot solve such as directly modifying the Transform, have huge mass ratios for impacting bodies, lots of stacked things not using continuous, have not considered increasing the allowed solver iterations to give it more time to solve tricky stuff etc.
     
  3. CodeUnit07

    CodeUnit07

    Joined:
    Aug 10, 2023
    Posts:
    11
    The problem with using continuous for me is that while every frame the ball moves closer to the edge, the frame that it hits the edge, instead of stopping at the contact point it ends up drifting to the side. For my purposes I NEED it to stop directly on the contact point. I think this problem is because the ball is coming on an angle and the ball is just finding the quickest way out of the edge instead of setting it to the contact point. I can attach a visual if that would be helpful.
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    If you have bounce in the material, it won't be at the contact point. Friction is also used to determine any sliding along the surface tangent.

    You're free to use a Kinematic Rigidbody2D and use queries to determine where it can move using queries such as Rigidbody2D.Cast and MovePosition to move. You can create your own collision response with this if you don't want the Dynamic collision response.
     
  5. CodeUnit07

    CodeUnit07

    Joined:
    Aug 10, 2023
    Posts:
    11
    Alright thanks. I just ended up using a different approach. I used the cast(); method to determine the precise spot to stop.
     
    MelvMay likes this.