Well basically I had to do it manually. Do linecast only on nodes with appropriate tags.
I filter nodes returned by Linecast as “trace” list.
I take last proper node in chain of proper nodes and do my own intersection against mesh to get intersection point. And I think such a functionality should be implemented in a library.
BTW. Here is a part of my code:
public StraightPathCheckResult CheckStraightPathValidity(Vector3 start, Vector3 end, PathGraph pathGraph, uint pathfindingTags) {
IRaycastableGraph reycastableGraph = this.GetRecastableGraph(pathGraph); if (reycastableGraph == null) { throw new GameException("Graph (" + pathGraph.ToString() + ") is not IRaycastableGraph"); }
StraightPathCheckResult straightPathCheckResult = new StraightPathCheckResult();
List<GraphNode> traversedNodes = new List<GraphNode>(); GraphHitInfo graphHitInfo; straightPathCheckResult.isStraight = !reycastableGraph.Linecast(start, end, null, out graphHitInfo, traversedNodes); straightPathCheckResult.hitPoint = straightPathCheckResult.isStraight ? end : graphHitInfo.point; straightPathCheckResult.isHitPointOnValidNode = true; if (pathfindingTags == ~(uint)0) { return straightPathCheckResult; }
if (traversedNodes.Count == 0) { straightPathCheckResult.isHitPointOnValidNode = false; return straightPathCheckResult; }
if (traversedNodes[0] is MeshNode) { for(int i=0;i < traversedNodes.Count; i++) { MeshNode node = traversedNodes[i] as MeshNode; if ( ((1 << (int)node.Tag) & pathfindingTags) == 0) { // first invalid tag node
if(i == 0) { //first node is invalid straightPathCheckResult.isHitPointOnValidNode = false; return straightPathCheckResult; } MeshNode lastValidNode = traversedNodes[i - 1] as MeshNode; int vertexCount = lastValidNode.GetVertexCount(); Vector2[] vertices = new Vector2[vertexCount + 1]; for(int vInd = 0; vInd < vertexCount; vInd++) { Vector3 v3 = (Vector3)lastValidNode.GetVertex(vInd); vertices[vInd] = new Vector2(v3.x, v3.z); } vertices[vertexCount - 1] = vertices[0];
Vector2 startV2 = new Vector2(start.x, start.z); Vector2 endV2 = new Vector2(end.x, end.z);
float minSqrDistance = float.MaxValue; Vector3 closestIntersection = Vector3.zero; for (int segmentInd = 1; segmentInd < vertexCount; segmentInd++) { Vector2 intersection; if(MathUtils.LineSegmentsIntersection(vertices[segmentInd - 1], vertices[segmentInd], startV2, endV2, out intersection)) { float curSqrDist = (intersection - endV2).sqrMagnitude; if(curSqrDist <= minSqrDistance) { minSqrDistance = curSqrDist; closestIntersection = new Vector3(intersection.x,0,intersection.y); } } }
straightPathCheckResult.hitPoint = closestIntersection; straightPathCheckResult.isHitPointOnValidNode = true; straightPathCheckResult.isStraight = false; } } }
return straightPathCheckResult; }