Class Funnel
Public
Implements the funnel algorithm as well as various related methods.
using UnityEngine;
using Pathfinding;
using Pathfinding.Drawing;
public class FunnelExample : MonoBehaviour {
public Transform target = null;
void Update () {
var path = ABPath.Construct(transform.position, target.position);
AstarPath.StartPath(path);
path.BlockUntilCalculated();
// Apply some default adjustments to the path
// not necessary if you are using the Seeker component
new StartEndModifier().Apply(path);
// Split the path into segments and links
var parts = Funnel.SplitIntoParts(path);
// Optionally simplify the path to make it straighter
var nodes = path.path;
Funnel.Simplify(parts, ref nodes);
using (Draw.WithLineWidth(2)) {
// Go through all the parts and draw them in the scene view
for (int i = 0; i < parts.Count; i++) {
var part = parts[i];
if (part.isLink) {
// Draw off-mesh links as a single line
Draw.Line(part.startPoint, part.endPoint, Color.cyan);
} else {
// Calculate the shortest path through the funnel
var portals = Funnel.ConstructFunnelPortals(nodes, part);
var pathThroghPortals = Funnel.Calculate(portals, unwrap: true, splitAtEveryPortal: false);
Draw.Polyline(pathThroghPortals, Color.black);
}
}
}
}
}
In the image you can see the output from the code example above. The cyan lines represent off-mesh links.
Inner Types
Public Static Methods
List<Vector3>
Calculate
(
FunnelPortals | funnel | The portals of the funnel. The first and last vertices portals must be single points (so for example left[0] == right[0]). |
bool | unwrap | Determines if twists and bends should be straightened out before running the funnel algorithm. |
bool | splitAtEveryPortal | If true, then a vertex will be inserted every time the path crosses a portal instead of only at the corners of the path. The result will have exactly one vertex per portal if this is enabled. This may introduce vertices with the same position in the output (esp. in corners where many portals meet). |
)
Calculate the shortest path through the funnel.
If the unwrap option is disabled the funnel will simply be projected onto the XZ plane. If the unwrap option is enabled then the funnel may be oriented arbitrarily and may have twists and bends. This makes it possible to support the funnel algorithm in XY space as well as in more complicated cases, such as on curved worlds. 

void
Simplify
(
)
Simplifies a funnel path using linecasting.
Running time is roughly O(n^2 log n) in the worst case (where n = end-start) Actually it depends on how the graph looks, so in theory the actual upper limit on the worst case running time is O(n*m log n) (where n = end-start and m = nodes in the graph) but O(n^2 log n) is a much more realistic worst case limit.
Requires #graph to implement IRaycastableGraph
List<PathPart>
SplitIntoParts
(
)
Splits the path into a sequence of parts which are either off-mesh links or sequences of adjacent triangles.
void
Unwrap
(
)
Unwraps the funnel portals from 3D space to 2D space.
The result is stored in the left and right arrays which must be at least as large as the funnel.left and funnel.right lists.
The input is a funnel like in the image below. It may be rotated and twisted.
The output will be a funnel in 2D space like in the image below. All twists and bends will have been straightened out. 
Private/Protected Members
void
Calculate
(
Vector2[] | left | |
Vector2[] | right | |
int | numPortals | |
int | startIndex | |
List<int> | funnelPath | |
int | maxCorners | |
out bool | lastCorner | |
)
Funnel algorithm.
funnelPath will be filled with the result. The result is the indices of the vertices that were picked, a non-negative value refers to the corresponding index in the left array, a negative value refers to the corresponding index in the right array. So e.g 5 corresponds to left[5] and -2 corresponds to right[2]
int
FixFunnel
(
Vector2[] | left | |
Vector2[] | right | |
int | numPortals | |
)
Try to fix degenerate or invalid funnels.
Return
The number of vertices at the start of both arrays that should be ignored or -1 if the algorithm failed.
bool
LeftOrColinear
(
)
True if b is to the left of or on the line from (0,0) to a.
bool
RightOrColinear
(
)
True if b is to the right of or on the line from (0,0) to a.