Upgrade Guide
This page helps you upgrade from an older version of the A* Pathfinding Project to a newer one.
Contents
- Upgrading to 5.0 from 4.x
- Installing the update
- Use ai.SetPath instead of Seeker.StartPath
- Seeker.pathCallback is deprecated
- Scans happen during OnEnable instead of during Awake
- Pathfinding tags are now represented by a struct
- Removed support for RVOSquareObstacle
- Deprecated RVONavmesh
- Changed interface for custom graphs
- Graph updates do more work asynchronously
- Use GraphUpdateObject.ApplyJob instead of Apply for grid graphs
- Batch grid node updates for better performance
- Costs in hexagonal graphs were incorrectly scaled
- NavGraph.GetNearest now always takes constraints into account
- Movement scripts no longer use Update and FixedUpdate
- ProceduralGridMover is now ProceduralGraphMover
- Namespace Structure
- General upgrade nodes
Upgrading to 5.0 from 4.x
There have been many changes in the 5.0 release. For most people, the upgrade should be smooth, and require no changes to your code, but there are a few breaking changes which may require you to update your code, or tweak some settings.
Installing the update
When you upgrade, make sure to delete your old AstarPathfindingProject folder before importing the new version. Not doing this can sometimes cause problems, due to old files being left over.
Use ai.SetPath instead of Seeker.StartPath
The built-in movement scripts no longer listen for all paths that their attached Seeker component calculates, instead they only listen for paths that they request. If you have been relying on this by calling seeker.StartPath from another script, and expecting the movement scripts to start to follow the path, you will need to change this to call ai.SetPath instead. This has been the recommended way to do it for a long time, but now it is required. There is some compatibility code which will keep your code working for now, but it will log a warning every time it happens.
Note
This does not affect you if you have written your own custom movement script. In that case you should continue using the Seeker.
Previously, your code may have looked like: var ai = GetComponent<IAstarAI>();
you should replace that by something like:
var seeker = GetComponent<Seeker>();
seeker.StartPath(ai.position, ai.destination);var ai = GetComponent<IAstarAI>();
var path = ABPath.Construct(ai.position, ai.destination);
ai.SetPath(path);
See
Searching for paths for more info
Seeker.pathCallback is deprecated
The Seeker.pathCallback field is now deprecated. You should instead send a callback to the StartPath method every time.
Note
This only affects you if you are writing your own movement script. If you are using one of the built-in movement scripts, then you should use ai.SetPath as described in the previous section.
Previously, your code may have looked like: Seeker seeker;
void OnEnable () {
seeker = GetComponent<Seeker>();
seeker.pathCallback += OnPathComplete;
}
void OnDisable () {
seeker.pathCallback -= OnPathComplete;
}
void DoSomething() {
seeker.StartPath(transform.position, target.position);
}
void OnPathComplete (Path path) {
// Do something with the path
}
You should replace that by something like: Seeker seeker;
OnPathDelegate onPathComplete;
void OnEnable () {
seeker = GetComponent<Seeker>();
onPathComplete = OnPathComplete;
}
void DoSomething() {
seeker.StartPath(transform.position, target.position, onPathComplete);
}
void OnPathComplete (Path path) {
// Do something with the path
}
See
Searching for paths for more info
Scans happen during OnEnable instead of during Awake
Scanning when the game starts now happens during early OnEnable instead of during early Awake. This should typically not cause any issues, since it's good practice in Unity to not depend on other components being initialized in Awake. But this may cause issues if you have been depending on this very specific initialization order.
Pathfinding tags are now represented by a struct
The type of some tag fields have changed from int to PathfindingTag. If you have assigned a tag to those fields before, you will now first need to convert it to a PathfindingTag:
GetComponent<GraphUpdateScene>().setTag = new PathfindingTag((uint)tag);
You can also use the PathfindingTag.FromName method to get a tag from a string.
If you want to show a tag enum in the inspector, you can expose a public field of type PathfindingTag. It will automatically be shown as a dropdown with the tag names.
Removed support for RVOSquareObstacle
The RVOSquareObstacle has been removed. It never worked particularly well and the performance was poor.
However, the local avoidance system now takes the pathfinding graph into account a lot better (if this is enabled on the RVOSimulator component), so you can use graph updates to update the pathfinding graph instead.
Deprecated RVONavmesh
The RVONavmesh component has been deprecated. This is now handled automatically by enabling the RVOSimulator.useNavmeshAsObstacle option.
Changed interface for custom graphs
If you have written your own custom graph class, several methods have changed their signature.
You can read more about what your code needs to do in Writing Graph Generators.
Graph updates do more work asynchronously
Graph updates for grid graphs and recast graphs do more work asynchronously now. This is usually a pure win as it improves your framerate. However, graph updates may take more frames to complete now, since the game can run while the graph updates are being calculated.
If you want to ensure that the graph updates are done immediately, you can call AstarPath.FlushGraphUpdates.
Use GraphUpdateObject.ApplyJob instead of Apply for grid graphs
Graph updates for grid graphs no longer call the GraphUpdateObject.Apply method, instead the GraphUpdateObject.ApplyJob method is called. If you have been inheriting from the GraphUpdateObject to make custom graph updates you may need to convert your code so that it works with Burst.
See
You may also be interested in Writing Custom Grid Graph Rules
Batch grid node updates for better performance
Due to the new burst and job system, individual node updates are a bit slower than they used to be, but batch updates can be significantly faster.
If you have been updating node walkability manually like this:
var grid = AstarPath.active.data.gridGraph;
grid.GetNodes(node => {
if (someCondition) {
node.Walkable = false;
}
});
grid.GetNodes(node => grid.CalculateConnections(node);
You should now do:
Or you can use the new convenience method GridGraph.SetWalkability:
AstarPath.active.AddWorkItem(() => {
Similarly, if you have been using GridGraph.UpdateCellAndNeighbours to update many nodes, I strongly recommend that you use GridGraph.RecalculateAllConnections or GridGraph.RecalculateConnectionsInRegion instead. If you have been just updating one or two nodes, then it's fine to continue using GridGraph.UpdateCellAndNeighbours.
var grid = AstarPath.active.data.gridGraph;
// Mark all nodes in a 10x10 square, in the top-left corner of the graph, as unwalkable.
grid.SetWalkability(new bool[10*10], new IntRect(0, 0, 9, 9));
});
If you are doing more complex updates of the graph, you may instead want to write a custom grid graph rule. Grid graph rules are a new feature in 5.0 which allows you to write code that integrates much more tightly with the scanning process. This also means that they work automatically with graph updates and the ProceduralGraphMover component.
Costs in hexagonal graphs were incorrectly scaled
Costs between nodes in hexagonal graphs were sqrt(3/2)≈1.22 times too large. The connection costs are now approximately 1000*the distance between the nodes, as they should be.
For example if you have set the hexagon width to 1 then the cost to move between two adjacent hexagons is now 1000 instead of 1224 like it was before. For almost all users this will not affect anything, however it may improve pathfinding performance a bit.
If you have been using penalties on your graph then you may have to divide them by 1.22 to get the same behavior. Similarly if you have been using the ConstantPath to get a set of nodes you may have to divide the maxGScore parameter by 1.22.
NavGraph.GetNearest now always takes constraints into account
NavGraph.GetNearest will now always take the constraint into account. Previously this depended on the graph type and it was generally hard to use to get consistent results across graph types.
The NavGraph.GetNearestForce method has been removed and replaced by the NavGraph.GetNearest method, as they now do the same thing.
Note
Not to be confused with AstarPath.GetNearest, which has always taken constraints into account.
Movement scripts no longer use Update and FixedUpdate
The AIPath and RichAI scripts no longer use the Update and FixedUpdate methods. Instead a separate script ( BatchedEvents) is used which allows all components of a specific type to be processed at once. This is slightly faster and is also required for the AIBase.rvoDensityBehavior implementation. If you have been overriding the Update or FixedUpdate methods you will need to change your code to instead override the OnUpdate method.
ProceduralGridMover is now ProceduralGraphMover
The ProceduralGridMover component has been renamed to ProceduralGraphMover, since it now supports more than just grids.
If you have been referencing it in a script, you'll need to change the name you use to reference it.
Namespace Structure
Namespace structure has been significantly improved. I have tried to keep most changes to internal classes that are not used often by users, but you may have to adjust your using statements slightly. Here's a summary of the changes:
Pathfinding.Graphs.Grid has been added, and a lot of classes related to the grid graph have been moved there.
Pathfinding.Graphs.Grid.Jobs is new and contains a lot of internal grid scanning code.
Pathfinding.Graphs.Grid.Rules is new, and contains grid graph rules.
Pathfinding.Graphs.Navmesh replaces Pathfinding.Recast.
Pathfinding.Graphs.Navmesh.Voxelization replaces Pathfinding.Voxels.
Sadly C# doesn't support public namespace aliases, so these changes cannot be made backwards compatible.
General upgrade nodes
If you are having problems upgrading, try to delete the AstarPathfindingProject folder in Unity and import the package again. This can help removing old scripts which are not included in the project anymore but since UnityPackages merges directories, they are still there.
If you have problems with some compiler messages saying that some members or functions do not exist in a class. It is likely that your project contains a class with that name in the global namespace. This causes a conflict between the classes. To solve it, the simplest solution is to put the conflicting class in a namespace or just rename it.