- A* version: 5.3.1
- Unity version: 2022.3.48f1
I’m running into an issue where only the nodes above y = 0 are getting updated with my custom rule.
I only want nodes where land exists to be walkable and this works fine but doesn’t apply to nodes generated below y = 0.
var nodeWalkable = context.data.nodes.walkable;
var nodePositions = context.data.nodes.positions;
for (int i = 0; i < nodePositions.Length; i++)
{
var position = nodePositions[i];
DebugHelper.DrawBox(position, .25f, .25f, Color.blue, 5f);
nodeWalkable[i] &= TileMapController.Instance.DoesTileExist(position, Enumerations.TileMapLayers.Land);
}
I understand it has something to do with the i = 0, but my interpretation is that if I have a nodePosition[i] and set nodeWalkable[i] = false… the position at nodePosition[i] will not be walkable.
Picture for context
Hi
Would you mind posting your whole code?
Here it is! Its went through a couple iterations trying to diagnose the issue.
using UnityEngine;
using Pathfinding;
using Pathfinding.Graphs.Grid.Rules;
// Mark with the Preserve attribute to ensure that this class is not removed when bytecode stripping is used. See https://docs.unity3d.com/Manual/IL2CPP-BytecodeStripping.html
[Pathfinding.Util.Preserve]
public class CustomPathFinderRule : GridGraphRule
{
public override void Register(GridGraphRules rules)
{
// The Register method will be called once the first time the rule is used
// and it will be called again if any settings for the rule changes in the inspector.
// Use this part to do any precalculations that you need later.
// Hook into the grid graph's calculation code
rules.AddMainThreadPass(Pass.BeforeConnections, context =>
{
if (TileMapController.Instance == null)
return;
// This callback is called when scanning the graph and during graph updates.
// Here you can modify the graph data as you wish.
// The context.data object contains all the node data as NativeArrays
// Not all data is valid for all passes since it may not have been calculated at that time.
// You can find more info about that on the documentation for the GridGraphScanData object.
// Get the data arrays we need
var nodeWalkable = context.data.nodes.walkable;
var nodePositions = context.data.nodes.positions;
for (int i = 0; i < nodePositions.Length; i++)
{
var position = nodePositions[i];
var doesTileExist = TileMapController.Instance.DoesTileExist(position, Enumerations.TileMapLayers.Land);
nodeWalkable[i] = doesTileExist;
}
});
}
}
TileMapController Method
public bool DoesTileExist(Vector3Int tilePosition, Enumerations.TileMapLayers layer)
{
var tileMap = GetTileMap(layer);
var tile = tileMap.GetTile(tilePosition);
return tile != null;
}
Any idea why this would be happening or is there anything else I can provide you?
You are passing a Vector3 world position to the method, but it expects a Vector3Int cell index. That’s the most likely issue I think.
Aw. I have that method overloaded so I don’t have to handle converting it everywhere. 
public bool DoesTileExist(Vector3 tilePosition, Enumerations.TileMapLayers layer)
{
var vector3Int = tilePosition.ToVector3Int();
return DoesTileExist(vector3Int, layer);
}
public bool DoesTileExist(Vector3Int tilePosition, Enumerations.TileMapLayers layer)
{
var tileMap = GetTileMap(layer);
var tile = tileMap.GetTile(tilePosition);
return tile != null;
}
You can’t just convert it to a Vector3Int by rounding it or something (which I would expect ToVector3Int to do). You need to convert from world space to local tilemap space.
I believe that would be true if my grid wasn’t centered at 0,0. But it is and should always be.
My approach is that if I have a building at 1.5, 1.5… then I call that .ToVector3Int() method and it returns me 1,1 which is a location on the grid.
Aw I figured it out. The issue is my ToVector3Int() function just floors all coordinates, including the z coordinate. Adjusting that to always return 0 instead of the potential -1 due to floating point numbers… it works now.
Thanks for the help!
1 Like