/// <summary> /// Time to collision of a ray to a disc. /// </summary> /// <param name="p">The start position of the ray</param> /// <param name="v">The velocity vector of the ray</param> /// <param name="p2">The center position of the disc</param> /// <param name="radius">The radius of the disc</param> /// <param name="collision">Specifies whether the time to collision is computed (false), or the time from collision (true).计算将要发生碰撞的时间,或者发生碰撞后经过的时间</param> /// <returns>Returns the time to collision of ray p + tv to disc D(p2, radius), and #RVO_INFTY when the disc is not hit. If collision is true, the value is negative.</returns> //点到直线距离公式:d = |AX0+BY0+C|/sqrt(A*A+B*B) //直线AX+BY+C=0,A=-V.y B=V.x C =P.x*V.y-V.x*P.y //可能碰撞:d<r=>d*d-r*r<0 //p2带入AX0+BY0+C //AX0+BY0+C = -v.y*p2.x+v.x*p2.y+p.x*v.y-v.x*p.y=v.x(p2.y-p.y)-v.y(p2.x-p.x)=det(v, ba) //d*d = det(v, ba)*det(v, ba)/absSq(v) //r*r-d*d>0 => r*r-det(v, ba)*det(v, ba)/absSq(v)>0 => discr = r*r*absSq(v) - det(v, ba)*det(v, ba)>0 // private float time2Collision(Vector2 p, Vector2 v, Vector2 p2, float radius, bool collision) { Vector2 ba = p2 - p; float sq_diam = radius * radius; float time; float discr = -RVOMath.Sqr(RVOMath.Det(v, ba)) + sq_diam * RVOMath.AbsSq(v); if (discr > 0) { if (collision) { time = (Vector2.Dot(v, ba) + Mathf.Sqrt(discr)) / RVOMath.AbsSq(v);//脱落碰撞需要的时间 if (time < 0) { time = -float.MaxValue; // Debug.LogError("isCollide time < 0 "); //? } } else { time = (Vector2.Dot(v, ba) - Mathf.Sqrt(discr)) / RVOMath.AbsSq(v);//将要发生碰撞的时间 if (time < 0) { time = float.MaxValue;//永远不会发生碰撞 } } } else {//不碰撞 if (collision) { time = -float.MaxValue; } else { time = float.MaxValue; } } return(time); }