Bug - When Switching External Behavior Trees NullReferenceException: Object reference not set to an instance of an object

kk99

New member
Alright, it took me literally days to track down this issue -__- :mad::mad::mad:


I guess I will provide some screenshots that make it easier to understand

1548359448499.png


This Error appears when I am trying to swap External Trees using following code


this.GetComponent<BehaviorTree>().ExternalBehavior = GameObject.Find("TreesBehavior").GetComponent<TreesBehavior>().getTree(TREE);



I literally tried everything before and after with all kind of combinations,even calling the upper code from other GameObjects that are not attached to BehaviorTree etc.

this.GetComponent<BehaviorTree>().StopAllCoroutines();
this.GetComponent<BehaviorTree>().DisableBehavior();
this.GetComponent<BehaviorTree>().enabled = false;


Tried calling in
public override TaskStatus OnUpdate()
or
public override void OnStart()

Nothing works.

The error seems not to be crucial because everything still works fine but the Error is pretty annoying because it Spams my console full.



The funny thing is, this error only happens when the upper code is executed within or below a Sequence that has a "Return Success". I assume there are more possible combinations and I am pretty sure an "Inverter" will lead to the same situation (not tested).

1548360031489.png


However, if you move the Swap Tree outside that Sequences into a Sequence that has not "Return Success", there is no error


1548360177753.png




Full Code looks like this right now but as I said I tried literally any kind of combination


public TreesBehavior.Tree TREE;

public override void OnStart()
{
this.GetComponent<BehaviorTree>().StopAllCoroutines();
}

public override TaskStatus OnUpdate()
{
this.GetComponent<BehaviorTree>().DisableBehavior();


var tree = Object.Instantiate(GameObject.Find("TreesBehavior").GetComponent<TreesBehavior>().getTree(TREE));
tree.Init();

this.GetComponent<BehaviorTree>().ExternalBehavior = tree;;
this.GetComponent<BehaviorTree>().EnableBehavior();
this.GetComponent<BehaviorTree>().enabled = true;

return TaskStatus.Success;

}




A fix or a solution would be very appreciated.

Sometimes not sure when I get this error instead of the upper one


ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
System.Collections.Generic.List`1[System.Collections.Generic.List`1[System.Int32]].get_Item (Int32 index) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:633)
BehaviorDesigner.Runtime.BehaviorManager.RunParentTask (BehaviorDesigner.Runtime.BehaviorTree behaviorTree, Int32 taskIndex, System.Int32& stackIndex, TaskStatus status)
BehaviorDesigner.Runtime.BehaviorManager.RunTask (BehaviorDesigner.Runtime.BehaviorTree behaviorTree, Int32 taskIndex, Int32 stackIndex, TaskStatus previousStatus)
BehaviorDesigner.Runtime.BehaviorManager.Tick (BehaviorDesigner.Runtime.BehaviorTree behaviorTree)
BehaviorDesigner.Runtime.BehaviorManager.Tick ()
BehaviorDesigner.Runtime.BehaviorManager.Update ()
 
it's cursed. moments after you post your problem you find your solutions accidentally

this fixed it for me




return TaskStatus.Running;

instead of

return TaskStatus.Success;

it also doesnt matter how you instentiate it

ExternalBehavior tree = Object.Instantiate(GameObject.Find("TreesBehavior").GetComponent<TreesBehavior>().getTree(TREE));
tree.Init();

this.GetComponent<BehaviorTree>().ExternalBehavior = tree;

or just



this.GetComponent<BehaviorTree>().ExternalBehavior = Object.Instantiate(GameObject.Find("TreesBehavior").GetComponent<TreesBehavior>().getTree(TREE));


or

this.GetComponent<BehaviorTree>().ExternalBehavior = (GameObject.Find("TreesBehavior").GetComponent<TreesBehavior>().getTree(TREE));


Tested all of them.
I wish I could get back my lost 15+ hours :cry::mad::eek::oops::rolleyes:o_Oo_Oo_Oo_Oo_Oo_O




I just hope this doesn't cause some performance issues if you do it too often. For the tree it looks like it still running although its not uhmm.
 
Last edited:
Glad you got it solved. So are you swapping the tree as it is executing? This isn't going to work too well so instead I recommend swapping the tree through another script outside of the behavior tree execution loop.
 
hmm Even if I swap the tree through another script outside of the behavior tree execution the error still shows up if the currently being executed Node of the current tree has a parent Node with "Return Success" e.g. in Position 2 in the image.


1548507452733.png




If you want to Swap a tree ( in such a Situation like in this the upper Screenshot) without Errors in Console and without using following Code you need some junk code.


//If you dont wanna use this
public override TaskStatus OnUpdate()
{
//Swap Code here

return TaskStatus.Running;
}


//but e.g. this
public override TaskStatus OnUpdate()
{
//Swap Code here, call external GameObject with e.g. with Coroutine

return TaskStatus.Success;
}

//or
public override void OnStart()
{
//Swap Code here, call external GameObject with e.g. with Coroutine

}


The junk code logic must somehow lead to a situation that you current node has no parent "Return Success" node.
If you tree is complex it will make your tree even more complex.


I am not sure if you are 100% aware of this issue and understand what I am trying to explain here but swapping tree in a child of "Return Success" Node is little complicated if you dont wanna use the Trick "return TaskStatus.Running; "


The probably easiest way might be to Call a Coroutine in another GameObject with e.g. 1 second delay.
At the the beginning of you tree have at least a 2 second Wait time before any logic is proceed.

Then you call "Restart Behavior Tree", after you called the Swap Tree Outside Logic.

1548508741303.png
 
Can you send me a repro scene via PM? Your setup is pretty specific so if you can send me a repro scene that would be great to allow me to quickly reprodocue it.
 
somehow I am not able to reproduce all errors in a new clean project.

I assume some errors might appear only when you have large project or maybe I am using something in an Action or Condition Script that should not be used this way and it's causing this console error when swapping trees.

Because I have already created more than 200+ Conditon/Action Scripts it's literally would take forever to track it down and since I found already a solution for me I dont care that much anymore.


but here is a sample project that generates the following error.

ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index


I experienced this also from time to time as mentioned in my previous posts.

https://drive.google.com/open?id=1OZGrl1pM4MU74iRvx1XjW2A7Cgf_a75p
 
Even though you are performing the swap within a monobehavior you are still performing the swap within the same execution tick as the behavior tree. If I change the method that AI_BT_SwapTree from swapap to swap then it is executed outside of the behavior tree's execution and it works.
 
I know and that's what I meant, in this Test Project it works fine, however, in my main project it does not work as it should and I am experiencing the issues as described in my previous posts, even if I am using an IEnumerator in the "swap" function.

But my main project has also tons of dependencies and 3rd party tools. For now it looks like to be very hard to reproduce unless I would upload my entire 20GB+ project.

anyhow thanks for the support if I should be ever able to find the cause I will come back to this post again.
 
Top