Behavior Tree Reference using SharedVariable<ExternalBehaviorTree>


New member

so I have an entity prefab with a behaviour tree and multiple prefab variants that inherit from it. I can change the shared variables on such a variant just fine to adjust its behaviour. But when it comes to changing the structure of the tree or extending some branch, I will have to create a separate tree for it. From then on, changes that should affect the basic behaviour of all entities have to be made to all those copied trees.
I think, much of this could be improved by allowing for dynamic behavior tree references. It is possible to create a SharedVariable<ExternalBehaviorTree> but it cannot be plugged into the BehaviorTreeReference Task, unfortunately. I have a hard time building this myself. Is it possible?


New member
Oh, this was one of those things I had to spell out to get myself sorted out and find the solution.
Turns out you can write an implementation of the BehaviorReference Task that supports this. It's pretty cool!
Now all my entities can use the same tree and I can swap out parts of it by changing the tree in the TestTree variable. Neat.

If you want to have this, you just need to write a SharedVariable<ExternalBehaviorTree> implementation:
public class SharedExternalBehaviorTree : SharedVariable<ExternalBehaviorTree>
    public static implicit operator SharedExternalBehaviorTree(ExternalBehaviorTree value)
        return new SharedExternalBehaviorTree {Value = value};

And then you can use this implementation of BehaviorReference:
// Wrapper class for the Behavior Reference task that allows for dynamic behavior trees.
// A use-case for this is building variants of a tree by moving part of it to an external tree and reference it
// as a variable. That way, you can plug in entire trees into a variable and have it merged into the tree min runtime.
    "Behavior Tree Reference allows you to run another behavior tree within the current behavior tree.")]
public class DynamicBehaviorReference : BehaviorReference
    [SerializeField] private SharedExternalBehaviorTree[] _dynamicExternalBehaviors;
    public override ExternalBehavior[] GetExternalBehaviors()
        var mergedBehaviors = new ExternalBehavior[externalBehaviors.Length + _dynamicExternalBehaviors.Length];
        Array.Copy(externalBehaviors, mergedBehaviors, externalBehaviors.Length);
        ExternalBehavior[] dynamicBehaviors =
            _dynamicExternalBehaviors.Select(t => t.Value as ExternalBehavior).ToArray();
        Array.Copy(dynamicBehaviors, 0, mergedBehaviors, externalBehaviors.Length, dynamicBehaviors.Length);
        return mergedBehaviors;

Last edited: