Best Practices for Performance in Complex Behavior Trees with Dynamic Roles

Schreppy

New member
"I am looking for best practices regarding performance and scalability for complex Behavior Trees (BTs).

The Situation:I have X NPCs, each capable of performing various jobs (e.g., blacksmith, guard, farmer). NPCs can switch between these jobs dynamically during runtime. Currently, my approach is to have one massive Behavior Tree per NPC that contains the logic for all possible jobs, using a conditional branch to enter only the currently active job's subtree. I use subtrees for each job, but I don't swap them out; instead, they lie next to each other and are essentially unpacked at runtime.

The Question:Is Behavior Designer intended to handle such complex, 'all-in-one' trees, or is it better practice to swap subtrees via script at runtime? What is the best practice approach for maintaining performance and readability in this scenario?
 

Attachments

  • TreeInEditor.png
    TreeInEditor.png
    82.4 KB · Views: 19
  • TreeInRuntime.png
    TreeInRuntime.png
    203.3 KB · Views: 20
For the absolute best performance you'll want to use ECS tasks, though I know that it's not possible in every situation. For your situation if you do not need to switch jobs often then reevaluating the tree and swapping them out is the way to go. In general the less tasks the better because those tasks then don't need to be iterated upon.
 
Hi Justin,

I followed your advice and swapping the subtrees. To do this, I created a ProfessionSubtreeReference with two Jobs Craftsmen and Servant:
public class ProfessionSubtreeReference : SubtreeReference
{

public Subtree servant;
public Subtree craftsmen;

private Subtree[] m_ActiveSelection;

public override Subtree[] Subtrees => m_ActiveSelection;

public override void EvaluateSubtrees(IGraphComponent graphComponent)
{
m_ActiveSelection = null;
var component = graphComponent as Component;
Debug.Log("EvaluateSubtrees");

if (component != null)
{
var npc = component.gameObject.GetComponent<NPCBehaviour>();

if (npc != null && npc.instance != null)
{
var profession = npc.instance.currentProfession;
Debug.Log(profession);
switch (profession)
{
case NPCInstance.Profession.Servant:
m_ActiveSelection = new Subtree[] { servant };
break;
case NPCInstance.Profession.Craftsmen:
m_ActiveSelection = new Subtree[] { craftsmen };
break;
default:
m_ActiveSelection = null;
break;
}
return;
}
}

m_ActiveSelection = null;
}
}

Every time the profession changes, I call :
public void ChangeProfession(Profession newProfession)
{
instance.currentProfession = newProfession;
tree.ReevaluateSubtreeReferences();
}

from the NPC. However, EvaluateSubtrees is still only called once at the beginning of the game and not after I change the job. That means the Tree goes initial in the first job but after changing to the other one it stays in the first one.

Here is the Tree:Tree.png
 
It's really hard to say without stepping through it. Can you reproduce the issue within the sample scene?
 
Back
Top