[Bug][1.6.8] ExternalBehaviorTree + Parallel task = error/problem

genoli

New member
I have a custom task (CheckPlayerAction) which calls the function below in a script attached to the AI's root gameobject, if I have a Parallel task in a tree after switching to new tree I get the error below.

Am I doing something wrong? Switching code insufficient? Or is this a bug? Any ideas?

Switching function:
C#:
public void SetBehaviorTree(ExternalBehaviorTree _ebt)
    {
        bt.DisableBehavior();
        bt.ExternalBehavior = _ebt;
        bt.EnableBehavior();
    }

Error:
Code:
NullReferenceException: Object reference not set to an instance of an object
BehaviorDesigner.Runtime.BehaviorManager.RunParentTask (BehaviorDesigner.Runtime.BehaviorManager+BehaviorTree behaviorTree, System.Int32 taskIndex, System.Int32& stackIndex, BehaviorDesigner.Runtime.Tasks.TaskStatus status) (at <843968489f854a31bdd9270d59c9c087>:0)
BehaviorDesigner.Runtime.BehaviorManager.RunTask (BehaviorDesigner.Runtime.BehaviorManager+BehaviorTree behaviorTree, System.Int32 taskIndex, System.Int32 stackIndex, BehaviorDesigner.Runtime.Tasks.TaskStatus previousStatus) (at <843968489f854a31bdd9270d59c9c087>:0)
BehaviorDesigner.Runtime.BehaviorManager.Tick (BehaviorDesigner.Runtime.BehaviorManager+BehaviorTree behaviorTree) (at <843968489f854a31bdd9270d59c9c087>:0)
BehaviorDesigner.Runtime.BehaviorManager.Tick () (at <843968489f854a31bdd9270d59c9c087>:0)
BehaviorDesigner.Runtime.BehaviorManager.Update () (at <843968489f854a31bdd9270d59c9c087>:0)
 

Attachments

  • behavior tree.png
    behavior tree.png
    42.2 KB · Views: 3
Are you switching the behavior tree within the tree that you are wanting to switch out? For this situation you'll want to do it outside of the actual task and instead wait for the tree to finish executing that tick.
 
Are you switching the behavior tree within the tree that you are wanting to switch out? For this situation you'll want to do it outside of the actual task and instead wait for the tree to finish executing that tick.

I have an external script to do the actual switch with the custom task just requesting it, I fixed it by adding interrupt tasks to make sure the tree completes itself, and using a listener to check when behavior tree ends after the request, then after the listener is called it switches the tree and no more error, I don't know if this a good way of doing it (if switching a lot), only that it works.

External script code which CheckPlayerAction task calls:
C#:
private ExternalBehaviorTree lastEbt;
public void SetBehaviorTree(ExternalBehaviorTree _ebt)
{
    lastEbt = _ebt;

    bt.OnBehaviorEnd += BehaviorEnded;
}

void BehaviorEnded(Behavior behavior)
{
    bt.OnBehaviorEnd -= BehaviorEnded;

    bt.ExternalBehavior = lastEbt;

    bt.EnableBehavior();
}
 

Attachments

  • working.png
    working.png
    53.8 KB · Views: 2
Update: Seems to work if you don't mind waiting for tree to complete first but I tried adding a Parallel Selector above the top Sequence Task with a bool check so I can set a StopNow variable to true externally which then completes the tree but I still get the errors even though I am using the listener and waiting for tree to complete, I think there is a problem with the Tick function in BehaviorManager where it's trying to look for an item in an array which doesn't exist.
 

Attachments

  • hmm.png
    hmm.png
    71.8 KB · Views: 1
I imported the source code and it seems that when changing external behavior tree the behaviorTree.activeStack list size is sometimes changed while the for loop in the Tick(BehaviorTree behaviorTree) function is running which then causes an exception at: TaskStatus status = behaviorTree.interruptionTaskStatus;

"i" being greater than the size of the list.

As a temporary fix I've added just above status variable line:

C#:
if (i >= behaviorTree.interruptionTaskStatus.Count)
{
    continue;
}
 
I would not try to replace the current tree within the behavior tree at all. When you replace the external behavior you are replacing the internal data structures so it's going to cause problems. You should wait for the tick to complete before setting the external tree.
 
I would not try to replace the current tree within the behavior tree at all. When you replace the external behavior you are replacing the internal data structures so it's going to cause problems. You should wait for the tick to complete before setting the external tree.

Is there a listener or some function called after tick completes were I can do this or would I need to add this functionality myself manually?
 
There isn't a tick complete callback but you can manually tick the tree and then issue your own callback/check:

 
Top