# How to get the tangent and normal of a collision?

In my game, one of my objects casts a ray into a 2d space. If that ray were to hit another object, I'd like to draw a line that is perpendicular to the tangent of the ray's hit point. So when the ray hits the other object, a tangent is formed at the point of contact, and then I'd like to use the linerenderer component to draw a line that is perpendicular to that tangent. I already know how to use the linerenderer to draw lines, but I don't know how to get the tangent and normal from a collision.

  if (Input.GetMouseButton(0))
{
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

var direction = (mousePos - (Vector2)cueBall.position).normalized;

var hit = Physics2D.Raycast(cueBall.position, direction, Mathf.Infinity, 1 << LayerMask.NameToLayer("Ball"));

if (hit)
{
_line1.SetPositions(cueBall.position, hit.point); //This is the line from the cueball to the red ball.
_line2.SetPositions(hit.point, hit.normal); //This is supposed to be the predicted trajectory of the red ball.
}
}


• Presumably you inspected the RaycastHit2D result that you get from the raycast query? Is the normal it provides not suitable for your case? Apr 3 '19 at 20:08
• When I created a line with one point being the ray's hit point and the other being the ray.normal, it did not look like a line that would be perpendicular to the tangent. The reason I say this is because I'm making a billiard game, and when the cueball casts a ray to the ball it's about to hit, the line that I drew was not the one that the ball traveled on. It was not the right trajectory that I drew. Apr 3 '19 at 20:21
• Right, because a normal is a direction, not a point, and the trajectory will be influenced by factors other than just the collision normal. Can you show us what you're doing in code so far, and a picture of the results you're getting? Apr 3 '19 at 20:23
• @DMGregory Sure, I went ahead and updated the question. Apr 3 '19 at 20:40

Your vector math here is not correct, nor even meaningful.

_line2.SetPositions(hit.point, hit.normal);


Here you're using a normal, which is a direction, as though it was a point in space. This does not make geometric sense.

If you want to draw a line from the hit point to a new point in the direction of the collision normal from that hit point then you'd do it like this:

float drawnLength = 1.0f;

var endpoint = hit.point + drawnLength * hit.normal;
_line2.SetPositions(hit.point, endpoint);


But this still does not give you the expected trajectory of an elastic collision. It gives you the line of symmetry between the incoming and outgoing trajectories.

To get an estimated bounce trajectory, you need to perform the reflection:

var reflectedDirection = Vector2.Reflect(direction, hit.normal);

endpoint = hit.point + drawnLength * reflectedDirection;
_line3.SetPositions(hit.point, endpoint);


Also note that for better accuracy in the presence of corners/obstacles, you'll want to use a CircleCast, not a Raycast, to account for the radius of the ball.

• Thanks so much. I replaced hit.point + drawnLength * hit.normal with hit.point - drawnLength * hit.normal and it worked perfectly. Thanks again. Also thanks for suggesting I use CircleCast instead of Raycast. Prior to this, I had to add a 2nd, larger circle collider to the red ball to make sure the ray doesn't miss it. I guess the circlecast makes up for this problem :) Apr 3 '19 at 21:15