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\$
  • \$\begingroup\$ You may like to look at using the Collision Normal \$\endgroup\$ – Kelly Thomas Apr 7 '15 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\$ – Fahir M Apr 7 '15 at 19:36
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

| improve this answer | |
\$\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
    }
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Tried that and its not working :S \$\endgroup\$ – Fahir M Apr 7 '15 at 16:02
  • \$\begingroup\$ What results are you getting when you run Debug.Log(dir)? \$\endgroup\$ – Wolfgang Skyler Apr 7 '15 at 20:57
  • \$\begingroup\$ Nvm. Sorry, failure of my brain. That wouldn't work. \$\endgroup\$ – Wolfgang Skyler Apr 7 '15 at 21:00
  • \$\begingroup\$ you can check if (dir.y > 0){ // hit top} else {// hit bottom} \$\endgroup\$ – Seyed Morteza Kamali Apr 19 '17 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.

| improve this answer | |
\$\endgroup\$
  • \$\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\$ – Fahir M Apr 7 '15 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.

| improve this answer | |
\$\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);
       }
   }
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.