BUG: Setting a variable through the Behavior Tree Reference task does not work properly if another BTR task set a variable with the same name

Brent

New member
I'm trying to use external behavior trees as building blocks that I can easily slot in and use for different characters with complex behavior - I don't want to rewrite "Move over there and pick up an object" dozens of times. So I frequently call external behaviors and set a simply-named variable like "TargetObject".

However, I've discovered that if I set TargetObject on Behavior Tree Reference A and then set a variable named TargetObject on Behavior Tree Reference B that pops up later, B will end up with the value I set for A. This seems very bizarre to me as I would expect that setting it the second time would override the variable and instead it does nothing. Changing the name of the variable in tree B to "TargetObjecto" makes it work (at least when you're not reusing the same trees), but this is not a viable solution for me.

Note that I do not have a TargetObject variable in my main tree. In fact I discovered that if I set up a variable named TargetObject in the main tree and leave it at null then setting the variable on the external tree through the BTR task won't do anything, it will just remain null!

My conclusion is that setting variables through the BTR task only works if you never have another variable with the same name in the expanded tree. This seems like a nasty bug and it's certainly stopping my plans cold! Let me know if you need any other info from me, but it should be pretty straightforward to set up.
 
Last edited:
I just tried but was unable to reproduce it. What serialization are you using? Can you attach a repro project? I only need the scenes/external trees :)
 
Wouldn't you know it, I put together a sample project and I couldn't reproduce it either. I bet this happens a lot!

We're going to integrate the source code in an attempt to debug what's going on in the main project. I'll be back when I have more info!
 
Alright, we got it! This took a long time, but we identified that the bug happens when you have 2 levels of subtrees through behaviour tree references. You can verify this by just running the sample scene, and you will see in the log that both ObjectA and ObjectB will have a reference to ObjectA.

By reducing the number of subtrees, the bug disappears. You can do this by clicking on the BehaviorObject in the scene and changing the tree reference to be MiddleLevelTree. When running that, ObjectA will reference ObjectA and ObjectB will reference ObjectB.

For our purposes we're going to be needing multiple levels for sure!
 
You can verify this by just running the sample scene, and you will see in the log that both ObjectA and ObjectB will have a reference to ObjectA.
Can you upload that sample scene? I'll then take a look!
 
Thank you. I see what is going on.

When the behavior tree loads it loads all of the variables based on the variable name. Because you have TargetObject as the same name in ExternalTreeA and B then it is only going to use a single variable. In order to have two different variables you will need to have two variable names, TargetObjectA and TargetObjectB. When the behavior tree is initialized the external tree concept is no longer applicable as the external trees are consumed at runtime and the variables are merged.
 
Your proposed workaround for the variable passing feature is very dangerous for complex projects:
  1. It is very error-prone and hard to debug as it's an invisible failure where a variable simply doesn't receive a new value.
  2. It is impossible to use the same external tree twice in a higher level tree.
To be clear, it's not a problem that the two become a single variable at runtime - we can work around that. The problem is that the variable cannot be set more than once through this method and subsequent attempts to write to it are ignored. That seems very much like an unintended result. Are you saying this problem is so inherent to the architecture of Behavior Designer that the feature can't be fixed?
 
When the behavior tree is loaded the structure is flattened so TargetObject becomes a normal variable. This means that you are able to write to that single variable, but it will have the same value in all of the subtrees. In your sample project if I were to add a Set GameObjects task just after the TreeA reference then it would update the value for the TreeB reference.
 
Top