(Bug?) Edge of ProceduralGridMover not running custom grid rule passes

Hello,

Im having an issue which i believe is a bug in the grid graph using a procedural grid mover. Im not sure if its related to the grid mover, but thats what im using.

Basically the edge of the graphs are not updating as you can see here. The adjacent horizontal tiles to it remove the connections just fine. When the grid mover moves, its always the edge tiles that do this, not any specific tile.
image

Im using a main thread pass to get the connection filters then running an IConnectionFilter job to remove them. I tried both AfterConnections and PostProcess.

I am pretty sure my logic is fine, breakpointing shows the proper directional flags are being passed into the job, and the job is in fact returning false at that edge tile to designate an invalid connection. Yet the edges still seem to be fully connected once the graph updates.

Any help is appreciated, and if you need more info please let me know!

Versions:
Unity 2022.8
A* 4.3.82

Ill just drop my entire Grid rule code here for good measure:

using Pathfinding;
using Pathfinding.Jobs;

using Unity.Collections;
using Unity.Jobs;

using UnityEngine;
using UnityEngine.Tilemaps;

using Entities.Players;

using Tombstone;

using Pathfinding.Graphs.Grid.Rules;

using static Pathfinding.Graphs.Grid.GridIterationUtilities;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace Mapping
{

    public class DirectionalBlockGridRule : GridGraphRule
    {

        [System.Flags]
        public enum Dir
        {
            None = 0,
            Down = 1,
            Right = 2,
            DownRight = 3,
            Up = 4,
            DownUp = 5,
            UpRight = 6,
            Left = 8,
            DownLeft = 9,
            RightLeft = 10,

            UpLeft = 12,

        }

        struct RemoveConnJob : IJob, IConnectionFilter
        {
            static Vector2Int NW = new(-1, 1);
            static Vector2Int NE = new(1, 1);
            static Vector2Int SW = new(-1, -1);
            static Vector2Int SE = new(1, -1);

            public IntBounds bounds;
            public NativeArray<ulong> nodeConnections;

            [WriteOnly] public NativeArray<bool> nodeWalkable;
            [ReadOnly] public NativeArray<Vector3> nodePositions;
            public bool layeredDataLayout;
            [ReadOnly] public NativeArray<Dir> Dirs;

            public void Execute()
            {
                FilterNodeConnections(bounds, nodeConnections, layeredDataLayout, ref this);
            }

            public bool IsValidConnection(int dataIndex, int dataX, int dataLayer, int dataZ,
                int direction, int neighbourDataIndex)
            {
                // no directonal blocks, exit early
                if (Dirs[dataIndex] == Dir.None) return true;

                int? neighborIndex = GetNeighbourDataIndex(bounds, nodeConnections, layeredDataLayout,
                    dataX, dataLayer, dataZ, direction);

                // Get our position and the adjacent node's position
                Vector3 position = nodePositions[dataIndex];

                Vector3 neighbourPosition = nodePositions[neighborIndex.Value];
                Dir dir = Dirs[dataIndex];

                // rounding float issue, need to floor them first before subtract
                Vector2Int posDiffToNeighbor = Vector2Int.FloorToInt(neighbourPosition)
                    - Vector2Int.FloorToInt(position);

                if (dir.HasFlag(Dir.Up) && posDiffToNeighbor == Vector2Int.up)
                {
                    int a = 0;
                }

                if (dir.HasFlag(Dir.Up)
                    && (posDiffToNeighbor == Vector2Int.up || posDiffToNeighbor == NW || posDiffToNeighbor == NE))
                    return false;

                if (dir.HasFlag(Dir.Down)
                    && (posDiffToNeighbor == Vector2Int.down || posDiffToNeighbor == SW || posDiffToNeighbor == SE))
                    return false;

                if (dir.HasFlag(Dir.Left)
                    && (posDiffToNeighbor == Vector2Int.left || posDiffToNeighbor == NW || posDiffToNeighbor == SW))
                    return false;

                if (dir.HasFlag(Dir.Right)
                    && (posDiffToNeighbor == Vector2Int.right || posDiffToNeighbor == NE || posDiffToNeighbor == SE))
                    return false;

                // diagonal
                if (dir.HasFlag(Dir.DownLeft) && posDiffToNeighbor == SW) return false;
                if (dir.HasFlag(Dir.UpRight) && posDiffToNeighbor == NE) return false;
                if (dir.HasFlag(Dir.UpLeft) && posDiffToNeighbor == NW) return false;
                if (dir.HasFlag(Dir.DownRight) && posDiffToNeighbor == SE) return false;

                return true;
            }
        }

        public Tilemap[] FunctionalTilemaps;

        void GetTilemaps()
        {
            TilemapManager tmMan;

            if (Application.isPlaying)
            {
                if (Player.LocalPlayer == null)
                {
                    Debug.LogWarning("Local player not loaded yet. This is probably fine?");
                    return;
                }

                var scene = Player.LocalPlayer.gameObject.scene;
                if (!FishNetUtils.IsValidGameScene(scene.name)) return;
                Debug.Log("TilemapGridRule, before conns, LocalPlayer scene: " + scene.name);

                if (!TilemapManager.Instances.TryGetValue(scene, out tmMan))
                {
                    Debug.LogWarning("No tilemap manager instance for scene: " + scene.name);
                    return;
                }
            }
            else
            {
                tmMan = Object.FindAnyObjectByType<TilemapManager>();
            }

            FunctionalTilemaps = tmMan.FunctionMaps;

        }

        public override void Register(GridGraphRules rules)
        {
            base.Register(rules);

            rules.AddMainThreadPass(Pass.PostProcess, context =>
            {
                GetTilemaps();
                if (FunctionalTilemaps == null || FunctionalTilemaps.Length == 0) return;

                NativeArray<Dir> dirs = new(context.data.nodePositions.Length, Allocator.TempJob);

                for (int i = 0; i < context.data.nodePositions.Length; i++)
                {
                    Dir dir = 0;
                    Vector2Int tilePos = Vector2Int.FloorToInt(context.data.nodePositions[i]);

                    // using tilemaps here is fine since this isnt actually on a diff thread, just the job is
                    foreach (Tilemap fnMap in FunctionalTilemaps)
                    {
                        if (fnMap == null) continue;

                        TileBase tile = fnMap.GetTile((Vector3Int)tilePos);
                        if (tile == null) continue;

                        string lowerTileName = tile.name.ToLower();

                        if (lowerTileName.Contains("up") && tilePos.y == 37)
                        {
                            int a = 0;
                        }

                        dir |= lowerTileName.Contains("down") ? Dir.Down
                            : lowerTileName.Contains("right") ? Dir.Right
                            : lowerTileName.Contains("up") ? Dir.Up
                            : lowerTileName.Contains("left") ? Dir.Left
                            : lowerTileName.Contains("nw") ? Dir.UpLeft
                            : lowerTileName.Contains("ne") ? Dir.UpRight
                            : lowerTileName.Contains("se") ? Dir.DownRight
                            : lowerTileName.Contains("sw") ? Dir.DownLeft
                            : Dir.None;
                    }

                    dirs[i] = dir;
                }

                RemoveConnJob job = new RemoveConnJob
                {
                    bounds = context.data.bounds,
                    nodeConnections = context.data.nodeConnections,
                    nodeWalkable = context.data.nodeWalkable,
                    nodePositions = context.data.nodePositions,
                    layeredDataLayout = context.data.layeredDataLayout,
                    Dirs = dirs,
                };

                var handle = job.Schedule(context.tracker);

                dirs.Dispose(handle);

            });


            rules.AddMainThreadPass(Pass.AfterConnections, context =>
            {
                GetTilemaps();
                if (FunctionalTilemaps == null || FunctionalTilemaps.Length == 0) return;

                for (int i = 0; i < context.data.nodePositions.Length; i++)
                {
                    Vector2Int tilePos = Vector2Int.FloorToInt(context.data.nodePositions[i]);

                    foreach (var fnMap in FunctionalTilemaps)
                    {
                        if (fnMap == null) continue;

                        TileBase tile = fnMap.GetTile((Vector3Int)tilePos);
                        if (tile == null) continue;

                        if (tile.name.ToLower() == "block")
                        {
                            context.data.nodeWalkable[i] = false;
                            break;
                        }
                    }
                }
            });

        }

    }


#if UNITY_EDITOR
    [CustomGridGraphRuleEditor(typeof(DirectionalBlockGridRule), "Directional Block Grid Rule")]
    public class DirectionalBlockGridRuleEditor : IGridGraphRuleEditor
    {

        public void OnInspectorGUI(GridGraph graph, GridGraphRule rule)
        {
            DirectionalBlockGridRule target = rule as DirectionalBlockGridRule;

            if (target.FunctionalTilemaps != null && target.FunctionalTilemaps.Length > 0)
                for (int i = 0; i < target.FunctionalTilemaps.Length; i++)
                    target.FunctionalTilemaps[i] = (Tilemap)EditorGUILayout.ObjectField("Fn Tilemap " + i, target.FunctionalTilemaps[i], typeof(Tilemap), true);
        }

        public void OnSceneGUI(GridGraph graph, GridGraphRule rule)
        {
        }

    }
#endif

}

bump

still have not found a solution!

bump

i have no updates to give atm

Hi

I’m planning on looking at this tomorrow. Sorry that I haven’t found time so far. I think I know where the problem might lie.

1 Like