Need help making a path rule

Hi I’m trying to make my pathfinding agents prefer walking on paths in my game. I have a 2d top down game.

I made a Unity Tilemap where I added the paths as tiles. Then I made a custom GridGraphRule to read in that tilemap and if there’s a tile at that node location it will decrease the nodePenalties parameter. Unfortunately it doesn’t work and I’m getting some errors when the scene changes.

Am I at least on the right track here? Here is my code.

using Pathfinding.Graphs.Grid.Rules;
using UnityEngine;
using UnityEngine.Tilemaps;

// 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 MyPathfindingWalkabilityRule : GridGraphRule
{

    public Grid grid;
    public Tilemap paths;
    
    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 => {
            // 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 nodesPenalties = context.data.nodes.penalties;
            var nodePositions = context.data.nodes.positions;

            // We iterate through all nodes and mark them as walkable or unwalkable based on some perlin noise
            for (int i = 0; i < nodePositions.Length; i++) {
                var position = nodePositions[i];
                
                Vector3Int tilePos = grid.WorldToCell(position);
                if (paths.GetTile(tilePos))
                {
                    nodesPenalties[i] -= 50;
                }
                
                
            }
        });
    }
}
using Pathfinding.Graphs.Grid.Rules;
using UnityEditor;
using UnityEngine;
using UnityEngine.Tilemaps;

namespace Pathfinding {
    [CustomGridGraphRuleEditor(typeof(MyPathfindingWalkabilityRule), "My Pathfinding Rule")]
    public class RuleExampleNodesEditor : IGridGraphRuleEditor {
        public void OnInspectorGUI (GridGraph graph, GridGraphRule rule)
        {
            var target = rule as MyPathfindingWalkabilityRule;

            target.grid = EditorGUILayout.ObjectField("Grid", target.grid, typeof(Grid), true) as Grid;
            target.paths = EditorGUILayout.ObjectField("Paths Tilemap", target.paths, typeof(Tilemap), true) as Tilemap;
        }

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

Hi

Penalties cannot be negative. But you can increase the penalty for all other nodes.

Sorry, I responded to my old post instead of this one. I got it working by using the GraphUpdateScene component…I wish I could paint the paths with a Tilemap because creating the GraphUpdateScene is painful when dealing with a Tilemap with many twists and turns. Also, I don’t understand the penalty number - it doesn’t work for small numbers but then I noticed in the tooltip it says to use large numbers and it started working then. It seems a bit odd to use some arbitrarily high numbers and hope it works. Just wanted to give you my feedback.

Maybe I can make a script to create a 1x1 graph update scene object to match each tile in a Tilemap although that could be a lot of objects. I will have to do something similar for the paths that the user is able to place in the game - I hope it doesn’t lag but we’ll see…

The cost of moving 1 world unit is approximately 1000. That’s a good reference to have in mind when setting penalty numbers.