Detect Side of Collision

I’m making a brick breaker game, and I’m trying to detect which side of the bricks the ball is hitting, so I can know which way to make the ball bounce.

I have this script attached to each of the bricks, and I’m trying to use raycasting to figure out which side of the brick the ball hits. It works part of the time, but sometimes the ball goes right through the object. Does anyone know how I can fix this?

using UnityEngine;
using System.Collections;

public class Brick : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}

    void OnCollisionEnter(Collision collision) {

        // Raycasting to determine what side of the brick the ball hits
        Ray myRay = new Ray(transform.position, collision.gameObject.transform.position);
        RaycastHit myRayHit;

        Physics.Raycast(myRay, out myRayHit);

        Vector3 myNormal = myRayHit.normal;
        myNormal = myRayHit.transform.TransformDirection(myNormal);

        if (myNormal == gameObject.transform.forward) {
            // If the ball hits the top of the brick
            Destroy(gameObject);
            collision.gameObject.GetComponent<Ball>().speedZ = -collision.gameObject.GetComponent<Ball>().speedZ;
        }

        else if (myNormal == -gameObject.transform.forward) {
            // If the ball hits the bottom of the brick
            Destroy(gameObject);
            collision.gameObject.GetComponent<Ball>().speedZ = -collision.gameObject.GetComponent<Ball>().speedZ;
        }
        else if (myNormal == gameObject.transform.right) {
            // If the ball hits the right of the brick
            Destroy(gameObject);
            collision.gameObject.GetComponent<Ball>().speedX = -collision.gameObject.GetComponent<Ball>().speedX;
        }
        else if (myNormal == -gameObject.transform.right) {
            // If the ball hits the left of the brick
            Destroy(gameObject);
            collision.gameObject.GetComponent<Ball>().speedX = -collision.gameObject.GetComponent<Ball>().speedX;
        }

    }

}

Hi,

I just wanted to share the code I made based on the replies from @fafase. It has slight modifications to work in a 2D project.

Notice that I decided to display what side of the PLAYER is hitting the wall, not what side of the wall was touched. I mean, it displays “Left” for the left side of the player (which is hitting the right side of a wall). I did this because it makes more sense for my game.

    void OnCollisionEnter(Collision col)
    {
        if (col.gameObject.tag.Equals("Wall"))
        {    
            Vector3 hit = col.contacts[0].normal;
            Debug.Log(hit);
            float angle = Vector3.Angle(hit, Vector3.up);

            if (Mathf.Approximately(angle, 0))
            {
                //Down
                Debug.Log("Down");
            }
            if(Mathf.Approximately(angle, 180))
            {
                //Up
                Debug.Log("Up");
            }
            if(Mathf.Approximately(angle, 90)){
                // Sides
                Vector3 cross = Vector3.Cross(Vector3.forward, hit);
                if (cross.y > 0)
                { // left side of the player
                    Debug.Log("Left");
                }
                else
                { // right side of the player
                    Debug.Log("Right");
                }
            }
        }
    }

In my particular case the player is rectangular and there’s no way to touch the corners, so this works great.

Best regards!

Simply use dot product/Angle and cross product to figure out where it comes from.

Use the normal of the hit and compare to a world vector of your choice.
With dot only you can determine if it is front or back of the box.

To determine if side you can use also cross product.

float angle = Vector3.Angle(hit.normal,Vector3.forward);

if(Mathf.Approximately(angle, 0))// back
if(Mathf.Approximately(angle, 180))// front
if(Mathf.Approximately(angle, 90)){
   Vector3 cross = Vector.Cross(Vector3.forward,hit.normal);
   if(cross.y > 0) // Right
   else // left
}

That should be it.