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
3
Question by PacmanBits · Jul 05, 2012 at 09:20 AM · collisionanglenormal

Collisions, Getting the Normal of the Collision Surface (Not the Angle of Impact)

I'm working on my first Unity project right now (a bit of a self prescribed crash-course) and I've run into a slight issue.

I'm trying deflect one object off of another one (via collision). For now, the deflection should be at a perfectly mirrored angle. No problem! I think to myself, I see this super handy contact.normal property; seems pretty straight forward (I'm working in a 2D plane, so it really should be have been smooth sailing from there).

A few frustratingly failed attempts, and several thousand drawRay commands later, I realize that the normal is NOT a normal to the face of impact, but is a normal OF the impact (ie, mirrors the angle of impact).

This is actually useful information, but to be useful, I need a face-normal to reflect the angle of impact over.

The moving object is using this.rigidbody.velocity = so I can't rely on built in physics; I'm also being a total stickler for how this bounce looks, so I'd really love to maintain full control over it.

Relevant code below:

 function OnCollisionEnter(collision : Collision)
 {
  var contactCount : int = 0;
  var normalAve : Vector3 = Vector3(0,0,0);
  var velocityAve : Vector3 = Vector3.zero;
  
  for (var contact : ContactPoint in collision.contacts)
  {
  contactCount++;
  normalAve += contact.normal;

  velocityAve += collision.relativeVelocity;
  Debug.DrawRay(contact.point, contact.normal, Color.green, 2, false);
  }
  
  normalAve /= contactCount;
  velocityAve /= contactCount;
  
  var damage = Vector3.Dot(normalAve, velocityAve) * collision.rigidbody.mass;
 
  
  
  life -= damage;
  
  if(life <= 0)
  {
      // Stackoverflow people can ignore this, bounces
      // don't happen when you're dead
  this.rigidbody.useGravity = this.GetComponent(ship_small_physics).stage.GetComponent(stage_params).grav_on_hit;
  
  this.GetComponent(ship_small_physics).impact();
  }else{
      // Stackoverflow people! Right here!
  Debug.Log("survived! with " + life + " life");
  this.GetComponent(ship_small_physics).small_impact(normalAve, velocityAve);
  }
 }

Then, in .small_impact

 function small_impact(n : Vector3, v : Vector3)
 {
  var h_angle : Vector3 = Vector3(n.x, 0, n.z);
  Debug.DrawRay(this.transform.position, n, Color.blue, 2, false);
  Debug.DrawRay(this.transform.position, h_angle, Color.red, 2, false);
 }

Just to clarify: The game IS in some sorts of 3D, but for various reasons in this case I only care about the collision normals in the x-z plane (another reason why the plane old physics engine won't do). That's why I make a new vector h_angle that's essentially the projection of the collision-normal onto the x-z plane.

It's entirely possible that I'm just not understanding everything.

Comment
Add comment
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

1 Reply

· Add your reply
  • Sort: 
avatar image
3

Answer by Nevermind · Feb 26, 2014 at 09:11 AM

Just had this same problem, and I came up with this solution: You need to find one single point on the collider that you can consider as the "collision point". This can never be completely accurate, unless you code a full-blown collision solver yourself; but what you can do is use raycasting to find some approximation. Basically, you step away from the collision using the collision normal provided, and than raycast against the collider. RaycastHit class gives you the actual surface normal at the hit point, as well as other potentially useful info (like what triangle exactly was hit) Here's my code (it's not very polished, but is generally working)

 void OnCollisionEnter(Collision info){
   // find collision point and normal. You may want to average over all contacts
   var point = info.contacts[0].point;
   var dir = -info.contacts[0].normal; // you need vector pointing TOWARDS the collision, not away from it
   // step back a bit
   point -= dir;
   RaycastHit hitInfo;
   // cast a ray twice as far as your step back. This seems to work in all
   // situations, at least when speeds are not ridiculously big
   if(info.collider.Raycast( new Ray( point, dir ), out hitInfo, 2 ) )
   {
     // this is the collider surface normal
     var normal = hitInfo.normal;
     // this is the collision angle
     // you might want to use .velocity instead of .forward here, but it 
     // looks like it's already changed due to bounce in OnCollisionEnter
     var angle = Vector3.Angle( -transform.forward, normal );
   }
 }
Comment
Add comment · Show 3 · 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 ahmadian · Sep 19, 2017 at 06:02 AM 0
Share

so what should I do with the angle if I want to instantiate some thing on the surface?

avatar image Dorscherl · Mar 12, 2018 at 09:30 PM 0
Share

Would it be better to do this in OnCollisionStay()? I need to constantly check for ground and the get the slope normal. Also would use would the angle have exactly? Slope threshold check?

avatar image Rhysimus · Jul 28, 2020 at 04:32 PM 0
Share

Perfect answer and solution for me. Thank you!

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

8 People are following this question.

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

Related Questions

Collision Normal 1 Answer

Not detecting a simple collision? 2 Answers

Get angle to retarget collision object. 1 Answer

Obtaining contact point and normal of first object in collision 0 Answers

Average of Normals 1 Answer


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