Create a PointGraph manualy

Hi,
I have checked on the forum any previous post about this subject but none helped me either api has changed or result did not worked. I am trying at runtime to create a point graph manualy, ie without calling pointgraph.Scan using its MaxDistance that creates all link between nodes.

I am creating nodes like that (dots is an array of Vector3) :

AstarPath.active.AddWorkItem(new AstarWorkItem(ctx => {

 for (int i = 0; i < dots.Count - 1; i++)
 {
     Int3 pos1 = (Int3)dots[i];
     Int3 pos2 = (Int3)dots[i + 1];
     poingraph.AddNode(pos1);
     poingraph.AddNode(pos2);
     PointNode pn1 = pg.nodes[poingraph.CountNodes() - 2];
     PointNode pn2 = pg.nodes[poingraph.CountNodes() - 1];
     
     var cost = (uint)(pn1.position - pn2.position).costMagnitude;
     
     GraphNode.Connect(pn1, pn2, cost);

}

But pathfinding can never find a path between any src & target. I am probably missing something because in the debug display of the pointGraph, I can not see the blue dots corresponding to all pointnodes.

Thank you in advance for you help

Best

Hi

That looks like it should work.
Though you probably want to do:

var pn1 = pointgraph.AddNode(pos1);
var pn2 = pointgraph.AddNode(pos2);

instead, to make the code more tidy.

The blue boxes are actually only drawn when the sources are GameObjects.

It should draw all connections between the nodes, though.

You should also make sure to call pointgraph.RebuildConnectionDistanceLookup() after you have added all those connections.

Hi,

I am still not understanding what goes wrong but if I create GO for all dots and call scan, path is working but path is not able to find any target once nodes are created like this :

AstarPath.active.AddWorkItem(new AstarWorkItem(ctx => {

for (int i = 0; i < dots.Count - 1; i++)
{
    Int3 pos1 = (Int3)dots[i];
    Int3 pos2 = (Int3)dots[i + 1];
    pg.AddNode(pos1);
    pg.AddNode(pos2);
    PointNode pn1 = pg.nodes[pg.CountNodes() - 2];
    PointNode pn2 = pg.nodes[pg.CountNodes() - 1];
    pn1.Tag = 3;
    pn2.Tag = 3;
    var cost = (uint)(pn1.position - pn2.position).costMagnitude;
    //pn1.AddConnection(pn2, 0);
    //pn2.AddConnection(pn1, 0);
    GraphNode.Connect(pn1, pn2, cost);

}


pg.RebuildNodeLookup();

}));

I can see the green lines between all nodes so it should be correct. I am not able to debug inside the package, but the searchnode count remains 0 but pointgraph.nodes contains the nodes above!

I tried to enable optimizeforsparse but I am getting this error :

NullReferenceException: Object reference not set to an instance of an object.
Pathfinding.PointGraph.GetNearest (UnityEngine.Vector3 position, Pathfinding.NNConstraint constraint, System.Single maxDistanceSqr) (at ./Library/PackageCache/com.arongranberg.astar@5.1.4/Graphs/PointGraph.cs:204)
AstarPath.GetNearest (UnityEngine.Vector3 position, Pathfinding.NNConstraint constraint) (at ./Library/PackageCache/com.arongranberg.astar@5.1.4/Core/AstarPath.cs:2190)
Pathfinding.OffMeshLinks.ClampSegment (Pathfinding.OffMeshLinks+Anchor anchor, Pathfinding.GraphMask graphMask, System.Single maxSnappingDistance, Pathfinding.OffMeshLinks+Anchor& result, System.Collections.Generic.List`1[T] nodes) (at ./Library/PackageCache/com.arongranberg.astar@5.1.4/Core/Misc/OffMeshLinks.cs:417)
Pathfinding.OffMeshLinks.Refresh () (at ./Library/PackageCache/com.arongranberg.astar@5.1.4/Core/Misc/OffMeshLinks.cs:579)
Pathfinding.WorkItemProcessor.ProcessWorkItems (System.Boolean force, System.Boolean sendEvents) (at ./Library/PackageCache/com.arongranberg.astar@5.1.4/Core/Misc/WorkItemProcessor.cs:360)
Pathfinding.WorkItemProcessor.ProcessWorkItemsForUpdate (System.Boolean force) (at ./Library/PackageCache/com.arongranberg.astar@5.1.4/Core/Misc/WorkItemProcessor.cs:416)
AstarPath.PerformBlockingActions (System.Boolean force) (at ./Library/PackageCache/com.arongranberg.astar@5.1.4/Core/AstarPath.cs:895)
AstarPath.Update () (at ./Library/PackageCache/com.arongranberg.astar@5.1.4/Core/AstarPath.cs:878)

Without sparse option, manually calling GetNearest for the start & end points give valid nodes. I am calling the search like this :

NNInfo inf = pg.GetNearest(destPathPos, NNConstraint.None);
GraphNode nodeDest = inf.node;
destPathPos = (Vector3)nodeDest.position;

inf = pg.GetNearest(sourcePathPos, NNConstraint.None);
GraphNode nodeSrc = inf.node;
sourcePathPos = (Vector3)nodeSrc.position;

roadpath = ABPath.Construct(sourcePathPos, destPathPos, null);
roadpath.enabledTags = (1 << 3);
roadpath.calculatePartial = true;
AstarPath.StartPath(roadpath);
yield return (roadpath.WaitForPath());

but the result is ==> roadpath.error = true

This is a really blocking issue, any tips would help a lot…

Best

I have enabled the heavy log and it gave me informations :

Path Completed : Computation Time 2.004 ms Searched Nodes 864 Path Length 15 Path Cost: 9073
Point: (-1058.36, 1.12, 1089.43)
Graph: 2
Start Node
Point: (-1063.54, 1.09, 1093.58)
Graph: 0

Graph #2 is the point Graph and Graph #0 is a RecastGraph. What we can see here is that the Startnode does not start in the Graph #2. Why because I am getting the closest pos on the pointgraph using the code previously shared :

inf = pg.GetNearest(sourcePathPos, NNConstraint.None);
GraphNode nodeSrc = inf.node;
sourcePathPos = (Vector3)nodeSrc.position;

roadpath = ABPath.Construct(sourcePathPos, destPathPos, null);

Underneath, I have links between PointGraph & ReactGraph (ie NodeLink2) but it seems that they are not found from the StartPoint…

Best

Hi,
Ok, I found the issue which was totally my fault. The loop was not creating nodes continually and caused unreachable target.
Regarding the sparse option, and the distance to connection, I am still not able to enable it. I will keep it disabled, not sure about its benefits.
Note that I did not find any method to reset all the nodes inside the graph, as a workaround, I am calling Scan without any GO which seems to clean up stuff, after what I can add all my nodes/connections.

Best

Hi,

I’m currently having some problems with this as well. I have created this method to create nodes and setup connections between them at runtime and in the editor. It works fine when i disable optimizeForSparseGraph but with optimizeForSparseGraph enabled it only works after I call this method the second time at runtime or in the editor from a custom editor button. The first scan always fails.
I’m guessing it has something to do with the lookupTree not being initialized in the Pointgraph.BuildNodeLookup function but I’m not sure…
Is there any method that I need to call before creating the nodes that would otherwise be done by the Scan() method?

For now I’ll keep optimizeForSparseGraph off but any help in getting it to work with optimizeForSparseGraph enabled would be appreciated!

Cheers

	public void ScanPointGraph()
	{
		if(debug) Debug.Log("ScanPointGraph()", this.gameObject);

		PointGraph pointGraph = AstarPath.active.data.pointGraph;

		pointGraph.RebuildNodeLookup();
		pointGraph.RebuildConnectionDistanceLookup();

		AstarPath.active.AddWorkItem(new AstarWorkItem(ctx => 
		{
			// Create and initialize nodes
			for (int i = 0; i < navNodesChunks.Length; i++)
			{
				for (int j = 0; j < navNodesChunks[i].navNodes.Length; j++)
				{
					if (navNodesChunks[i].navNodes[j] != null)
					{
						// Initialize the graphNode if necessary
						if (navNodesChunks[i].navNodes[j].pointNode == null)
						{
							navNodesChunks[i].navNodes[j].pointNode = pointGraph.AddNode((Int3)navNodesChunks[i].navNodes[j].transform.position);
						}
					}
				}
			}
			pointGraph.RebuildNodeLookup();

			// Set up connections between nodes
			for (int i = 0; i < navNodesChunks.Length; i++)	// For each chunck
			{
				// For each navNode in the chunck
				for (int j = 0; j < navNodesChunks[i].navNodes.Length; j++)
				{
					NavNode currentNode = navNodesChunks[i].navNodes[j];

					if (currentNode != null)
					{
						ConnectToNeighbor(currentNode, currentNode.neighborFront);
						ConnectToNeighbor(currentNode, currentNode.neighborBack);
						ConnectToNeighbor(currentNode, currentNode.neighborLeft);
						ConnectToNeighbor(currentNode, currentNode.neighborRight);
					}
				}
			}
			// pointGraph.RebuildConnectionDistanceLookup();
			pointGraph.RebuildConnectionDistanceLookup();
		}));

		AstarPath.active.FlushWorkItems();

		GraphUpdateScene[] graphUpdateScenes = FindObjectsByType<GraphUpdateScene>(FindObjectsSortMode.None);
		for(int i=0; i<graphUpdateScenes.Length; i++)
			if(graphUpdateScenes[i].applyOnScan) graphUpdateScenes[i].Apply();

		AstarPath.active.FlushGraphUpdates();
	}

	private void ConnectToNeighbor(NavNode node, NavNode neighbor)
	{
		if (node != null && node.pointNode != null && neighbor != null && neighbor.pointNode != null)
		{
			if (!node.pointNode.ContainsOutgoingConnection(neighbor.pointNode))
			{
				var cost = (uint)(node.pointNode.position - neighbor.pointNode.position).costMagnitude;
				GraphNode.Connect(node.pointNode,neighbor.pointNode, cost);
			}
		}
	}

Are you getting the same error the OP above was getting? This may be one you want to make a new thread for actually, so I can tag Aron to check it. From my POV that looks “correct”. But yeah go ahead and start a new thread for this and we can check it out more granularly :+1:

Thanks for your response tealtxgr.

I have posted it in a new topic over here:
Error on creating point graph nodes with optimizeForSparseGraph enabled - General / Point graph - Support Forum

1 Like