- Home /
Calculate collision angle [c#] Weird results?
I want to calculate the angle of a collision between A) The player character and B) the floor, a wall, or another character.
I want to calculate this so that later on I can determine how much damage different collisions will do to the player. Unfortunately the results I get seemed to be unrelated to the angle at which i'm actually colliding my object into the testing object.
This is my code, based on this Unity Answer:
void OnCollisionEnter(Collision collision)
{
Vector3 normal = collision.contacts[0].normal;
Vector3 myCollisionVelocity = rb.velocity;
collisionAngleTest1 = Vector3.Angle(myCollisionVelocity, -normal);
Debug.Log("AngleTest1: " + collisionAngleTest1);
}
Here are a couple of screenshots of my floating character being test-collided into a wall.
On scene-start, if I collide the character directly into the wall without steering at all the debugger returns either 90 degrees or 0 degrees. But when coming at a shallow angle as indicated in the second screenshot I often get returned angles of 80, 75, even things like 110. It just doesn't make sense to me. The angle that comes back in the debugger seems completely unrelated to the angle that I decide to collide with the wall.
It's worth noting that my character objects rotates and spins when it is bashed into things. 'W' adds force to the character in the direction the camera is looking (but force is locked to the horizontal axis to better examine my results while trying to fix this). So there is no real up, down, left right as far as the character is concerned, it is just propelled in the direction that the camera is looking. The character has a standard sphere collider attached and rigibody.
Can anyone see where i'm going wrong? I've tried tweaking my code so much; even recreating this solution here which yields very similar (but wrong) results as the above method. The code for this is here:
void OnCollisionEnter(Collision collision)
{
Vector3 orthagonalVector = collision.contacts[0].point - transform.position;
Vector3 myCollisionVelocity = rb.velocity;
collisionAngleTest2 = Vector3.Angle(orthagonalVector, myCollisionVelocity);
Debug.Log("AngleTest2: " + collisionAngleTest2);
}
I've tried a scene like yours (first OnCollisionEnter routine) and it worked fine for relatively small velocities, 30 or less. Increasing the velocity made the resulting angle grow, and at some higher speeds the ball passed through the wall. $$anonymous$$y scene had the following objects:
1- The wall: a simple cube stretched to the sides, without rigidbody and with "none" as the collider's physics material.
2- The ball: a simple sphere with a rigidbody, and its collider has a physics material with bounciness near to 1 (>0.8, for instance). Without a physics material or with a low bounciness material, the ball just bounced off in a direction close to the wall.
Hi Aldonaletto,
Thanks for your response.
I asked the same question on Reddit and recieved this response
Do you agree that:
"The results that are being returned are because rigidbody.velocity is already modified by the collision by the time OnCollisionEnter is called. You're comparing the velocity after the collision with the normal"?
I'm really hoping factoring in the angle of collision is possible. I'd like my character to be able to survive high-speed glancing collisions against floors / walls / other players but to take a lot more damage if the collision is head-on.
I'm not interested in calculating the angle that the character should rebound at – as this works fine with the rigibody physics anyway...
I just really want to be able to calculate damage based on: 1. the relative velocity of both colliding objects. 2. the mass of both objects, and; 3. the angle of collision.
Thanks again for your time.
The problem is, that the contact normal is NOT the surface normal. You need to raycast against that point again to get the actual surface normal.
Hi Hexagonius,
Thanks for your reply.
I asked the same question on Reddit and received this response.
Do you agree with the reddit poster that...
"The results that are being returned are because rigidbody.velocity is already modified by the collision by the time OnCollisionEnter is called. You're comparing the velocity after the collision with the normal" ?
What I really want is for the character to take different amounts of damage depending on the angle of collision. In my head this calculation with factor in: 1. the relative velocity of both colliding objects. 2. the mass of both objects, and; 3. the angle of collision. Do you think this is possible or not with Unity?
Thanks again for your time.
Answer by eddieion · Jun 15, 2017 at 06:17 PM
Okay so – Moving Vector3 myCollisionVelocity = rb.velocity; out of the OnCollisionEnter function seemed to have fixed the problem. Code below:
void OnCollisionEnter(Collision collision)
{
//COLLISION ANGLE
Vector3 normal = collision.contacts[0].normal;
collisionAngle = 90 - (Vector3.Angle(myVelocity, -normal));
Debug.Log("Collision Angle:" + collisionAngle);
//
}
So far this seems to be working nicely.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Collisions won't register? 2 Answers
OnCollisionEnter2D and OnCollisionExit2D 1 Answer
Different scores given at different angles of a collider 1 Answer