Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Getting collision direction detection from triggers

Discussion in 'Scripting' started by MadboyJames, Nov 16, 2017.

  1. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    Hi, So I'm trying to get the direction my player is entering a BoxCollider2D trigger. So far I've come up with pretty much nothing in terms of a working solution. I was playing around with rays, but couldn't get them to work.

    This is as far as I got with the rays
    Code (CSharp):
    1. private void OnTriggerEnter2D(Collider2D other)
    2.     {
    3.         if (other == CameraFollow.currentTarg.GetComponent<Collider2D>())
    4.         {
    5.          
    6.             Ray hitRay = new Ray(transform.position, other.transform.position);
    7.             RaycastHit hitPos;
    8.             Debug.DrawRay(transform.position, targetPosition.position);
    9.             if (Physics.Raycast(hitRay, out hitPos,4))
    10.             { print(hitPos); }
    11.         }
    12.     }
    If anyone has any good ideas about how to go about this, (either with the raycasts, or any other way that is more direct) I would love some help.
     
  2. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    Oooohkay. So I have some code that almost works, but I'm going to debug it in a bit. Meanwhile, if anyone is interested in having a look-see, here it is.
    Code (CSharp):
    1. if (other == CameraFollow.currentTarg.GetComponent<Collider2D>())
    2.         {
    3.             yAxisMax = transform.position.y + GetComponent<Collider2D>().bounds.max.y; // y position+ the right boundary offset...
    4.             yAxisMin = transform.position.y - GetComponent<Collider2D>().bounds.min.y;  // the y postion - the left boundary offset...
    5.             xAxisMax = transform.position.x + GetComponent<Collider2D>().bounds.max.x;
    6.             xAxisMin = transform.position.x - GetComponent<Collider2D>().bounds.min.x;
    7.             yAxisTargMax = other.transform.position.y + other.GetComponent<Collider2D>().bounds.max.y;
    8.             yAxisTargMin = other.transform.position.y - other.GetComponent<Collider2D>().bounds.min.y;
    9.             xAxisTargMax = other.transform.position.x + other.GetComponent<Collider2D>().bounds.max.x;
    10.             xAxisTargMin = other.transform.position.x - other.GetComponent<Collider2D>().bounds.min.x;
    11.  
    12.             float heightWidth = GetComponent<BoxCollider2D>().size.y / GetComponent<BoxCollider2D>().size.x; //compensates for a trigger that is not a perfect square (I hope)
    13.             float widthHight = GetComponent<BoxCollider2D>().size.x / GetComponent<BoxCollider2D>().size.y;
    14.  
    15.             if ((transform.position.y * widthHight) - other.transform.position.y < (transform.position.x * heightWidth) - other.transform.position.x)
    16.             {
    17.                 if (yAxisMax - yAxisTargMax < Mathf.Abs(2))
    18.                 {
    19.                     print("Top");
    20.                 }
    21.                 else if (yAxisMin - yAxisTargMin < Mathf.Abs(2))
    22.                 {
    23.                     print("Bottom");
    24.                 }
    25.             }
    26.             else if ((transform.position.y * widthHight) - other.transform.position.y > (transform.position.x * heightWidth) - other.transform.position.x)
    27.             {
    28.                 if (xAxisMax - xAxisTargMin < Mathf.Abs(1))
    29.                 {
    30.                     print("Right");
    31.                 }
    32.                 else if (xAxisMin - xAxisTargMax < Mathf.Abs(1))
    33.                 {
    34.                     print("Left");
    35.                 }
    36.             }
    37.         }
    This is all to get the general collision side of a trigger. soo much math.
     
  3. sebastiansgames

    sebastiansgames

    Joined:
    Mar 25, 2014
    Posts:
    114
    Wow that’s a lot of code! Wouldn’t it just be the difference between the collision object position and the player’s position? https://docs.unity3d.com/Manual/DirectionDistanceFromOneObjectToAnother.html

    If you normalize the return vector3 you should just be able to check x,y,z of that v3 positive or negative to see what side the collision happened on. Or at least that’s what I would try!
     
  4. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    It would be the difference between the players position and the collision objects position, but since that vector is a centerpoint (rather than an edge), I need to add/subtract the max/min boundaries to each axis, respectively. or at least I thought I did?
     
  5. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    So I'm trying to visualize what you're suggesting (cause it takes me a bit to comprehend). The "Direction distance from one object to another" would make a vector that... well, does exactly what the name suggests. Then I would check the x,y,z of that vector to see what is positive or negative, and it is there I could extrapolate the direction? Okay. I think I see it now. What does normalizing do?
     
  6. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    Hrm, I could check to see if the collision was on opposite sides, but how would that let me if the collision was Top, rather than Right?
     
  7. sebastiansgames

    sebastiansgames

    Joined:
    Mar 25, 2014
    Posts:
    114
    Normalizing takes away the distance so it’s pure direction. Unless I’m misunderstanding what you’re trying to accomplish (a possibility!) I’m not sure why comparing center points wouldn’t work.
     
  8. sebastiansgames

    sebastiansgames

    Joined:
    Mar 25, 2014
    Posts:
    114
    To check top vs right, compare the y to the x.
     
  9. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    Ah, you understand. I didn't. Yes, normalizing would indeed solve my issues more concision. Currently I was just comparing the boundary of the box to the boundary of the target to see if they were touching. I will try this out and get back to you in about 10 hours. I apologize for the delay, I'd love to try this right now, but I think I'm in a significantly different timezone than most of the people on here. :) And I had no idea about Direction distance from one object to another functions. You have helped immensely already. Every time I post here I learn about a new way to do whatever it is I'm trying to do. It's quite fantastic.
     
  10. sebastiansgames

    sebastiansgames

    Joined:
    Mar 25, 2014
    Posts:
    114
    I hope it works for you! That’s the approach I would try first— but I could be wrong! At least it’s an idea. Good luck!
     
  11. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    Okay, so I got it mostly working. It works perfectly for a square of any 1:1 ratio, but if the width and the height are ever not equal, then I run into problems. This is what works for perfect square collision boxes:
    Code (CSharp):
    1. var heading = other.transform.position - transform.position;
    2.             var distence = heading.magnitude;
    3.             var direction = heading / distence;
    4.  
    5.             if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
    6.             { print("Hit from Left/Right"); }
    7.              if (Mathf.Abs(direction.x) < Mathf.Abs(direction.y))
    8.             { print("Hit from Top/Bot"); }
    I made a calculation to determine what the ratio between the boxes is, But I'm struggling to figure out how to correctly apply the number. Here is the code
    Code (CSharp):
    1.  float heightWidth = GetComponent<BoxCollider2D>().bounds.size.y / GetComponent<BoxCollider2D>().bounds.size.x;
    2.             float widthHeight = GetComponent<BoxCollider2D>().bounds.size.x / GetComponent<BoxCollider2D>().bounds.size.y;
    This lets me know that if x is 10, and y is 10, heightWidth and widthHeight are both 1. If x is 20, and y is 5 then heightWidth is .25, and widthHeight is 4. I'm currently trying to figure out how to use those numbers to make direction.x and direction.y always have the same "percents off center" rather than real figures.
     
    Last edited: Nov 17, 2017
  12. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    I think I got it
    Code (CSharp):
    1.  if (Mathf.Abs(direction.x / widthHeight) > Mathf.Abs(direction.y / heightWidth))
    2.             { print("Hit from Left/Right"); }
    3.              if (Mathf.Abs(direction.x / widthHeight) < Mathf.Abs(direction.y / heightWidth))
    4.             { print("Hit from Top/Bot"); }
     
  13. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    yeah, it works pretty darn well. :D thank you!
     
  14. MadboyJames

    MadboyJames

    Joined:
    Oct 28, 2017
    Posts:
    262
    So here is the final code
    Code (CSharp):
    1.  if (Mathf.Abs(direction.x / widthHeight) > Mathf.Abs(direction.y / heightWidth))
    2.             {
    3.                 if (Mathf.Sign(direction.x) == 1)
    4.                     print("Hit From Right");
    5.                 if (Mathf.Sign(direction.x) == -1)
    6.                     print("Hit From Left");
    7.             }
    8. if (Mathf.Abs(direction.x / widthHeight) < Mathf.Abs(direction.y / heightWidth))
    9.             {
    10.                 if (Mathf.Sign(direction.y) == 1)
    11.                     print("Hit From Top");
    12.                 if (Mathf.Sign(direction.y) == -1)
    13.                     print("Hit From Bot");
    14.             }
    Also If I make those Else If statements the code janks out a bit, so I'm leaving them all as plain If statements.
     
    FireAlt and Biggerandreas like this.