How to add tags to graph nodes not at runtime

Hello!

I want to export the graph using a script, and then also use tilemap tile data to tag certain nodes. However, the tags do not seem to work. My non-flying enemies walk right through the water (set to not traverse water in Seeker component) and the debug does not color the water a different color (I have it set to color tags in debug settings).

I have ExportAStarGraphTool.cs which basically just exports the graph data to a specific folder.

public static void ExportAStarGraph() {
	AstarPath.FindAstarPath();
	Selection.SetActiveObjectWithContext(AstarPath.active, AstarPath.active.gameObject);
	string assetPath = GetGraphPath();
	SerializeSettings serializationSettings = SerializeSettings.Settings;
	serializationSettings.nodes = true;
	AstarPath.active.Scan();
	byte[] data = AstarPath.active.data.SerializeGraphs(serializationSettings, out _);
	AstarPath.active.FlushWorkItems();
	string directory = Path.GetDirectoryName(assetPath);
	AstarSerializer.SaveToFile(assetPath, data);
	AssetDatabase.SaveAssets();
	AssetDatabase.Refresh();
}

And GraphUpdateSceneTilemap.cs which I use to tag Water and Pit nodes:

[RequireComponent(typeof(Tilemap))]
public class GraphUpdateSceneTilemap : GraphUpdateScene {

	public override void OnPostScan() {
		applyOnStart = false;
		Tilemap tilemap = GetComponent<Tilemap>();
		foreach (Vector3Int position in tilemap.cellBounds.allPositionsWithin) {
			TileBase tile = tilemap.GetTile(position);
			if (tile != null && (tile as BaseTile).AStarTag != AStarTag.None) {
				Bounds bounds = new Bounds(position, Vector2.one);
				GraphUpdateObject guo = new GraphUpdateObject(bounds) {
					modifyWalkability = false,
					setWalkability = false,
					addPenalty = 0,
					updatePhysics = false,
					updateErosion = false,
					resetPenaltyOnPhysics = false,
					modifyTag = true,
					setTag = (int) (tile as BaseTile).AStarTag
				};
				AstarPath.active.UpdateGraphs(guo);
			}
		}
	}
}

Is the right approach? Is there anything that you notice I am doing incorrectly?

Update: I just tried using AddWorkItem and this does work.

private static void ApplyTilemapTileTags() {
	Dictionary<Vector3, uint> nodesToTag = new Dictionary<Vector3, uint>();
	List<Tilemap> groundTilemaps = TilemapUtility.GetTilemapsByLayer(TileLayer.GroundAndPits);
	foreach (Tilemap groundTilemap in groundTilemaps) {
		foreach (Vector3Int position in groundTilemap.cellBounds.allPositionsWithin) {
			TileBase tile = groundTilemap.GetTile(position);
			if (tile != null && (tile as BaseTile).AStarTag != AStarTag.None) {
				Vector3 nodePosition = position  + new Vector3(1, 1);
				if (!nodesToTag.ContainsKey(nodePosition)) {
					uint tag = (uint) (tile as BaseTile).AStarTag;
					nodesToTag.Add(nodePosition, tag);
				}
			}
		}
	}
	AstarPath.active.AddWorkItem(new AstarWorkItem(() => {
		foreach (var nodeToTag in nodesToTag) {
			GraphNode node = AstarPathUtility.GetNode(nodeToTag.Key);
			node.Tag = nodeToTag.Value;
		}
	}));
    AstarPath.active.FlushWorkItems();
}

So although my problem is solved, I’m still a bit curious as to why the other method did not work o.0.

Hi

Hmm… I’m not sure why the first approach didn’t work either. Did the graph change in the scene view after the update?

It used to work in the past. I just can pinpoint what changed. But no, the graph did not change in the scene view after the graph update.

Ah. I see the issue. You have created a bounding box with a size of Vector2.one. This will create a bounding box which has no width at all along the Z dimension. If you are really lucky the nodes’ z coordinates will be exactly what you have stored, but more likely it will differ a bit.
I would suggest that you use Vector3.one instead.

1 Like

Ah, I see! Thanks so much for pointing that out. As always, I sincerely appreciate the fast and effective support!

1 Like