Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by GlitteringStone · Jun 13, 2013 at 05:20 AM · collisiondetectionside

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;
         }
 
     }
 
 }
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Benproductions1 · Jun 13, 2013 at 05:35 AM 0
Share

Why not just use some simple maths to figure out collisions?

avatar image GlitteringStone · Jun 13, 2013 at 05:38 AM 0
Share

Because I can't get the position of the surface of the object, so if I try and compare positions of the bricks to the ball, then the ball would have overlapped with the brick when it detects the collision.

2 Replies

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by fafase · Jun 13, 2013 at 05:55 AM

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.

Comment
Add comment · Show 13 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image GlitteringStone · Jun 13, 2013 at 06:05 AM 0
Share

Is the hit the same "myRayHit" that I have in my code already, or is it something else?

avatar image fafase · Jun 13, 2013 at 07:28 AM 0
Share

This should go on the sphere and hit is:

 Vector3 hit = hit.contacts[0].normal;
avatar image GlitteringStone · Jun 13, 2013 at 06:57 PM 0
Share

It's not working, I put a debug log statement inside each of the if blocks and none of them print out when I hit a brick, so it seems like none of the if statements are working.

This is my OnCollisionEnter function, do you think you could take a look? It's attached to the ball. The tags are there to control bouncing off the walls as well, that part works fine.

 void OnCollisionEnter(Collision collision) {
 
         if (collision.gameObject.tag == "horizontalWall") {
             speedZ = -speedZ;
         }
         else if (collision.gameObject.tag == "verticalWall") {
             speedX = -speedX;
         }
         else if (collision.gameObject.tag == "brick") {
 
             Vector3 hit = collision.contacts[0].normal;
             Debug.Log(hit);
             float angle = Vector3.Angle(hit, Vector3.forward);
 
             if ($$anonymous$$athf.Approximately(angle, 0)) { // top
                 Destroy(collision.gameObject);
                 speedZ = -speedZ;
             }
             if ($$anonymous$$athf.Approximately(angle, 180)) { // bottom
                 Destroy(collision.gameObject);
                 speedZ = -speedZ;
             }
             if ($$anonymous$$athf.Approximately(angle, 90)) {
                 Vector3 cross = Vector3.Cross(Vector3.forward, hit);
                 if (cross.y > 0) { // right
                     Destroy(collision.gameObject);
                     speedX = -speedX;
                 }
                 else { // left
                     Destroy(collision.gameObject);
                     speedX = -speedX;
                 }
             }
         }
     }
avatar image fafase · Jun 14, 2013 at 05:50 AM 0
Share

Is your level aligned with the world forward?

avatar image fafase · Jun 14, 2013 at 06:21 AM 1
Share

I would recommend to place the debug at

 else if (collision.gameObject.tag == "brick")

Then try with Dot product:

 if (Vector3.Dot(hit,Vector3.forward) > 0) { // top
   // Back
 }else if(Vector3.Dot(hit,Vector3.forward) < 0){
    // Front
 }else if(Vector3.Dot(hit,Vector3.forward) == 0){
    // Sides
 }
Show more comments
avatar image
7

Answer by Forest3 · Sep 21, 2015 at 09:35 AM

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!

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Biktor · Feb 02, 2016 at 12:40 PM 0
Share

Thank you, works like a charm.

avatar image TheYumma · Apr 20, 2017 at 06:05 PM 0
Share

Works great for my prototype. Thank you much appreciated

avatar image avodhel · Nov 02, 2018 at 08:15 PM 0
Share

you're the best man thanks.

avatar image Ajdar_div_salar · Jun 04, 2021 at 05:21 AM 0
Share

For this to work in a 2D project with Unity 2020.1.6f1, rewrite the first line as :

void OnCollisionEnter2D(Collision2D col)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

22 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Rigid Body Collision Detection 1 Answer

Very fast objects and collision detect + Optimize issue 1 Answer

Detect if ball is on a platform or if it fell 4 Answers

Trouble with raycast hitting a tagged object 0 Answers

Jittery Collision Detection 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges