libgdx/gdx-ai

Guarded task start() method running before guard.

lukz opened this issue · 7 comments

lukz commented

Is it intended to run start() method of guarded task before guard?

In my case I'm using guards to check if task should run and I'm setting some values that guarded task may use.

For example:
(isPlayerVisible? range:512 outVar:"targetPlayer") interpose ent1Var:"targetGuardEnt" ent2Var:"targetPlayer"

Guard is checking if any player is visible and output visible player reference to blackboard. Interpose task is using this reference in its start() method to set up Interpose task. But because interpose start() method is run before guard I've got null ptr exception.

Yeah I see your point.
Not sure but considering checkGuard occurrences it looks like you can replace code like this

		child.setControl(this);
		child.start();
		if (child.checkGuard(this))
			child.run();
		else
			child.fail();

with something along the line of

		child.setControl(this);
                boolean ok = child.checkGuard(this);
		child.start();
		if (ok)
			child.run();
		else
			child.fail();

I'm really busy these days, sorry. Can you try it and let me know?

lukz commented

I can't see how this change would fix the problem.

Well, maybe I'm missing something. As said above, I've not tested this change myself. Just looked quickly into the code.
Assuming you have a tree as simple as

parent
  (guard) task

wouldn't this change make guard run before task.start() ?

I'm just wondering if start method shouldn't be called at all in this context.

Wiki says :

a guard is a condition that must be met before executing the respective task

start() called when the task is entered, just before run() is invoked.

But "task execution" is not clearly defined. Is start method included in "task execution" ?

DynamicGuardSelector evaluates guard before starting children but Selector (and others) doesn't. Consider following example :

selector
  (hungry?) eat

Should we really start eating even if we're not hungry ?

lukz commented

@davebaol sorry I wrote my first question imprecisely

@mgsx-dev is right, the problem is that task start() method is called even when guard fail

Sounds reasonable. It looks like this code

		child.setControl(this);
		child.start();
		if (child.checkGuard(this))
			child.run();
		else
			child.fail();

should become

		child.setControl(this);
		if (child.checkGuard(this)) {
			child.start();
			child.run();
		}
		else
			childFail(null); // actually child has not failed

This kind of code should work for Decorator and BehaviorTree.
For Parallel and the other branches some other changes are likely needed.

Ali-RS commented

@davebaol any plan to fix this?

IMHO task.start() should be called only if the guard succeeds as mentioned by others.