Turn-based example behaved oddly

We encountered some issues while adapting the turn-based example on this page:

https://arongranberg.com/astar/docs/turnbased.php

We ultimately got the code to work, but not without several edits/workarounds. This A* Pathfinding Project is quite well-used, so we wonder if perhaps we are doing something wrong. We are using version 4.0.10.

  1. We copied the code in BlockerPathTest.cs, but changed line 14 to use BlockManager.BlockMode.AllExceptSelector instead of BlockManager.BlockMode.OnlySelector . After doing so, we passed in 0 arguments to the “obstacles” list, which we figured would treat everything as an obstruction. It did not–the path was drawn straight through the sphere. Our workaround was to pass 1 argument (not the sphere) to the “obstacles” list, which resulted in the path being drawn around the sphere as we believe is proper.

  2. We tried applying the example code to objects in our 2-D game. There are about 20 objects on our 17x15 grid. To each object were attached SingleNodeBlocker.cs and BlockerTest.cs. Then the BlockerPathTest script (using BlockManager.BlockMode.AllExceptSelector on line 14) was added to one of the objects and given another object as the target. The object itself was passed into the obstacles list so as to prevent pathing around itself. (This also suffices as the workaround for Issue 1.) We observed that the path was being drawn straight through objects that should have been obstructions. Investigation with a debugger revealed that line 102 of BlockManager.cs wasn’t finding anything because the hashcode of the node being looked for was different than the hashcode of the corresponding node in the “blocked” dictionary. Workaround: in GridNodeBase.cs, we overrode methods GetHashCode() and Equals(object obj) to ensure that a node at a particular X-Z position always returns a consistent hashcode.

  3. After the above changes, the pathing algorithm was properly finding nodes in the “blocked” dictionary, but misevaluating whether a node was an obstruction. We determined that the logic BlockManager.NodeContainsAnyExcept() was returning incorrect results. Workaround: we replaced lines 108-114 (a FOR loop) with this condition:

if (selector.Contains(inNode) == false) { return true; }

As mentioned, after making the above changes, the pathing in our game now seems to be working correctly. But it seems unlikely that we’d be the first to encounter issues of this significance on such a well-used project. Are we perhaps doing something incorrectly?

Hi

The pathfinding system itself is very well used, however the turn-based subsystem is very new. It was introduced only a few months ago in 4.0, so not that many people have used it yet.

  1. That does indeed look like a bug. I have fixed it in my dev version now.
  2. That sounds odd. Nodes are reference type objects, so their hash code should be essentially their memory address.
    Have you re-scanned the graph or something like that in-game?
  3. Yep. I also concluded that. I have made almost the same fix. The difference is that the selector.Contains call would end up using the unity equality comparison which is not thread safe. So it will only work when you are not using multithreading. Here is my version: https://pastebin.com/q6G4n30L

Re. 2, You’re right; we were calling AstarPath.active.Scan() each time the board configuration changed. But this appears not to be necessary–paths are updating with each turn even without those calls. Removing those calls eliminates the problem and allows us to remove the workaround code.

Re. 3. I’ve replaced our workaround code with your version and things seem to be working.

Thanks for your help, and for this package!