A* Pathfinding Project
4.1.1
The A* Pathfinding Project for Unity 3D
|
Automatically generates navmesh graphs based on world geometry. More...
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. The Recast process is described as follows:
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.
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).
Public Types | |
enum | RelevantGraphSurfaceMode { DoNotRequire, OnlyForCompletelyInsideTile, RequireForAll } |
Public Member Functions | |
override GraphTransform | CalculateTransform () |
Returns a new transform which transforms graph space to world space. | |
Vector3 | ClosestPointOnNode (TriangleMeshNode node, Vector3 pos) |
Returns the closest point of the node. | |
bool | ContainsPoint (TriangleMeshNode node, Vector3 pos) |
Returns if the point is inside the node in XZ space. | |
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. | |
Public Member Functions inherited from NavmeshBase | |
void | EndBatchTileUpdate () |
End batch updating of tiles. | |
override NNInfoInternal | GetNearest (Vector3 position, NNConstraint constraint, GraphNode hint) |
Returns the nearest node to a position using the specified NNConstraint. | |
override NNInfoInternal | GetNearestForce (Vector3 position, NNConstraint constraint) |
Returns the nearest node to a position using the specified constraint . | |
override void | GetNodes (System.Action< GraphNode > action) |
Calls a delegate with all nodes in the graph. | |
NavmeshTile | GetTile (int x, int z) |
Tile at the specified x, z coordinate pair. | |
Bounds | GetTileBounds (IntRect rect) |
Returns an XZ bounds object with the bounds of a group of tiles. | |
Bounds | GetTileBounds (int x, int z, int width=1, int depth=1) |
Returns an XZ bounds object with the bounds of a group of tiles. | |
Bounds | GetTileBoundsInGraphSpace (IntRect rect) |
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 (Vector3 position) |
Returns the tile coordinate which contains the specified position. | |
NavmeshTile[] | GetTiles () |
All tiles. | |
IntRect | GetTouchingTiles (Bounds bounds) |
Returns a rect containing the indices of all tiles touching the specified bounds. | |
IntRect | GetTouchingTilesInGraphSpace (Rect rect) |
Returns a rect containing the indices of all tiles touching the specified bounds. | |
IntRect | GetTouchingTilesRound (Bounds bounds) |
Returns a rect containing the indices of all tiles by rounding the specified bounds to tile borders. | |
Int3 | GetVertex (int index) |
Vertex coordinate for the specified vertex index. | |
int | GetVertexArrayIndex (int index) |
Int3 | GetVertexInGraphSpace (int index) |
Vertex coordinate in graph space for the specified vertex index. | |
bool | Linecast (Vector3 origin, Vector3 end) |
Returns if there is an obstacle between origin and end on the graph. | |
bool | Linecast (Vector3 origin, Vector3 end, GraphNode hint, out GraphHitInfo hit) |
Returns if there is an obstacle between origin and end on the graph. | |
bool | Linecast (Vector3 origin, Vector3 end, GraphNode hint) |
Returns if there is an obstacle between origin and end on the graph. | |
bool | Linecast (Vector3 origin, Vector3 end, GraphNode hint, out GraphHitInfo hit, List< GraphNode > trace) |
Returns if there is an obstacle between origin and end on the graph. | |
override void | OnDrawGizmos (Pathfinding.Util.RetainedGizmos gizmos, bool drawNodes) |
GraphNode | PointOnNavmesh (Vector3 position, NNConstraint constraint) |
Finds the first node which contains position. | |
override void | RelocateNodes (Matrix4x4 deltaMatrix) |
Moves the nodes in this graph. | |
void | RelocateNodes (GraphTransform newTransform) |
Moves the nodes in this graph. | |
void | ReplaceTile (int x, int z, Int3[] verts, int[] tris) |
Replace tile at index with nodes created from specified navmesh. | |
void | ReplaceTile (int x, int z, int w, int d, Int3[] verts, int[] tris) |
Replaces a tile with a new mesh. | |
void | StartBatchTileUpdate () |
Start batch updating of tiles. | |
Public Member Functions inherited from NavGraph | |
virtual int | CountNodes () |
Number of nodes in the graph. | |
NNInfoInternal | GetNearest (Vector3 position) |
Returns the nearest node to a position using the default NNConstraint. | |
NNInfoInternal | GetNearest (Vector3 position, NNConstraint constraint) |
Returns the nearest node to a position using the specified NNConstraint. | |
void | GetNodes (System.Func< GraphNode, bool > action) |
Calls a delegate with all nodes in the graph until the delegate returns false. | |
virtual void | OnDrawGizmos (RetainedGizmos gizmos, bool drawNodes) |
Draw gizmos for the graph. | |
void | RelocateNodes (Matrix4x4 oldMatrix, Matrix4x4 newMatrix) |
Moves nodes in this graph. | |
void | Scan () |
Scan the graph. | |
void | ScanGraph () |
Scan the graph. | |
void | SetMatrix (Matrix4x4 m) |
Use to set both matrix and inverseMatrix at the same time. | |
Public Member Functions inherited from IGraphInternals | |
void | DeserializeExtraInfo (GraphSerializationContext ctx) |
void | DeserializeSettingsCompatibility (GraphSerializationContext ctx) |
void | DestroyAllNodes () |
void | OnDestroy () |
void | PostDeserialization (GraphSerializationContext ctx) |
IEnumerable< Progress > | ScanInternal () |
void | SerializeExtraInfo (GraphSerializationContext ctx) |
Public Member Functions inherited from INavmesh | |
void | GetNodes (System.Action< GraphNode > del) |
Public Member Functions inherited from INavmeshHolder | |
void | GetTileCoordinates (int tileIndex, out int x, out int z) |
Transforms coordinates from graph space to world space. | |
Int3 | GetVertex (int i) |
Position of vertex number i in the world. | |
int | GetVertexArrayIndex (int index) |
Int3 | GetVertexInGraphSpace (int i) |
Position of vertex number i in coordinates local to the graph. | |
Public Member Functions inherited from IUpdatableGraph | |
GraphUpdateThreading | CanUpdateAsync (GraphUpdateObject o) |
void | UpdateArea (GraphUpdateObject o) |
Updates an area using the specified GraphUpdateObject. | |
void | UpdateAreaInit (GraphUpdateObject o) |
May be called on the Unity thread before starting the update. | |
void | UpdateAreaPost (GraphUpdateObject o) |
May be called on the Unity thread after executing the update. | |
Public Attributes | |
const int | BorderVertexMask = 1 |
const int | BorderVertexOffset = 31 |
float | cellSize = 0.5F |
Voxel sample size (x,z). | |
float | characterRadius = 1.5F |
Radius of the agent which will traverse the navmesh. | |
float | colliderRasterizeDetail = 10 |
Controls detail on rasterization of sphere and capsule colliders. | |
float | contourMaxError = 2F |
Max distance from simplified edge to real edge. | |
int | editorTileSize = 128 |
Size in voxels of a single tile. | |
Vector3 | forcedBoundsCenter |
Center of the bounding box. | |
LayerMask | mask = -1 |
Layer mask which filters which objects to include. | |
float | maxEdgeLength = 20 |
Longer edges will be subdivided. | |
float | maxSlope = 30 |
Max slope in degrees the character can traverse. | |
float | minRegionSize = 3 |
Minumum region size. | |
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. | |
RelevantGraphSurfaceMode | relevantGraphSurfaceMode = RelevantGraphSurfaceMode.DoNotRequire |
Require every region to have a RelevantGraphSurface component inside it. | |
Vector3 | rotation |
Rotation of the graph in degrees. | |
bool | scanEmptyGraph |
If true, scanning the graph will yield a completely empty graph. | |
List< string > | tagMask = new List<string>() |
Objects tagged with any of these tags will be rasterized. | |
int | terrainSampleSize = 3 |
Controls how large the sample size for the terrain is. | |
int | tileSizeX = 128 |
Size of a tile along the X axis in voxels. | |
int | tileSizeZ = 128 |
Size of a tile along the Z axis in voxels. | |
bool | useTiles |
If true, divide the graph into tiles, otherwise use a single tile covering the whole graph. | |
float | walkableClimb = 0.5F |
Height the character can climb. | |
float | walkableHeight = 2F |
Character height. | |
Public Attributes inherited from NavmeshBase | |
Vector3 | forcedBoundsSize = new Vector3(100, 40, 100) |
Size of the bounding box. | |
bool | nearestSearchOnlyXZ |
Perform nearest node searches in XZ space only. | |
System.Action< NavmeshTile[]> | OnRecalculatedTiles |
Called when tiles have been completely recalculated. | |
bool | showMeshOutline = true |
Show an outline of the polygons in the Unity Editor. | |
bool | showMeshSurface |
Show the surface of the navmesh. | |
bool | showNodeConnections |
Show the connections between the polygons in the Unity Editor. | |
const int | TileIndexMask = 0x7FFFF |
const int | TileIndexOffset = 12 |
int | tileXCount |
Number of tiles along the X-axis. | |
int | tileZCount |
Number of tiles along the Z-axis. | |
GraphTransform | transform = new GraphTransform(Matrix4x4.identity) |
Determines how the graph transforms graph space to world space. | |
const int | VertexIndexMask = 0xFFF |
Public Attributes inherited from NavGraph | |
AstarPath | active |
Reference to the AstarPath object in the scene. | |
bool | drawGizmos = true |
Enable to draw gizmos in the Unity scene view. | |
uint | graphIndex |
Index of the graph, used for identification purposes. | |
Guid | guid |
Used as an ID of the graph, considered to be unique. | |
bool | infoScreenOpen |
Used in the editor to check if the info screen is open. | |
uint | initialPenalty |
Default penalty to apply to all nodes. | |
Matrix4x4 | inverseMatrix = Matrix4x4.identity |
Inverse of matrix. | |
Matrix4x4 | matrix = Matrix4x4.identity |
A matrix for translating/rotating/scaling the graph. | |
string | name |
Name of the graph. | |
bool | open |
Is the graph open in the editor. | |
Protected Member Functions | |
NavmeshTile | BuildTileMesh (Voxelize vox, int x, int z, int threadIndex=0) |
override void | DeserializeSettingsCompatibility (GraphSerializationContext ctx) |
An old format for serializing settings. | |
IEnumerable< Progress > | ScanAllTiles () |
override IEnumerable< Progress > | ScanInternal () |
Internal method to scan the graph. | |
Protected Member Functions inherited from NavmeshBase | |
void | ClearTiles (int x, int z, int w, int d) |
Clear all tiles within the rectangle with one corner at (x,z), width w and depth d. | |
void | ConnectTiles (NavmeshTile tile1, NavmeshTile tile2) |
Generate connections between the two tiles. | |
void | ConnectTileWithNeighbours (NavmeshTile tile, bool onlyUnflagged=false) |
TriangleMeshNode[] | CreateNodes (int[] tris, int tileIndex, uint graphIndex) |
override void | DeserializeExtraInfo (GraphSerializationContext ctx) |
Deserializes graph type specific node data. | |
void | FillWithEmptyTiles () |
Fills graph with tiles created by NewEmptyTile. | |
NavmeshTile | NewEmptyTile (int x, int z) |
Creates a single new empty tile. | |
override void | OnDestroy () |
Function for cleaning up references. | |
override void | PostDeserialization (GraphSerializationContext ctx) |
Called after all deserialization has been done for all graphs. | |
void | RemoveConnectionsFromTile (NavmeshTile tile) |
void | RemoveConnectionsFromTo (NavmeshTile a, NavmeshTile b) |
override void | SerializeExtraInfo (GraphSerializationContext ctx) |
Serializes Node Info. | |
Protected Member Functions inherited from NavGraph | |
virtual void | DestroyAllNodes () |
Destroys all nodes in the graph. | |
void | DrawUnwalkableNodes (float size) |
Properties | |
float | CellHeight [get] |
int | CharacterRadiusInVoxels [get] |
Convert character radius to a number of voxels. | |
Bounds | forcedBounds [get] |
World bounds for the graph. | |
override float | MaxTileConnectionEdgeDistance [get] |
int | TileBorderSizeInVoxels [get] |
Number of extra voxels on each side of a tile to ensure accurate navmeshes near the tile border. | |
float | TileBorderSizeInWorldUnits [get] |
override float | TileWorldSizeX [get] |
override float | TileWorldSizeZ [get] |
Properties inherited from NavmeshBase | |
abstract float | MaxTileConnectionEdgeDistance [get] |
Maximum (vertical) distance between the sides of two nodes for them to be connected across a tile edge. | |
abstract float | TileWorldSizeX [get] |
Size of a tile in world units along the X axis. | |
abstract float | TileWorldSizeZ [get] |
Size of a tile in world units along the Z axis. | |
GraphTransform ITransformedGraph. | transform [get] |
Properties inherited from NavGraph | |
bool | exists [get] |
True if the graph exists, false if it has been destroyed. | |
Properties inherited from ITransformedGraph | |
GraphTransform | transform [get] |
Private Member Functions | |
Bounds | CalculateTileBoundsWithBorder (int x, int z) |
GraphUpdateThreading IUpdatableGraph. | CanUpdateAsync (GraphUpdateObject o) |
List< RasterizationMesh > | CollectMeshes (Bounds bounds) |
NavmeshTile | CreateTile (Voxelize vox, VoxelMesh mesh, int x, int z, int threadIndex) |
Create a tile at tile index x, z from the mesh. | |
void | InitializeTileInfo () |
List< RasterizationMesh >[] | PutMeshesIntoTileBuckets (List< RasterizationMesh > meshes) |
Creates a list for every tile and adds every mesh that touches a tile to the corresponding list. | |
void IUpdatableGraph. | UpdateArea (GraphUpdateObject guo) |
void IUpdatableGraph. | UpdateAreaInit (GraphUpdateObject o) |
void IUpdatableGraph. | UpdateAreaPost (GraphUpdateObject guo) |
Called on the Unity thread to complete a graph update. | |
Private Attributes | |
Voxelize | globalVox |
List< NavmeshTile > | stagingTiles = new List<NavmeshTile>() |
List of tiles that have been calculated in a graph update, but have not yet been added to the graph. | |
Additional Inherited Members | |
Static Public Member Functions inherited from NavmeshBase | |
static int | GetTileIndex (int index) |
Tile index from a vertex index. | |
static bool | Linecast (NavmeshBase graph, Vector3 origin, Vector3 end, GraphNode hint, out GraphHitInfo hit) |
Returns if there is an obstacle between origin and end on the graph. | |
static bool | Linecast (NavmeshBase graph, Vector3 origin, Vector3 end, GraphNode hint, out GraphHitInfo hit, List< GraphNode > trace) |
Returns if there is an obstacle between origin and end on the graph. | |
Static Protected Member Functions inherited from NavmeshBase | |
static void | CreateNodeConnections (TriangleMeshNode[] nodes) |
Create connections between all nodes. | |
Protected Attributes inherited from NavmeshBase | |
NavmeshTile[] | tiles |
All tiles. | |
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. |
|
protected |
|
private |
|
virtual |
Returns a new transform which transforms graph space to world space.
Does not update the transform field.
Implements NavmeshBase.
|
private |
Vector3 ClosestPointOnNode | ( | TriangleMeshNode | node, |
Vector3 | pos | ||
) |
Returns the closest point of the node.
|
private |
bool ContainsPoint | ( | TriangleMeshNode | node, |
Vector3 | pos | ||
) |
Returns if the point is inside the node in XZ space.
|
private |
Create a tile at tile index x, z from the mesh.
|
protectedvirtual |
An old format for serializing settings.
Reimplemented from NavGraph.
|
private |
|
private |
Creates a list for every tile and adds every mesh that touches a tile to the corresponding list.
|
protected |
|
protectedvirtual |
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.
Implements NavGraph.
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.
|
private |
|
private |
|
private |
Called on the Unity thread to complete a graph update.
const int BorderVertexMask = 1 |
const int BorderVertexOffset = 31 |
float cellSize = 0.5F |
Voxel sample size (x,z).
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.
int editorTileSize = 128 |
Size in voxels of a single tile.
This is the width of the tile.
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 lead to effects looking like invisible obstacles.
Vector3 forcedBoundsCenter |
Center of the bounding box.
Scanning will only be done inside the bounding box
|
private |
LayerMask mask = -1 |
Layer mask which filters which objects to include.
float maxEdgeLength = 20 |
Longer edges will be subdivided.
Reducing this value can improve path quality since similarly sized polygons yield better paths than really large and really small next to each other
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).
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.
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).Vector3 rotation |
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
|
private |
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.
List<string> tagMask = new List<string>() |
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.
int tileSizeZ = 128 |
Size of a tile along the Z axis in voxels.
bool useTiles |
If true, divide the graph into tiles, otherwise use a single tile covering the whole graph.
float walkableClimb = 0.5F |
Height the character can climb.
float walkableHeight = 2F |
Character height.
|
getprivate |
|
getprivate |
Convert character radius to a number of voxels.
|
get |
World bounds for the graph.
Defined as a bounds object with size forcedBoundsSize and centered at forcedBoundsCenter
|
getprotected |
|
getprivate |
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)
|
getprivate |
|
get |
|
get |