libgdx/gdx-ai

Subsequent calls to PathFinderRequest.search throw exception

tomcashman opened this issue · 4 comments

Issue details

It seems that once the path is found or not found, subsequent calls to PathFinderRequest.search will throw an exception. I was receiving the exception in my game and it took some time to figure out. I would expect that calling search after the path is found or not found would just immediately return true.

Version of gdx-ai and/or relevant dependencies

1.9.6

Stacktrace

Found path
Exception in thread "LWJGL Application" java.lang.ArrayIndexOutOfBoundsException: -1
	at com.badlogic.gdx.utils.BinaryHeap.remove(BinaryHeap.java:70)
	at com.badlogic.gdx.utils.BinaryHeap.pop(BinaryHeap.java:60)
	at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.search(IndexedAStarPathFinder.java:144)
	at com.badlogic.gdx.ai.pfa.PathFinderRequest.search(PathFinderRequest.java:88)
	at com.mygdx.game.BugExample.render(BugExample.java:26)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:225)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:126)

Glad to see you back again.
I'm going to investigate this issue asap.
Thanks for the report.

Not sure how to reproduce your issue, but after a quick glance at the stack trace I guess that replacing the loop do { ... } while (openList.size > 0); with the loop while (openList.size > 0) { ... } should fix the issue.

Can you confirm?

I can check this evening but I've attached a quick example I wrote the other day trying to solve the issue. I think the issue may be a documentation problem as I might be using the API wrong?

gdx-ai-bug.zip

Well, yes, I have to admit that the documentation about interruptible pathfinding is not exhaustive at all.
You should not call PathFinderRequest.search() directly. That method should be called for you by the PathFinderRequestControl of the PathFinderQueue.
Ideally, with time sliced pathfinding you have to use a queue because a single search may take several frames to complete and there might be new incoming requests in the meantime.

It might be worth adding a check before the above-mentioned loop in order to detect and report possible improper use of the API. I mean, something like

if (openList.size == 0) {
  throw new RuntimeException("The open list is unexpectedly empty. Usually, this means that you're misusing the API.");
}