/// <summary> /// 射线检测可走性。 /// 返回True表示检测到障碍 /// </summary> public bool LineCastForMoving(ref HitInfo hit, MoveType mov) { return(navgationGraph.LineCastForMoving(ref hit, mov)); }
public override bool LineCastForMoving(ref HitInfo hit, MoveType mov) { Int3 from = hit.from; Int3 to = hit.to; hit.hitPosition = from; if (trace != null) { trace.Clear(); } Int3 end = to; Int3 origin = from; if (origin == end) { hit.hitPosition = from; return(false); } NavMeshNode node = GetNearest(from, NNConstraint.None).node; if (node == null) { Debug.LogError("Could not find a valid node to start from"); hit.hitPosition = from; return(true); } origin = node.ClosestPointOnNode(origin); List <Int3> left = Util.ListPool <Int3> .Claim(); List <Int3> right = Util.ListPool <Int3> .Claim(); int counter = 0; while (true) { counter++; if (counter > 2000) { Debug.LogError("Linecast was stuck in infinite loop. Breaking."); Util.ListPool <Int3> .Release(left); Util.ListPool <Int3> .Release(right); return(true); } NavMeshNode newNode = null; if (trace != null) { trace.Add(node); } if (node.ContainsPoint(end)) { hit.hitPosition = to; Util.ListPool <Int3> .Release(left); Util.ListPool <Int3> .Release(right); return(false); } for (int i = 0; i < node.connections.Length; i++) { left.Clear(); right.Clear(); NavMeshNode other = GetNode(node.connections[i]) as NavMeshNode; if (!node.GetPortal(other, left, right)) { continue; } Int3 a = left[0]; Int3 b = right[0]; //i.e Left or colinear if (!VectorMath.RightXZ(a, b, origin)) { if (VectorMath.RightXZ(a, b, end)) { //Since polygons are laid out in clockwise order, the ray would intersect (if intersecting) this edge going in to the node, not going out from it continue; } } float factor1, factor2; if (VectorMath.LineIntersectionFactorXZ(a, b, origin, end, out factor1, out factor2)) { //Intersection behind the start if (factor2 < 0) { continue; } if (factor1 >= 0 && factor1 <= 1) { newNode = other; break; } } } if (newNode == null) { //Possible edge hit int vs = node.GetVertexCount(); for (int i = 0; i < vs; i++) { var a = node.GetVertex(i); var b = node.GetVertex((i + 1) % vs); //i.e left or colinear if (!VectorMath.RightXZ(a, b, origin)) { //Since polygons are laid out in clockwise order, the ray would intersect (if intersecting) this edge going in to the node, not going out from it if (VectorMath.RightXZ(a, b, end)) { //Since polygons are laid out in clockwise order, the ray would intersect (if intersecting) this edge going in to the node, not going out from it continue; } } float factor1, factor2; if (VectorMath.LineIntersectionFactorXZ(a, b, origin, end, out factor1, out factor2)) { if (factor2 < 0) { continue; } if (factor1 >= 0 && factor1 <= 1) { Vector3 intersectionPoint = (Vector3)a + (Vector3)(b - a) * factor1; hit.hitPosition = new Int3(intersectionPoint); Util.ListPool <Int3> .Release(left); Util.ListPool <Int3> .Release(right); return(true); } } } //Ok, this is wrong... Debug.LogWarning("Linecast failing because point not inside node, and line does not hit any edges of it"); Util.ListPool <Int3> .Release(left); Util.ListPool <Int3> .Release(right); return(false); } node = newNode; } }
// 射线碰撞,计算起点到终点间的最远可到达点 public override bool LineCastForMoving(ref HitInfo hit, MoveType mov) { Int3 from = hit.from; Int3 to = hit.to; Int3 blockPoint = from; int stepLen = Math.Min(200, navData.GridSize); bool blocked = false; // y = a*x + b Fix64 a = (Fix64)0; int dx = to.x - from.x; int dz = to.z - from.z; if (Math.Abs(dx) > Math.Abs(dz)) { a = (Fix64)dz / (Fix64)dx; int step = to.x - from.x > 0 ? stepLen : -stepLen; for (int x = from.x + step; step > 0 ? x <to.x + step : x> to.x - step; x += step) { x = step > 0 ? Math.Min(x, to.x) : Math.Max(x, to.x); Fix64 z = (Fix64)from.z + a * (Fix64)(x - from.x); var tmpPos = new Int3(x, 0, (int)z); if (!IsWalkable(tmpPos)) { if (!SpecialTerrainPassable(tmpPos, mov)) { blocked = true; break; } } blockPoint.Set(x, from.y, (int)z); } } else { a = (Fix64)dx / (Fix64)dz; int step = to.z - from.z > 0 ? stepLen : -stepLen; for (int z = from.z + step; step > 0 ? z <to.z + step : z> to.z - step; z += step) { z = step > 0 ? Math.Min(z, to.z) : Math.Max(z, to.z); Fix64 x = (Fix64)from.x + a * (Fix64)(z - from.z); var tmpPos = new Int3((int)x, 0, z); if (!IsWalkable(tmpPos)) { if (!SpecialTerrainPassable(tmpPos, mov)) { blocked = true; break; } } blockPoint.Set((int)x, from.y, z); } } if (blockPoint != from) { hit.hitPosition = blockPoint; } else { hit.hitPosition = to; } return(blocked); }