RecastGraph recenter

Hi, I have a question regarding recentering of RecastGraph by reusing the ProceduralGraphMover. I read the following in the documentation for the ‘TranslateInDirection’ method:

/// <summary>
/// Moves the recast graph by a number of tiles, discarding old tiles and scanning new ones.
///
/// Note: Only translation in a single direction is supported. dx == 0 || dz == 0 must hold.
/// If you need to move the graph diagonally, then you can call this function twice, once for each axis.
/// </summary>
public IGraphUpdatePromise TranslateInDirection (int dx, int dz) {
	return new RecastMovePromise(this, new Int2(dx, dz));
}

Let’s say I wanted to recenter/move the RecastGraph to the closest tile given a position. Either when an agent is spawned outside the graph bounds, or when the player is teleported to a new area outside the graph bounds.

Is polling a similar method as ‘ProceduralGraphMover.UpdateGraph’ still my best option here, or could I combine the graph shift done in ‘ProceduralGraphMover.UpdateRecastGraph’ somehow’?

void UpdateRecastGraph (RecastGraph graph, Int2 delta, bool async) {
	updatingGraph = true;
	List<(IGraphUpdatePromise, IEnumerator<JobHandle>)> promises = new List<(IGraphUpdatePromise, IEnumerator<JobHandle>)>();
	AstarPath.active.AddWorkItem(new AstarWorkItem(
		ctx => {
		var promise = graph.TranslateInDirection(delta.x, delta.y);
		promises.Add((promise, promise.Prepare()));
	},
		(ctx, force) => {
		if (GraphUpdateProcessor.ProcessGraphUpdatePromises(promises, ctx, force)) {
			updatingGraph = false;
			return true;
		}
		return false;
	}
		));
	if (!async) AstarPath.active.FlushWorkItems();
}

Hi

I take it you want to move it along a non-zero dx and non-zero dz?
In that case, you can add two promises to the list, like in the UpdateRecastGraph method:

var promise1 = graph.TranslateInDirection(2, 0);
promises.Add((promise1, promise1.Prepare()));
var promise2 = graph.TranslateInDirection(0, 5);
promises.Add((promise2, promise2.Prepare()));

Thank you! Apologies for the late reply. Is it possible to move the graph while retaining previously scanned tiles, but excluding the newly added ones from scanning? I assume this is done within the ‘ReplaceTile’ method during the Apply stage?

Well, yes. That’s what the TranslateInDirection method does. It moves the graph, and recalculates only the tiles that need to be recalculated.
Or are you referring to something else?

Well, I have a ‘GraphArea’ script which periodically requests graph translations when moved out of the graph bounds. It also performs GraphUpdates within its own bounds when necessary.

However when I perform graph translations, all of the newly added tiles will be scanned. I’m not sure if this is intended or if I am doing something wrong. In any case I’d like to avoid this and let all GraphUpdates/Scans to be handled by my ‘GraphArea’ script. Sorry if I’m not being clear.

RecastGraph with GraphArea


RecastGraph after running TranslateInDirection

It sounds like you might want to use RecastGraph - A* Pathfinding Project instead

Thank you for your time. The following code seems to work for my use case I’m not sure if the early return is necessary anymore though:

public void RecenterGraph()
{
    if (updatingGraph) return;

    updatingGraph = true;

    AstarPath.active.AddWorkItem(ctx =>
    {
        Int2 shiftDelta = CalculateTileShift(recenterTarget);
        IntRect newTileBounds = new(shiftDelta.x, shiftDelta.y, graph.tileXCount - 1 + shiftDelta.x, graph.tileZCount - 1 + shiftDelta.y);
        graph.Resize(newTileBounds);
        recenterScheduled = false;
        updatingGraph = false;
    });
}
1 Like