Adding custom nodes to point graphs
Introduction
The Point graph is a type of graph that is created from a set of points in space. Each node is a single point, and the nodes can have connections between each other.
In some cases you may want to create a point graph completely using code, by adding all nodes and connections manually.
If you want even more customization, you can write a custom graph type: Writing Graph Generators.
Adding nodes to a point graph
To add nodes to a point graph, you can use the PointGraph.AddNode method. This must be done during a graph update, for safety.
// This holds all graph data
AstarData data = AstarPath.active.data;
// This creates a Point Graph
PointGraph graph = data.AddGraph(typeof(PointGraph)) as PointGraph;
AstarPath.active.Scan(graph);
// Make sure we only modify the graph when all pathfinding threads are paused
AstarPath.active.AddWorkItem(() => {
// Add 2 nodes and connect them
var node1 = graph.AddNode((Int3) new Vector3(1, 2, 3));
var node2 = graph.AddNode((Int3) new Vector3(4, 5, 6));
var cost = (uint)(node2.position - node1.position).costMagnitude;
GraphNode.Connect(node1, node2, cost);
});
// Run the above work item immediately
AstarPath.active.FlushWorkItems();
Scanning a point graph will recalculate it from scratch, and discard any custom nodes you may have added.
If you don't want to calculate the node connections yourself, you can use a graph update object to do it for you. This code will recalculate all connections around the node, and connect it to other nodes using the graph's settings.
AstarPath.active.AddWorkItem(() => {
var node = graph.AddNode((Int3) new Vector3(1, 2, 3));
// Recalculate all connections around the node
AstarPath.active.UpdateGraphs(new Bounds((Vector3)node.position, Vector3.one*0.1f));
});
// Run the above updates immediately
AstarPath.active.FlushWorkItems();
AstarPath.active.FlushGraphUpdates();
Removing nodes from a point graph
You can also remove nodes using the PointGraph.RemoveNode method.
// Make sure we only modify the graph when all pathfinding threads are paused
AstarPath.active.AddWorkItem(() => {
// Find the node closest to some point
var nearest = AstarPath.active.GetNearest(new Vector3(1, 2, 3));
// Check if it is a PointNode
if (nearest.node is PointNode pnode) {
// Remove the node. Assuming it belongs to the first point graph in the scene
AstarPath.active.data.pointGraph.RemoveNode(pnode);
}
});
Associating nodes with GameObjects
If you want to associate your custom nodes with GameObjects, you can use the PointNode.gameObject field:
// Associate a GameObject with a node
Later you can retrieve the GameObject from the node like this:
var node = graph.AddNode((Int3) new Vector3(1, 2, 3));
node.gameObject = gameObject;
var node = AstarPath.active.GetNearest(transform.position).node;
var pointNode = node as PointNode;
if (pointNode != null) {
Debug.Log("That node was created from the GameObject named " + pointNode.gameObject.name);
} else {
Debug.Log("That node is not a PointNode");
}
Associating nodes with custom data
If you want to add more custom data to your point nodes, you can create a subclass of the PointNode class.
class CustomPointNode : PointNode {
// Some custom data to store on the node
public int importantAnswer;
public CustomPointNode(AstarPath active) : base(active) {}
}
void AddCustomPointNode () {
AstarPath.active.AddWorkItem(() => {
var graph = AstarPath.active.data.pointGraph;
graph.AddNode(new CustomPointNode(AstarPath.active) {
importantAnswer = 42
}, (Int3) new Vector3(1, 2, 3));
});
}
Nodes created in this way cannot be serialized (see Saving and Loading Graphs).