Using UpdateGraphs Properly

Hey Aron,

I’m trying to use UpdateGraphs to cut out any 2d physics props when they move in a scene. I am using a GraphUpdateObject and using UpdateGraphs every time the physics objects move, which can be quite a lot, if AI are pushing them around.

		if (currentPosition != tr.position)
		{
			// If prop has moved, update navigation path around that area
			AstarPath.active.UpdateGraphs(graphBoundsUpdateObject);
		}

Firstly: is this the correct way to do it, because it seems quite performance heavy? (Your documentation doesn’t really specific the correct place to call UpdateGraphs)

Secondly, with a lot of updates to the graph, I’m seeing the AI losing all ability to path find until the graph updates have been completed, which basically means if an AI is pushing an object in a scene, it completely stops all other AI from navigating. Have I set up the ai pathfinder requests in the wrong way or something?

Hi

Generally that is the correct way of doing it. Though I’m not quite sure where and how you define the graphBoundsUpdateObject variable. Also you do not seem to set the ‘currentPosition’ variable.
You could also use the DynamicGridObstacle script which does this and is also a bit more optimized. For example it doesn’t update the graph every single frame when the object moves (that is indeed quite slow), but instead only when it has moved a certain distance. I think it should work with 2D physics as well. There is an example of the DynamicGridObstacle component in the Example2 example scene.

You can also batch graph updates as when a single graph update is done, there is a relatively expensive step of recalculating the connected components of the graph. Under the A* Inspector -> Settings tab you can find a setting for ‘Batch Graph Updates’ which applies all queued graph updates every N seconds (where N is something like 0.1 or 0.2) instead of as soon as possible. See also https://arongranberg.com/astar/docs/class_astar_path.php#a88da553087354f51cbd2413f1cbe052b

I set the bounds like this:

	Bounds bounds = spriteCollider.bounds;
	bounds.Expand(Vector3.forward * 1000);
	graphBoundsUpdateObject = new GraphUpdateObject(bounds);
	graphBoundsUpdateObject.updatePhysics = true;
	AstarPath.active.UpdateGraphs(graphBoundsUpdateObject);

And I update the position like this:

protected override void FixedUpdate()
{
	// Update AI navigation if prop has moved
	UpdateGraphs();
}

I’ve checked out that example script. Gonna try it for 2d objects. :slight_smile:

Ok.
Do you make sure to update those bounds as the object moves around? (this is not relevant for performance though).

Does the debug graph showing the grid shape actually update the shape when using AstarPath.active.UpdateGraphs(graphBoundsUpdateObject)?

Because I am not seeing updates on the debug grid using your code.

After the update the visualized graph will change to stay up to date. However you will not see any debug visualizations for exactly which parts of the graph is being updated.

So I won’t see any holes being cut, is that what you mean?

I checked the DynamicGridObstacle component and it turns out that it does not currently work with 2D colliders.
That was relatively easy to fix however. So here is an updated version: https://pastebin.com/zN7qHsC2

You would see holes being cut.
See

HHhmm, I am not seeing that at all.

Do you have colliders on those objects? And are you sure the layers of those objects are included in the Grid Graph -> Collision Testing -> mask?

Ah, yeah, I took that out as I didn’t want to initial scan to remove them, for testing. I didn’t realise that the upgrade graph position would also use it.

Also, using your example script and added the batch flag seems to have alleviated the pathfinding issues.

Thanks Aron.

1 Like

Hey Aron,

Using a modified version of your script, I am getting these errors occasionally: “Coroutine couldn’t be started because the the game object ‘A-Star’ is inactive!”

Its caused by the “OnDestroy” command you included to remove the prop from being cut out from the nav mesh and it caused when the scene is closing. Is there a way I can avoid this? I’m testing if the path is enabled before I start the routine, but it still fires occasionally.

void OnDestroy () 
{
	if (find && find.enabled && find.activePath.enabled && AstarPath.active == null)
	{
		// var guo = new GraphUpdateObject(prevBounds);
		// AstarPath.active.UpdateGraphs(guo);
		find.activePath.UpdateGraphs(prevBounds);
	}
}

Hi

Why did you have to change these lines of code? I’m not sure why you are checking for “AstarPath.active == null”.

its based on your null checking when running any path finding. i was hoping that check would avoid running the coroutine when its not available.

void Update () 
{
	if (AstarPath.active == null || AstarPath.active.isScanning || Time.realtimeSinceStartup - lastCheckTime < checkTime || !Application.isPlaying) 
	{
		return;
	}
}

Well. That code has a “return” inside of it, so you would need to invert the check.

Yeah, I know. That code is in the update, the code before is in the destroy. I tried that check and was still getting the error.

Ok, I took your unmodified code and changed it to a 2d collider again and it seems to have eliminated the error. Obviously my fault, but I’m still not sure what I was doing wrong with the on destroy command.

I’m not sure either. But then I’m also not sure why you are using that ‘find’ variable instead of the AstarPath.active variable.