public static bool lineToCircle( Vector2 start, Vector2 end, Circle s, out RaycastHit hit )
{
hit = new RaycastHit();
// calculate the length here and normalize d separately since we will need it to get the fraction if we have a hit
var lineLength = Vector2.Distance( start, end );
var d = ( end - start ) / lineLength;
var m = start - s.position;
var b = Vector2.Dot( m, d );
var c = Vector2.Dot( m, m ) - s.radius * s.radius;
// exit if r's origin outside of s (c > 0) and r pointing away from s (b > 0)
if( c > 0f && b > 0f )
return false;
var discr = b * b - c;
// a negative descriminant means the line misses the circle
if( discr < 0 )
return false;
// ray intersects circle. calculate details now.
hit.fraction = -b - Mathf.sqrt( discr );
// if fraction is negative, ray started inside circle so clamp fraction to 0
if( hit.fraction < 0 )
hit.fraction = 0;
hit.point = start + hit.fraction * d;
Vector2.Distance( ref start, ref hit.point, out hit.distance );
hit.normal = Vector2.Normalize( hit.point - s.position );
hit.fraction = hit.distance / lineLength;
return true;
}