I have a 2D procedural tilemap and am looking into ways to prevent water areas from being walkable. Looking at other posts I see mention of the GraphUpdateScene component and tagging areas, but it sounds like that won’t work with a procedural world because I can’t define the areas ahead of time.
Is tagging a possible solution in my scenario? If so, how do I tag my water tiles? If not, what should I use? They don’t use colliders, so I’m not clear how else the graph would know of their existence, unless I add custom logic which I’m sure is unnecessary.
In case it matters, I’ve used the “grid mover” script provided in the procedural example. I need to debug it to ensure it’s finding my objects with colliders properly movement and path detection is working fine.
Also… I can’t seem to get the debug view to work in play mode. I can see the grid correctly in scene view but when I hit play it’s not there. I’ve toggled the debug settings and have even added the Pathfinding Debug script, no luck.
I’ve toyed around with a custom graph update object, and while it seems simple enough, I imagine it would be more efficient to move this logic into the graph mover script - so I’m looking over that logic to see if I can figure out the best place to do so.
public void Apply(GraphNode node) {
var tile = world.GetTile((Vector2) node.position);
// Set liquid tiles as unwalkable
if (tile != null && tile is ILiquidTile) {
// node.Tag = 1;
node.Walkable = false;
}
}
Hi
I think the best method would be to subclass the GridGraph and override the RecalculateCell method.
The benefit of doing this is that everything will work out of the box with graph updates and the ProceduralGridMover script.
public class MyGridGraph : GridGraph {
public override void RecalculateCell (int x, int z, bool resetPenalties = true, bool resetTags = true) {
var node = nodes[z*width + x];
// Set the node's initial position with a y-offset of zero
node.position = GraphPointToWorld(x, z, 0);
node.Walkable = DoSomeWorkHere();
node.Tag = 0;
// Store walkability before erosion is applied
// Used for graph updates
node.WalkableErosion = node.Walkable;
}
}
You would also have to add
[CustomGraphEditor(typeof(MyGridGraph), "My Custom Grid Graph")]
To the GridGraphEditor.cs script, otherwise it will not show up in the graph list.
Make sure the ‘Gizmos’ button is enabled. It is in the upper-right corner of the game view.
Thanks, that’s exactly the kind of solution I was hoping for.
However, you don’t mention how to ensure that the original logic runs as well? For now I’ve just thrown in a call to the original recalc method - but it seems to override the node.Walkable
bool so I only call it if the node is potentially walkable.
if (walkable) {
base.RecalculateCell(x, z, resetPenalties, resetTags);
}
Is that the intended solution?
It works just fine in the editor, but in play mode I get this error:
Exception: The AstarPath object has no GridGraph or LayeredGridGraph
AstarGridMover.Start () (at Assets/Scripts/World/Pathfinding/AstarGridMover.cs:75)
Looks like this is due to the specificity of the type equality check in AstarData, FindGraphOfType:
System.Type.Equals(graphs[i].GetType(), type) // returns false when the grid is custom
Replacing it with type.IsAssignableFrom(graphs[i].GetType())
solves that issue.
Edited: I was able to get the gizmos to work. I didn’t realize they were different between scene/play modes. Thanks!
I would call it at the start of the method and then change the Walkable flag depending on if it is a liquid tile or not, not in the reverse order.
Yup. The ProceduralGridMover didn’t have support for custom grid graph types. I have fixed this in my dev version now. It will be included in the next update. It was essentially the same fix as you made.
Nice