I've implemented a simple Behavior Tree algorithm which I intend to use inside a Unity project. It's mostly working as I expected, except I'm having trouble making proper use of it, which might be caused by some misunderstanding of mine. My problem is as follows:
If a leaf node takes a long time to finish, for instance, an action that makes a game unit follow a specific path, that means the leaf node is currently at the "running" state. However, if I return the state, I can no longer run the rest of the function, which means I can't reach my destination.
So my question is: what is the proper way to tell my tree that a leaf node is running?
Here's what I got on my ActionNode class:
public class ActionNode : BTNode
{
public delegate NodeStates ActionNodeDelegate();
protected ActionNodeDelegate nodeAction;
public ActionNode(ActionNodeDelegate action)
{
nodeAction = action;
}
public override NodeStates Evaluate()
{
switch (nodeAction())
{
case NodeStates.FAILURE:
currentNodeState = NodeStates.FAILURE;
return currentNodeState;
case NodeStates.SUCESS:
currentNodeState = NodeStates.SUCESS;
return currentNodeState;
case NodeStates.RUNNING:
currentNodeState = NodeStates.RUNNING;
return currentNodeState;
default:
currentNodeState = NodeStates.FAILURE;
return currentNodeState;
}
}
}
If you need to check the other classes, it's all based on this article. Linking it for the sake of keeping the thread cleaner.
As for an action example, consider this:
private NodeStates FollowPath() {
bool targetReached;
if (targetReachable)
targetReached = WalkToTarget();
if (targetReached)
return NodeStates.SUCESS;
else
return NodeStates.FAILURE;
}
What I'm wondering is, if WalkToTarget takes a long time, how do I return a "running" state?
I've read many different articles on the subject, but I can't seem to grasp the exact concept behind these states. I understand how I can, for instance, tell that a Sequence or Selector node is running.
The only idea that crossed my mind is that I'd store the remaining path inside a variable at my enemy class and call the method every game update tick, but I feel like that's just poor coding.
Are leaf nodes supposed to return "running" at any given moment? If so, in which cases would that happen? Any examples would be appreciated!
Okay, I figured out what I was doing wrong. I was assuming that my tree was responsible for executing the action code, when it is actually supposed to only evaluate the state of every node. In this case, my above example would change to something like this:
private NodeStates ShouldFollowPath() {
if (targetReachable && this.position != target.position)
return NodeStates.RUNNING;
else if (this.position == target.position)
return NodeStates.SUCESS;
else
return NodeStates.FAILURE;
}
And then I'd check the state of the above Node after evaluating the tree and execute my FollowPath code:
private ActionNode FollowPathNode = new ActioNode(ShouldFollowPath);
private void Update()
{
FollowPathNode.evaluate();
if (FollowPathNode.nodeState == NodeStates.RUNNING)
FollowPath();
}
In summary, I misunderstood the usage of the behavior tree. The above example solves my problems.