Artificial Intelligence framework for games based on libGDX or not. Features: Steering Behaviors, Formation Motion, Pathfinding, Behavior Trees and Finite State Machines
Apache License 2.0
1.18k
stars
241
forks
source link
Fix parallel task join orchestrator hard-resets its children. #134
The Parallel task's Join orchestrator calls reset() on its children when completed. That renders them unusable for any further use within the tree. Looks like it's a simple mistake of calling reset() (pool-related hard reset for task instances) instead of resetTask() (soft "restart" so the task can be run again).
Here's a simple example that demonstrates the bug.
public class BTreeParallelJoinTest extends ApplicationAdapter {
private BehaviorTree bTree;
@Override
public void create() {
super.create();
bTree = new BehaviorTree(
new Repeat(ConstantIntegerDistribution.NEGATIVE_ONE, // Repeat forever.
new Parallel(Parallel.Orchestrator.Join,
new AlwaysFail( // Any decorator will do here.
new Success()
)
)
)
);
}
@Override
public void render() {
super.render();
bTree.step();
}
}
The Repeat task crashes on the second iteration at the AlwaysFail decorator as its child was nullified by the reset() call:
Exception in thread "main" java.lang.NullPointerException: Cannot read field "status" because "this.child" is null
at com.badlogic.gdx.ai.btree.Decorator.run(Decorator.java:65)
at com.badlogic.gdx.ai.btree.branch.Parallel$Orchestrator$2.execute(Parallel.java:215)
at com.badlogic.gdx.ai.btree.branch.Parallel.run(Parallel.java:123)
at com.badlogic.gdx.ai.btree.LoopDecorator.run(LoopDecorator.java:56)
at com.badlogic.gdx.ai.btree.BehaviorTree.step(BehaviorTree.java:124)
...
The
Parallel
task'sJoin
orchestrator callsreset()
on its children when completed. That renders them unusable for any further use within the tree. Looks like it's a simple mistake of callingreset()
(pool-related hard reset for task instances) instead ofresetTask()
(soft "restart" so the task can be run again).Here's a simple example that demonstrates the bug.
The
Repeat
task crashes on the second iteration at theAlwaysFail
decorator as its child was nullified by thereset()
call: