Agent ignores penalty by going diagonally

Using a grid graph, and as shown in a picture, an agent completely ignores penalty by cutting the nodes diagonally:
image

The blue nodes are marked as walkable.
The blue nodes have tag “Wall”, which has a penalty cost of 500,000 in a Seeker for the agent:
image

When I remove any diagonal node possibility for the agent, the path is calculated correctly:
image

When I make the nodes not traversable in Tags, the path is calculated correctly
image
image

However the tag needs to be traversable so enemies can path through walls if path is too long to get to the player and attack him.

I have tried removing all modifiers from the agent, as well as using funnel, simple smooth or raycast, still the same issue.

Grid Setup:

How to solve this issue? Am I doing something wrong, or could this be a bug?

Thank you!

I am also recalculating all connections using
graph.GetNodes(node => graph.CalculateConnections((GridNodeBase)node));

Hi

Sorry for the late reply, I’ve been sick these last few weeks.

That is expected behavior, the agent never moves over the nodes that have a penalty if it moves diagonally like that.

Hello @aron_granberg,

not sure I understand your answer, even though I must have read it more than 5 times :slight_smile:
What do you mean by “agent never moves over the nodes that have a penalty if it moves diagonally like that.”?

The agent does move over nodes with penalties diagonally, but it should not, correct? It should behave like in any other scenario it is not suppose to move over the nodes (e.g. they are not traversable).

How to make so the agent cannot move diagonally as shown in the picture?

Unwanted behaviour
image
Expected behaviour:
image

when using only penalties on blue nodes in the picture

So if I understand correctly, the grid graph is just unusable when using penalties? Since if agents cross diagonally, it defeats the entire purpose of grid tiles.

Hi

I’ve been thinking about this.
So the main issue is that by going diagonally, the agent never actually moves over the nodes you have added penalties to. Currently, there’s no out of the box way to change this behavior.

However, I did come up with a solution, but it requires a minor change to the code.
If you open the GridNode.cs script, there should be a comment saying:

// Check if the other node has not yet been visited by this path

Right before that comment, add this snippet of code:

if (dir >= 4) {
        // Get the two axis aligned neighbours that we are moving between
	var d1 = dir - 4;
	var d2 = (dir - 4 + 1) % 4;
	var n1 = this.GetNeighbourAlongDirection(d1);
	var n2 = this.GetNeighbourAlongDirection(d2);
	// Theroretically reasonable scaling factor.
	// This will make moving diagonally across a grid of nodes with penalties
	// equally costly per unit of distance as moving in an axis aligned direction.
	const float SQRT2_MINUS_1 = 0.414213f;
	if (n1 != null) tmpCost += (uint)(path.GetTraversalCost(n1) * (SQRT2_MINUS_1 * 0.5f));
	if (n2 != null) tmpCost += (uint)(path.GetTraversalCost(n2) * (SQRT2_MINUS_1 * 0.5f));
}

Thank you @aron_granberg very much! I cannot test this, as we are using the beta of the pathfinding and have your asset only as a manifest package, thus the code cannot be edited. Not sure how hard it is, but would you be able to deploy this addition to the beta? Maybe adding some optional flag into the grid graph?

Such a functionality seems like a common usage for many devs using grids.

Hi

What you can do is just copy and paste the package into your project for testing. Take a look at this page: Unity - Manual: Embedded dependencies under the Copying a Unity package from the cache section. Move it to Assets/AstarPathfindingProject.

Let me know how it works for you and maybe I’ll include it in the main package. :slight_smile:

@aron_granberg big thanks for all your help! The provided solution works like a charm.

Would it be possible now to add it into an official beta release? Maybe like an option somwehere? Since the code is changed just manually, updating the package any time in the future would always just rewrite this fix.

1 Like

Helo @aron_granberg, not sure if you remember this issue, but the fix code provided by you no longer works with the newest BETA version.
Is there any way how to fix this issue again? Or has it been maybe implemented as some flag?

Hi

Why does it no longer work?

My mistake, I did use a different modifier and it didnt work with that. But works with simple smooth.

1 Like

Hello @aron_granberg , we upgraded to newest beta, the comment no longer exists:

// Check if the other node has not yet been visited by this path

is there already an official way how to solve this, or we still have to do this manual fix after each update :slight_smile:

Please @aron_granberg any updates here? We cannot upgrade until this is solved :frowning: We really need your support in this issue.

Hi

Instead, change this line:

path.OpenCandidateConnection(pathNodeIndex, other.NodeIndex, gScore, neighbourCosts[dir], 0, other.position);

to

uint cost = neighbourCosts[dir];
if (dir >= 4) {
        // Get the two axis aligned neighbours that we are moving between
	var d1 = dir - 4;
	var d2 = (dir - 4 + 1) % 4;
	var n1 = this.GetNeighbourAlongDirection(d1);
	var n2 = this.GetNeighbourAlongDirection(d2);
	// Theroretically reasonable scaling factor.
	// This will make moving diagonally across a grid of nodes with penalties
	// equally costly per unit of distance as moving in an axis aligned direction.
	const float SQRT2_MINUS_1 = 0.414213f;
	if (n1 != null) cost += (uint)(path.GetTraversalCost(n1) * (SQRT2_MINUS_1 * 0.5f));
	if (n2 != null) cost += (uint)(path.GetTraversalCost(n2) * (SQRT2_MINUS_1 * 0.5f));
}
path.OpenCandidateConnection(pathNodeIndex, other.NodeIndex, gScore, cost, 0, other.position);
1 Like

Thank you very much, this is working.

Please, would you officially support this as some boolean flag on grid graph or agents? Because I imagine many other people would want to enable this functionality, and now its only possible to do this manually after every upgrade.

Hello @aron_granberg

I still have to make official request for this feature to be as some optional UI toggle in the grid graph settings.
Because now, we have to each time manually update the package, copy it as embedded package, find this class and replace the code, if you change the class, it will not longer work as well.

I presume this setting could be used by other users.

Thank you very much :slight_smile:

Again begging here for this simple addition to newest version of this plugin. Its very cumbersome for our team to update the plugin now.