1
\$\begingroup\$

I have a ball and a rectangle in my game.enter image description here

The rectangle has a box collider 2d attached to it. How can I calculate or check when the ball hits the top of my collider, when it hits the bottom, left and right, so basically any side of the collider and also a corner of the collider, I have searched over the internet and not one answer that I found helped me into solving my problem. If anyone can help I would appreciate it.

\$\endgroup\$
2
  • \$\begingroup\$ You may like to look at using the Collision Normal \$\endgroup\$ Commented Apr 7, 2015 at 16:10
  • \$\begingroup\$ I have figured out how to check when the ball hits the top and down of the collider but im having trouble about sides \$\endgroup\$ Commented Apr 7, 2015 at 19:36

5 Answers 5

2
\$\begingroup\$

I know this is a bit old, just thought that someone else might find this useful. The transforms of the GameObjects has its anchor point in the center.

I did like this to check. In the circles OnCollisionEnter2D-method:

  void OnCollisionEnter2D(Collision2D coll) {
        if (coll.gameObject.tag == "Block_that_got_hit") {
            if ((this.transform.position.x - coll.collider.transform.position.x) < 0) {
                print("hit left");
            } else if ((this.transform.position.x - coll.collider.transform.position.x) > 0) {
                print("hit right");
            }
        }
    }

Things to account for is that this only divide the rectangle into two sections, left and right.

To get the size of collider called coll you could do: coll.collider.bounds.size.x

\$\endgroup\$
1
\$\begingroup\$

First, you find their position relative to each-other (a vector subtraction of their positions), normalize that, and then you have the direction from one game object to the other. From there, it's fairly trivial. Just if statements and checks of that direction.

An untested example:

void OnCollision2D(Collision2D col)
{
    Vector3 dir = (col.gameObject.transform.position - gameObject.transform.position).normalized;

    if (dir.y > 0)
    {
        // hit top
    }
    else if (dir.y < 0)
    {
        // hit bottom
    }
}
\$\endgroup\$
4
  • \$\begingroup\$ Tried that and its not working :S \$\endgroup\$ Commented Apr 7, 2015 at 16:02
  • \$\begingroup\$ What results are you getting when you run Debug.Log(dir)? \$\endgroup\$ Commented Apr 7, 2015 at 20:57
  • \$\begingroup\$ Nvm. Sorry, failure of my brain. That wouldn't work. \$\endgroup\$ Commented Apr 7, 2015 at 21:00
  • \$\begingroup\$ you can check if (dir.y > 0){ // hit top} else {// hit bottom} \$\endgroup\$ Commented Apr 19, 2017 at 5:56
0
\$\begingroup\$

One solution:

Build your rectangle of 4 pieces, and which one registers the collision tells you which side it happened on. If two register, you know it was on a corner.

Another solution:

Use the relative positions of the two objects and their velocities to figure out where it happened. For example, if the ball is above the rectangle, and the xcoords are almost the same, you know the collision happened on top.

The velocity is a sanity check. If the ball's y coord is below the rect's y coord, but the velocity indicates the ball was moving down, you know it moved too far in one frame and should have bounced back up first.

\$\endgroup\$
1
  • \$\begingroup\$ I tried adding 4 colliders as child objects each to register a side, but the problem is when i position them, if i position them to close to each other when the ball hits at the corner sometimes it goes up and sometimes it changes the side, i have experimented a little bit now and i figured out how to register top and bottom, but still having trouble with the sides. \$\endgroup\$ Commented Apr 7, 2015 at 15:05
0
\$\begingroup\$

I would rather use Raycast than OnCollision2D.

Here is the code.

Circle : no rigidbody 2d and no collider attached. Just having this script.
Box : box collider 2d attached.

using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;


public class CircleThing : MonoBehaviour
{
    float       _radius = 0.5f; //radius of the circle
    Vector3     _prevPos, _dirV;
    Transform   _transform;


    void Start() {
        _transform = transform;
        _prevPos = _transform.position;
    }

    void FixedUpdate() {
        if(_transform.position == _prevPos)
            return;

        _dirV = _transform.position - _prevPos;
        RaycastHit2D hit = Physics2D.Raycast(_transform.position, _dirV, _radius);
        if (hit.collider != null) {
            //Debug.Log ("Collided :" + hit.collider.name + " / " +  hit.normal);
            if(hit.normal.x != 0f)
            {
                if(hit.normal.x>0f)
                    Debug.Log ("Left Side");
                else 
                    Debug.Log ("Right Side");
            }
            else if(hit.normal.y != 0f)
            {
                if(hit.normal.y>0f)
                    Debug.Log ("Top Side");
                else 
                    Debug.Log ("Bottom Side");
            }
        }

        _prevPos = _transform.position;
    }
}

You can use reflection normal to identify collision side.

\$\endgroup\$
0
\$\begingroup\$

You can use contact point so first you check for collision and then you have an if statement to check which side it way eg. Vector3.up, here's an example:

public class NewBehaviourScript2 : MonoBehaviour {

   void OnCollisionEnter(Collision other){

       //This will print the first point of contact in Vector3
       print (other.contacts[0].point);

//if the contact of collision is equal to Vector3.up destroy the collided object
       if (other.contacts [0].point == Vector3.up) {

           Destroy(other.gameObject);
       }
   }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .