Public
Automatically generates navmesh graphs based on world geometry.
The recast graph is based on Recast (http://code.google.com/p/recastnavigation/).
I have translated a good portion of it to C# to run it natively in Unity.
For a tutorial on how to configure a recast graph, take a look at Automatically generating a navmesh.
How a recast graph works
When generating a recast graph what happens is that the world is voxelized. You can think of this as constructing an approximation of the world out of lots of boxes. If you have played Minecraft it looks very similar (but with smaller boxes). ![](images/recast/voxelized_truck.jpg)
The Recast process is described as follows:
The voxel mold is build from the input triangle mesh by rasterizing the triangles into a multi-layer heightfield. Some simple filters are then applied to the mold to prune out locations where the character would not be able to move.
The walkable areas described by the mold are divided into simple overlayed 2D regions. The resulting regions have only one non-overlapping contour, which simplifies the final step of the process tremendously.
The navigation polygons are peeled off from the regions by first tracing the boundaries and then simplifying them. The resulting polygons are finally converted to convex polygons which makes them perfect for pathfinding and spatial reasoning about the level.
It works exactly like that in the C# version as well, except that everything is triangulated to triangles instead of n-gons. The recast generation process usually works directly on the visiable geometry in the world, this is usually a good thing, because world geometry is usually more detailed than the colliders. You can however specify that colliders should be rasterized, if you have very detailed world geometry, this can speed up the scan.
Check out the second part of the Get Started Tutorial which discusses recast graphs.
Exporting for manual editing
In the editor there is a button for exporting the generated graph to a .obj file. Usually the generation process is good enough for the game directly, but in some cases you might want to edit some minor details. So you can export the graph to a .obj file, open it in your favourite 3D application, edit it, and export it to a mesh which Unity can import. You can then use that mesh in a navmesh graph.
Since many 3D modelling programs use different axis systems (unity uses X=right, Y=up, Z=forward), it can be a bit tricky to get the rotation and scaling right. For blender for example, what you have to do is to first import the mesh using the .obj importer. Don't change anything related to axes in the settings. Then select the mesh, open the transform tab (usually the thin toolbar to the right of the 3D view) and set Scale -> Z to -1. If you transform it using the S (scale) hotkey, it seems to set both Z and Y to -1 for some reason. Then make the edits you need and export it as an .obj file to somewhere in the Unity project. But this time, edit the setting named "Forward" to "Z forward" (not -Z as it is per default).
![](images/recastgraph_inspector.png)
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
Inner Types
Public Methods
void
EnsureInitialized
()
Initialize the graph with empty tiles if it is not currently scanned.
void
ReplaceTiles
(
RecastBuilder.TileMeshes | tileMeshes | The tiles to load. They will be loaded into the graph at the TileMeshes.tileRect tile coordinates. |
float | yOffset=0 | All vertices in the loaded tiles will be moved upwards (or downwards if negative) by this amount. |
)
Load tiles from a TileMeshes object into this graph.
This can be used for many things, for example world streaming or placing large prefabs that have been pre-scanned.
The loaded tiles must have the same world-space size as this graph's tiles. The world-space size for a recast graph is given by the cellSize multiplied by tileSizeX (or tileSizeZ).
If the graph is not scanned when this method is called, the graph will be initialized and consist of just the tiles loaded by this call.
// Scans the first 6x6 chunk of tiles of the recast graph (the IntRect uses inclusive coordinates)
var graph = AstarPath.active.data.recastGraph;
var buildSettings = RecastGraph.RecastBuilder.BuildTileMeshes(graph, new IntRect(0, 0, 5, 5));
var disposeArena = new Pathfinding.Jobs.DisposeArena();
var promise = buildSettings.Schedule(disposeArena);
AstarPath.active.AddWorkItem(() => {
// Wait for the asynchronous job to complete
var result = promise.Complete();
RecastGraph.RecastBuilder.TileMeshes tiles = result.tileMeshes.ToManaged();
// Take the scanned tiles and place them in the graph,
// but not at their original location, but 2 tiles away, rotated 90 degrees.
tiles.tileRect = tiles.tileRect.Offset(new Int2(2, 0));
tiles.Rotate(1);
graph.ReplaceTiles(tiles);
// Dispose unmanaged data
disposeArena.DisposeAll();
result.Dispose();
});
Warning
All arrays in the tileMeshes parameter will be consumed by this method. You should not use them for anything else after calling this method.
void
Resize
(
IntRect | newTileBounds | Rectangle of tiles that the graph should contain. Relative to the old bounds. |
)
Resize the number of tiles that this graph contains.
This can be used both to make a graph larger, smaller or move the bounds of the graph around. The new bounds are relative to the existing bounds which are IntRect(0, 0, tileCountX-1, tileCountZ-1).
Any current tiles that fall outside the new bounds will be removed. Any new tiles that did not exist inside the previous bounds will be created as empty tiles. All other tiles will be preserved. They will stay at their current world space positions.
Note
This is intended to be used at runtime on an already scanned graph. If you want to change the bounding box of a graph like in the editor, use forcedBoundsSize and forcedBoundsCenter instead.
AstarPath.active.AddWorkItem(() => {
var graph = AstarPath.active.data.recastGraph;
var currentBounds = new IntRect(0, 0, graph.tileXCount-1, graph.tileZCount-1);
// Make the graph twice as large, but discard the first 3 columns.
// All other tiles will be kept and stay at the same position in the world.
// The new tiles will be empty.
graph.Resize(new IntRect(3, 0, currentBounds.xmax*2, currentBounds.ymax*2));
});
void
SnapForceBoundsToScene
()
Changes the bounds of the graph to precisely encapsulate all objects in the scene that can be included in the scanning process based on the settings.
Which objects are used depends on the settings. If an object would have affected the graph with the current settings if it would have been inside the bounds of the graph, it will be detected and the bounds will be expanded to contain that object.
This method corresponds to the 'Snap bounds to scene' button in the inspector.
Public Static Methods
Public Variables
float
cellSize = 0.5F
Voxel sample size (x,z).
When generating a recast graph what happens is that the world is voxelized. You can think of this as constructing an approximation of the world out of lots of boxes. If you have played Minecraft it looks very similar (but with smaller boxes).
The cell size is the width and depth of those boxes. The height of the boxes is usually much smaller and automatically calculated however. See CellHeight.
Lower values will yield higher quality navmeshes, however the graph will be slower to scan.
float
characterRadius = 1.5F
Radius of the agent which will traverse the navmesh.
The navmesh will be eroded with this radius.
float
colliderRasterizeDetail = 10
Controls detail on rasterization of sphere and capsule colliders.
This controls the number of rows and columns on the generated meshes. A higher value does not necessarily increase quality of the mesh, but a lower value will often speed it up.
You should try to keep this value as low as possible without affecting the mesh quality since that will yield the fastest scan times.
float
contourMaxError = 2F
Max distance from simplified edge to real edge.
This value is measured in voxels. So with the default value of 2 it means that the final navmesh contour may be at most 2 voxels (i.e 2 times cellSize) away from the border that was calculated when voxelizing the world. A higher value will yield a more simplified and cleaner navmesh while a lower value may capture more details. However a too low value will cause the individual voxels to be visible (see image below).
![](images/recast/max_edge_error.gif)
int
editorTileSize = 128
Size in voxels of a single tile.
This is the width of the tile.
![](images/recast/tile.png)
A large tile size can be faster to initially scan (but beware of out of memory issues if you try with a too large tile size in a large world) smaller tile sizes are (much) faster to update.
Different tile sizes can affect the quality of paths. It is often good to split up huge open areas into several tiles for better quality paths, but too small tiles can also lead to effects looking like invisible obstacles. For more information about this take a look at Notes about navmesh graphs. Usually it is best to experiment and see what works best for your game.
When scanning a recast graphs individual tiles can be calculated in parallel which can make it much faster to scan large worlds. When you want to recalculate a part of a recast graph, this can only be done on a tile-by-tile basis which means that if you often try to update a region of the recast graph much smaller than the tile size, then you will be doing a lot of unnecessary calculations. However if you on the other hand update regions of the recast graph that are much larger than the tile size then it may be slower than necessary as there is some overhead in having lots of tiles instead of a few larger ones (not that much though).
Recommended values are between 64 and 256, but these are very soft limits. It is possible to use both larger and smaller values.
Vector3
forcedBoundsCenter
Center of the bounding box.
Scanning will only be done inside the bounding box
Layer mask which filters which objects to include.
float
maxEdgeLength = 20
Longer edges will be subdivided.
Reducing this value can sometimes improve path quality since similarly sized triangles yield better paths than really large and really triangles small next to each other. However it will also add a lot more nodes which will make pathfinding slower. For more information about this take a look at Notes about navmesh graphs.
float
maxSlope = 30
Max slope in degrees the character can traverse.
float
minRegionSize = 3
Minumum region size.
Small regions will be removed from the navmesh. Measured in square world units (square meters in most games).
![](images/recast/min_region_size.gif)
If a region is adjacent to a tile border, it will not be removed even though it is small since the adjacent tile might join it to form a larger region.
bool
rasterizeColliders
Use colliders to calculate the navmesh.
bool
rasterizeMeshes = true
Use scene meshes to calculate the navmesh.
bool
rasterizeTerrain = true
Include the Terrain in the scene.
bool
rasterizeTrees = true
Rasterize tree colliders on terrains.
If the tree prefab has a collider, that collider will be rasterized. Otherwise a simple box collider will be used and the script will try to adjust it to the tree's scale, it might not do a very good job though so an attached collider is preferable.
Note
It seems that Unity will only generate tree colliders at runtime when the game is started. For this reason, this graph will not pick up tree colliders when scanned outside of play mode but it will pick them up if the graph is scanned when the game has started. If it still does not pick them up make sure that the trees actually have colliders attached to them and that the tree prefabs are in the correct layer (the layer should be included in the layer mask).
RelevantGraphSurfaceMode
relevantGraphSurfaceMode = RelevantGraphSurfaceMode.DoNotRequire
Require every region to have a RelevantGraphSurface component inside it.
A RelevantGraphSurface component placed in the scene specifies that the navmesh region it is inside should be included in the navmesh.
If this is set to OnlyForCompletelyInsideTile a navmesh region is included in the navmesh if it has a RelevantGraphSurface inside it, or if it is adjacent to a tile border. This can leave some small regions which you didn't want to have included because they are adjacent to tile borders, but it removes the need to place a component in every single tile, which can be tedious (see below).
If this is set to RequireForAll a navmesh region is included only if it has a RelevantGraphSurface inside it. Note that even though the navmesh looks continous between tiles, the tiles are computed individually and therefore you need a RelevantGraphSurface component for each region and for each tile.
In the above image, the mode OnlyForCompletelyInsideTile was used. Tile borders are highlighted in black. Note that since all regions are adjacent to a tile border, this mode didn't remove anything in this case and would give the same result as DoNotRequire. The RelevantGraphSurface component is shown using the green gizmo in the top-right of the blue plane.
In the above image, the mode RequireForAll was used. No tiles were used. Note that the small region at the top of the orange cube is now gone, since it was not the in the same region as the relevant graph surface component. The result would have been identical with OnlyForCompletelyInsideTile since there are no tiles (or a single tile, depending on how you look at it).
The mode RequireForAll was used here. Since there is only a single RelevantGraphSurface component, only the region it was in, in the tile it is placed in, will be enabled. If there would have been several RelevantGraphSurface in other tiles, those regions could have been enabled as well.
Here another tile size was used along with the OnlyForCompletelyInsideTile. Note that the region on top of the orange cube is gone now since the region borders do not intersect that region (and there is no RelevantGraphSurface component inside it).
Note
When not using tiles. OnlyForCompletelyInsideTile is equivalent to RequireForAll.
Rotation of the graph in degrees.
bool
scanEmptyGraph
If true, scanning the graph will yield a completely empty graph.
Useful if you want to replace the graph with a custom navmesh for example
List<string>
tagMask = new List<string>()
Objects tagged with any of these tags will be rasterized.
Note that this extends the layer mask, so if you only want to use tags, set mask to 'Nothing'.
int
terrainSampleSize = 3
Controls how large the sample size for the terrain is.
A higher value is faster to scan but less accurate
int
tileSizeX = 128
Size of a tile along the X axis in voxels.
This is the width of the tile.
![](images/recast/tile.png)
A large tile size can be faster to initially scan (but beware of out of memory issues if you try with a too large tile size in a large world) smaller tile sizes are (much) faster to update.
Different tile sizes can affect the quality of paths. It is often good to split up huge open areas into several tiles for better quality paths, but too small tiles can also lead to effects looking like invisible obstacles. For more information about this take a look at Notes about navmesh graphs. Usually it is best to experiment and see what works best for your game.
When scanning a recast graphs individual tiles can be calculated in parallel which can make it much faster to scan large worlds. When you want to recalculate a part of a recast graph, this can only be done on a tile-by-tile basis which means that if you often try to update a region of the recast graph much smaller than the tile size, then you will be doing a lot of unnecessary calculations. However if you on the other hand update regions of the recast graph that are much larger than the tile size then it may be slower than necessary as there is some overhead in having lots of tiles instead of a few larger ones (not that much though).
Recommended values are between 64 and 256, but these are very soft limits. It is possible to use both larger and smaller values.
int
tileSizeZ = 128
Size of a tile along the Z axis in voxels.
This is the width of the tile.
![](images/recast/tile.png)
A large tile size can be faster to initially scan (but beware of out of memory issues if you try with a too large tile size in a large world) smaller tile sizes are (much) faster to update.
Different tile sizes can affect the quality of paths. It is often good to split up huge open areas into several tiles for better quality paths, but too small tiles can also lead to effects looking like invisible obstacles. For more information about this take a look at Notes about navmesh graphs. Usually it is best to experiment and see what works best for your game.
When scanning a recast graphs individual tiles can be calculated in parallel which can make it much faster to scan large worlds. When you want to recalculate a part of a recast graph, this can only be done on a tile-by-tile basis which means that if you often try to update a region of the recast graph much smaller than the tile size, then you will be doing a lot of unnecessary calculations. However if you on the other hand update regions of the recast graph that are much larger than the tile size then it may be slower than necessary as there is some overhead in having lots of tiles instead of a few larger ones (not that much though).
Recommended values are between 64 and 256, but these are very soft limits. It is possible to use both larger and smaller values.
bool
useTiles = true
If true, divide the graph into tiles, otherwise use a single tile covering the whole graph.
Since
Since 4.1 the default value is true.
float
walkableClimb = 0.5F
Height the character can climb.
float
walkableHeight = 2F
Character height.
Public Static Variables
const int
BorderVertexMask = 1
const int
BorderVertexOffset = 31
Public Enums
RelevantGraphSurfaceMode
DoNotRequire |
No RelevantGraphSurface components are required anywhere.
|
OnlyForCompletelyInsideTile |
Any surfaces that are completely inside tiles need to have a RelevantGraphSurface component positioned on that surface, otherwise it will be stripped away.
|
RequireForAll |
All surfaces need to have one RelevantGraphSurface component positioned somewhere on the surface and in each tile that it touches, otherwise it will be stripped away.
Only tiles that have a RelevantGraphSurface component for that surface will keep it. |
Inherited Public Members
int
CountNodes
()
Number of nodes in the graph.
Note that this is, unless the graph type has overriden it, an O(n) operation.
This is an O(1) operation for grid graphs and point graphs. For layered grid graphs it is an O(n) operation.
void
EndBatchTileUpdate
()
End batch updating of tiles.
During batch updating, tiles will not be connected if they are updated with ReplaceTile. When ending batching, all affected tiles will be connected. This is faster than not using batching.
Vector3 | position | The position to try to find a close node to |
)
Returns the nearest node to a position.
Vector3 | position | The position to try to find a close node to |
NNConstraint | constraint | Can for example tell the function to try to return a walkable node. If you do not get a good node back, consider calling GetNearestForce. |
)
Returns the nearest node to a position using the specified NNConstraint.
Vector3 | position | The position to try to find a close node to |
NNConstraint | constraint | Can for example tell the function to try to return a walkable node. If you do not get a good node back, consider calling GetNearestForce. |
GraphNode | hint | Can be passed to enable some graph generators to find the nearest node faster. |
)
Returns the nearest node to a position using the specified NNConstraint.
)
Returns the nearest node to a position using the specified constraint .
Return
an NNInfo. This method will only return an empty NNInfo if there are no nodes which comply with the specified constraint.
void
GetNodes
(
)
Calls a delegate with all nodes in the graph until the delegate returns false.
void
GetNodes
(
)
Calls a delegate with all nodes in the graph.
This is the primary way of iterating through all nodes in a graph.
Do not change the graph structure inside the delegate.
var gg = AstarPath.active.data.gridGraph;
gg.GetNodes(node => {
// Here is a node
Debug.Log("I found a node at position " + (Vector3)node.position);
});
If you want to store all nodes in a list you can do this
var gg = AstarPath.active.data.gridGraph;
List<GraphNode> nodes = new List<GraphNode>();
gg.GetNodes((System.Action<GraphNode>)nodes.Add);
)
Tile at the specified x, z coordinate pair.
The first tile is at (0,0), the last tile at (tileXCount-1, tileZCount-1).
var graph = AstarPath.active.data.recastGraph;
int tileX = 5;
int tileZ = 8;
NavmeshTile tile = graph.GetTile(tileX, tileZ);
for (int i = 0; i < tile.nodes.Length; i++) {
// ...
}
// or you can access the nodes like this:
tile.GetNodes(node => {
// ...
});
Bounds
GetTileBounds
(
)
Returns a bounds object with the bounding box of a group of tiles.
The bounding box is defined in world space.
Bounds
GetTileBounds
(
int | x | |
int | z | |
int | width=1 | |
int | depth=1 | |
)
Returns a bounds object with the bounding box of a group of tiles.
The bounding box is defined in world space.
Bounds
GetTileBoundsInGraphSpace
(
)
Bounds
GetTileBoundsInGraphSpace
(
int | x | |
int | z | |
int | width=1 | |
int | depth=1 | |
)
Returns an XZ bounds object with the bounds of a group of tiles in graph space.
void
GetTileCoordinates
(
int | tileIndex | |
out int | x | |
out int | z | |
)
Tile coordinates from a tile index.
Int2
GetTileCoordinates
(
)
Returns the tile coordinate which contains the specified position.
It is not necessarily a valid tile (i.e it could be out of bounds).
int
GetTileIndex
(
)
Tile index from a vertex index.
All tiles.
Warning
Do not modify this array
IntRect
GetTouchingTiles
(
)
Returns a rect containing the indices of all tiles touching the specified bounds.
If a margin is passed, the bounding box in graph space is expanded by that amount in every direction.
IntRect
GetTouchingTilesInGraphSpace
(
Rect | rect | Graph space rectangle (in graph space all tiles are on the XZ plane regardless of graph rotation and other transformations, the first tile has a corner at the origin) |
)
Returns a rect containing the indices of all tiles touching the specified bounds.
IntRect
GetTouchingTilesRound
(
)
Returns a rect containing the indices of all tiles by rounding the specified bounds to tile borders.
This is different from GetTouchingTiles in that the tiles inside the rectangle returned from this method may not contain the whole bounds, while that is guaranteed for GetTouchingTiles.
Int3
GetVertex
(
)
Vertex coordinate for the specified vertex index.
int
GetVertexArrayIndex
(
)
Int3
GetVertexInGraphSpace
(
)
Vertex coordinate in graph space for the specified vertex index.
bool
Linecast
(
)
Returns if there is an obstacle between origin and end on the graph.
This is not the same as Physics.Linecast, this function traverses the graph and looks for collisions instead of checking for collider intersection.
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
bool
Linecast
(
Vector3 | origin | Point to linecast from. |
Vector3 | end | Point to linecast to. |
GraphNode | hint | You may pass the node closest to the start point if you already know it for a minor performance boost. If null, a search for the closest node will be done. This parameter is mostly deprecated and should be avoided. Pass null instead. |
outGraphHitInfo | hit | Contains info on what was hit, see GraphHitInfo. |
)
Returns if there is an obstacle between origin and end on the graph.
This is not the same as Physics.Linecast, this function traverses the graph and looks for collisions instead of checking for collider intersection.
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
bool
Linecast
(
Vector3 | origin | Point to linecast from. |
Vector3 | end | Point to linecast to. |
GraphNode | hint | You may pass the node closest to the start point if you already know it for a minor performance boost. If null, a search for the closest node will be done. This parameter is mostly deprecated and should be avoided. Pass null instead. |
)
Returns if there is an obstacle between origin and end on the graph.
This is not the same as Physics.Linecast, this function traverses the graph and looks for collisions instead of checking for collider intersection.
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
bool
Linecast
(
Vector3 | origin | Point to linecast from. |
Vector3 | end | Point to linecast to. |
GraphNode | hint | You may pass the node closest to the start point if you already know it for a minor performance boost. If null, a search for the closest node will be done. This parameter is mostly deprecated and should be avoided. Pass null instead. |
outGraphHitInfo | hit | Contains info on what was hit, see GraphHitInfo. |
List<GraphNode> | trace | If a list is passed, then it will be filled with all nodes the linecast traverses. |
)
Returns if there is an obstacle between origin and end on the graph.
This is not the same as Physics.Linecast, this function traverses the graph and looks for collisions instead of checking for collider intersection.
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
bool
Linecast
(
Vector3 | origin | Point to linecast from. |
Vector3 | end | Point to linecast to. |
outGraphHitInfo | hit | Contains info on what was hit, see GraphHitInfo. |
List<GraphNode> | trace | If a list is passed, then it will be filled with all nodes the linecast traverses. |
System.Func<GraphNode, bool> | filter | If not null then the delegate will be called for each node and if it returns false the node will be treated as unwalkable and a hit will be returned. Note that unwalkable nodes are always treated as unwalkable regardless of what this filter returns. |
)
Returns if there is an obstacle between origin and end on the graph.
This is not the same as Physics.Linecast, this function traverses the graph and looks for collisions instead of checking for collider intersection.
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
bool
Linecast
(
NavmeshBase | graph | The graph to perform the search on. |
Vector3 | origin | Point to start from. |
Vector3 | end | Point to linecast to. |
GraphNode | hint | You may pass the node closest to the start point if you already know it for a minor performance boost. If null, a search for the closest node will be done. This parameter is mostly deprecated and should be avoided. Pass null instead. |
outGraphHitInfo | hit | Contains info on what was hit, see GraphHitInfo. |
)
Returns if there is an obstacle between origin and end on the graph.
This is not the same as Physics.Linecast, this function traverses the graph and looks for collisions instead of checking for collider intersection.
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
bool
Linecast
(
NavmeshBase | graph | The graph to perform the search on |
Vector3 | origin | Point to start from. This point should be on the navmesh. It will be snapped to the closest point on the navmesh otherwise. |
Vector3 | end | Point to linecast to |
GraphNode | hint | If you already know the node which contains the origin point, you may pass it here for slighly improved performance. If null, a search for the closest node will be done. |
outGraphHitInfo | hit | Contains info on what was hit, see GraphHitInfo |
List<GraphNode> | trace | If a list is passed, then it will be filled with all nodes along the line up until it hits an obstacle or reaches the end. |
System.Func<GraphNode, bool> | filter=null | If not null then the delegate will be called for each node and if it returns false the node will be treated as unwalkable and a hit will be returned. Note that unwalkable nodes are always treated as unwalkable regardless of what this filter returns. |
)
Returns if there is an obstacle between origin and end on the graph.
This is not the same as Physics.Linecast, this function traverses the graph and looks for collisions instead of checking for collider intersections.
Note
This method only makes sense for graphs in which there is a definite 'up' direction. For example it does not make sense for e.g spherical graphs, navmeshes in which characters can walk on walls/ceilings or other curved worlds. If you try to use this method on such navmeshes it may output nonsense.
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
void
OnDrawGizmos
(
DrawingData | gizmos | |
bool | drawNodes | |
RedrawScope | redrawScope | |
)
Draw gizmos for the graph.
System.Action<NavmeshTile[]>
OnRecalculatedTiles
Called when tiles have been completely recalculated.
This is called after scanning the graph and after performing graph updates that completely recalculate tiles (not ones that simply modify e.g penalties). It is not called after NavmeshCut updates.
)
Finds the first node which contains position.
"Contains" is defined as position is inside the triangle node when seen from above. So only XZ space matters. In case of a multilayered environment, which node of the possibly several nodes containing the point is undefined.
Returns null if there was no node containing the point. This serves as a quick check for "is this point on the navmesh or not".
Note that the behaviour of this method is distinct from the GetNearest method. The GetNearest method will return the closest node to a point, which is not necessarily the one which contains it in XZ space.
void
RelocateNodes
(
)
Moves the nodes in this graph.
Multiplies all node positions by deltaMatrix.
For example if you want to move all your nodes in e.g a point graph 10 units along the X axis from the initial position var graph = AstarPath.data.pointGraph;
var m = Matrix4x4.TRS (new Vector3(10,0,0), Quaternion.identity, Vector3.one);
graph.RelocateNodes (m);
Note
For grid graphs, navmesh graphs and recast graphs it is recommended to use their custom overloads of the RelocateNodes method which take parameters for e.g center and nodeSize (and additional parameters) instead since they are both easier to use and are less likely to mess up pathfinding.
Warning
This method is lossy for PointGraphs, so calling it many times may cause node positions to lose precision. For example if you set the scale to 0 in one call then all nodes will be scaled/moved to the same point and you will not be able to recover their original positions. The same thing happens for other - less extreme - values as well, but to a lesser degree.
void
RelocateNodes
(
)
Moves the nodes in this graph.
Moves all the nodes in such a way that the specified transform is the new graph space to world space transformation for the graph. You usually use this together with the CalculateTransform method.
So for example if you want to move and rotate all your nodes in e.g a recast graph you can do var graph = AstarPath.data.recastGraph;
graph.rotation = new Vector3(45, 0, 0);
graph.forcedBoundsCenter = new Vector3(20, 10, 10);
var transform = graph.CalculateTransform();
graph.RelocateNodes(transform);
This will move all the nodes to new positions as if the new graph settings had been there from the start.
Note
RelocateNodes(deltaMatrix) is not equivalent to RelocateNodes(new GraphTransform(deltaMatrix)). The overload which takes a matrix multiplies all existing node positions with the matrix while this overload does not take into account the current positions of the nodes.
void
ReplaceTile
(
int | x | |
int | z | |
Int3[] | verts | |
int[] | tris | |
)
Replace tile at index with nodes created from specified navmesh.
This will create new nodes and link them to the adjacent tile (unless batching has been started in which case that will be done when batching ends).
The vertices are assumed to be in 'tile space', that is being in a rectangle with one corner at the origin and one at (TileWorldSizeX, 0, TileWorldSizeZ).
Note
The vertex and triangle arrays may be modified and will be stored with the tile data. do not modify them after this method has been called.
void
Scan
()
Scan the graph.
Consider using AstarPath.Scan() instead since this function only scans this graph and if you are using multiple graphs with connections between them, then it is better to scan all graphs at once.
void
StartBatchTileUpdate
()
Start batch updating of tiles.
During batch updating, tiles will not be connected if they are updating with ReplaceTile. When ending batching, all affected tiles will be connected. This is faster than not using batching.
const int
TileIndexMask = 0x7FFFF
const int
TileIndexOffset = 12
const int
VertexIndexMask = 0xFFF
Reference to the AstarPath object in the scene.
bool
drawGizmos = true
Enable to draw gizmos in the Unity scene view.
In the inspector this value corresponds to the state of the 'eye' icon in the top left corner of every graph inspector.
bool
enableNavmeshCutting = true
Should navmesh cuts affect this graph.
Vector3
forcedBoundsSize = new Vector3(100, 40, 100)
Size of the bounding box.
uint
graphIndex
Index of the graph, used for identification purposes.
Used as an ID of the graph, considered to be unique.
Note
This is Pathfinding.Util.Guid not System.Guid. A replacement for System.Guid was coded for better compatibility with iOS
bool
infoScreenOpen
Used in the editor to check if the info screen is open.
Should be inside UNITY_EDITOR only #ifs but just in case anyone tries to serialize a NavGraph instance using Unity, I have left it like this as it would otherwise cause a crash when building. Version 3.0.8.1 was released because of this bug only
uint
initialPenalty
Default penalty to apply to all nodes.
string
name
Name of the graph.
Can be set in the unity editor
bool
nearestSearchOnlyXZ
Perform nearest node searches in XZ space only.
Recomended for single-layered environments. Faster but can be inaccurate esp. in multilayered contexts. You should not use this if the graph is rotated since then the XZ plane no longer corresponds to the ground plane.
This can be important on sloped surfaces. See the image below in which the closest point for each blue point is queried for: ![](images/distanceXZ2.png)
You can also control this using a field on an NNConstraint object.
bool
open
Is the graph open in the editor.
bool
showMeshOutline = true
Show an outline of the polygons in the Unity Editor.
bool
showMeshSurface = true
Show the surface of the navmesh.
bool
showNodeConnections
Show the connections between the polygons in the Unity Editor.
int
tileXCount
Number of tiles along the X-axis.
int
tileZCount
Number of tiles along the Z-axis.
Private/Protected Members
void
AssertSafeToUpdateGraph
()
Throws an exception if it is not safe to update internal graph data right now.
It is safe to update graphs when graphs are being scanned, or inside a work item. In other cases pathfinding could be running at the same time, which would not appreciate graph data changing under its feet.
Voxelize | vox | |
int | x | |
int | z | |
int | threadIndex=0 | |
)
Bounds
CalculateTileBoundsWithBorder
(
)
int
CharacterRadiusInVoxels
Convert character radius to a number of voxels.
void
ClearTile
(
)
Clear the tile at the specified coordinate.
Must be called during a batch update, see StartBatchTileUpdate.
void
ConnectTileWithNeighbours
(
)
void
ConnectTiles
(
NavmeshTile | tile1 | |
NavmeshTile | tile2 | |
float | tileWorldSizeX | |
float | tileWorldSizeZ | |
float | maxTileConnectionEdgeDistance | |
)
Generate connections between the two tiles.
The tiles must be adjacent.
void
CreateNodeConnections
(
)
Create connections between all nodes.
Version
Since 3.7.6 the implementation is thread safe
void
CreateNodes
(
NavmeshTile | tile | |
int[] | tris | |
int | tileIndex | |
uint | graphIndex | |
uint[] | tags | |
AstarPath | astar | |
uint | initialPenalty | |
bool | recalculateNormals | |
)
)
Create a tile at tile index x, z from the mesh.
Version
Since version 3.7.6 the implementation is thread safe
void
DestroyAllNodes
()
Destroys all nodes in the graph.
Warning
This is an internal method. Unless you have a very good reason, you should probably not call it.
void
DisposeUnmanagedData
()
Cleans up any unmanaged data that the graph has.
Note
The graph has to stay valid after this. However it need not be in a scanned state.
void
DrawUnwalkableNodes
(
DrawingData | gizmos | |
float | size | |
RedrawScope | redrawScope | |
)
void
FillWithEmptyTiles
()
Fills graph with tiles created by NewEmptyTile.
void
InitializeTileInfo
()
float
MaxTileConnectionEdgeDistance
)
Creates a single new empty tile.
void
OnDestroy
()
Function for cleaning up references.
This will be called on the same time as OnDisable on the gameObject which the AstarPath script is attached to (remember, not in the editor). Use for any cleanup code such as cleaning up static variables which otherwise might prevent resources from being collected. Use by creating a function overriding this one in a graph class, but always call base.OnDestroy () in that function. All nodes should be destroyed in this function otherwise a memory leak will arise.
void
PostDeserialization
(
)
Called after all deserialization has been done for all graphs.
Can be used to set up more graph data which is not serialized
)
Creates a list for every tile and adds every mesh that touches a tile to the corresponding list.
void
RemoveConnectionsFromTile
(
)
void
RemoveConnectionsFromTo
(
)
IEnumerable<Progress>
ScanAllTilesBurst
(
)
IEnumerable<Progress>
ScanInternal
(
)
Internal method to scan the graph.
Called from AstarPath.ScanAsync. Override this function to implement custom scanning logic. Progress objects can be yielded to show progress info in the editor and to split up processing over several frames when using async scanning.
int
TileBorderSizeInVoxels
Number of extra voxels on each side of a tile to ensure accurate navmeshes near the tile border.
The width of a tile is expanded by 2 times this value (1x to the left and 1x to the right)
float
TileBorderSizeInWorldUnits
void IUpdatableGraph.
UpdateArea
(
)
Updates an area using the specified GraphUpdateObject.
Notes to implementators. This function should (in order):
Call o.WillUpdateNode on the GUO for every node it will update, it is important that this is called BEFORE any changes are made to the nodes.
Update walkabilty using special settings such as the usePhysics flag used with the GridGraph.
Call Apply on the GUO for every node which should be updated with the GUO.
Update connectivity info if appropriate (GridGraphs updates connectivity, but most other graphs don't since then the connectivity cannot be recovered later).
)
May be called on the Unity thread before starting the update.
May return a GraphUpdatePromise or null. If a GraphUpdatePromise is returned it will be polled on the main thread until it returns done. Only then will it progress to the next stage. The `Complete` method may be called if the graph update needs to be completed immediately.
void IUpdatableGraph.
UpdateAreaPost
(
)
Called on the Unity thread to complete a graph update.
bool
exists
True if the graph exists, false if it has been destroyed.
List of tiles that have been calculated in a graph update, but have not yet been added to the graph.
When updating the graph in a separate thread, large changes cannot be made directly to the graph as other scripts might use the graph data structures at the same time in another thread. So the tiles are calculated, but they are not yet connected to the existing tiles that will be done in UpdateAreaPost which runs in the Unity thread.
Note
Should not contain duplicates.
Deprecated Members
Vector3
ClosestPointOnNode
(
)
Returns the closest point of the node.
bool
ContainsPoint
(
)
Returns if the point is inside the node in XZ space.
void
DeserializeSettingsCompatibility
(
)
An old format for serializing settings.
Deprecated
This is deprecated now, but the deserialization code is kept to avoid loosing data when upgrading from older versions.
Bounds
forcedBounds
World bounds for the graph.
Defined as a bounds object with size forcedBoundsSize and centered at forcedBoundsCenter
Deprecated
Obsolete since this is not accurate when the graph is rotated (rotation was not supported when this property was created)