Course contentsShow
← Unreal Engine Game Development
Lesson 445 of 8806. AI, Navigation, and Decision MakingFree lesson

Creating Custom Behavior Tree Decorators for State Checks

Write custom C++ Decorator nodes that query your state machine to determine if a branch of the tree should execute.

In this lesson, you will learn how to bridge your C++ State Machine logic directly into your Behavior Tree using custom Decorator nodes for robust decision-making.

The Problem with Blackboard-Only Logic

While Blackboard keys are excellent for simple data storage, they often struggle with complex, multi-variable states (e.g., "Is the AI currently reloading while also under cover?"). Instead of cluttering your Blackboard with flags that need constant synchronization, you can create a custom UBTDecorator that queries your C++ State Machine component directly.

Implementing the Custom Decorator

To do this, create a class inheriting from UBTDecorator. You’ll primarily override CalculateRawConditionValue. This function acts as the gatekeeper for your branch, returning true or false based on your AI’s internal state.

bool UMyStateDecorator::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
{
    // Access the AI Controller and its custom state component
    AAIController* Controller = OwnerComp.GetAIOwner();
    UMyStateMachine* StateMachine = Controller ? Controller->FindComponentByClass<UMyStateMachine>() : nullptr;

    if (StateMachine)
    {
        // Query the state machine directly for the condition
        return StateMachine->GetCurrentState() == EAIState::Combat;
    }

    return false;
}

Why This is Better

By moving the logic into a C++ Decorator, you achieve two major benefits:

  1. Encapsulation: Your Behavior Tree doesn't need to know how the state is calculated, only the result of the state.
  2. Performance: You avoid the overhead of updating multiple Blackboard keys every time an AI state changes. You simply check the component directly when the tree asks, "Can I enter this branch?"

When using these decorators, ensure your state machine logic is thread-safe and lightweight, as CalculateRawConditionValue will be triggered whenever the Behavior Tree evaluates the node, potentially multiple times per tick if the node is actively being monitored.

Key Takeaway: Use custom C++ Decorators to encapsulate complex state-check logic, keeping your Blackboard clean and your decision-making centralized within your State Machine component.