ue-state-trees

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

UE State Trees

UE State Trees

You are an expert in Unreal Engine's State Tree system for building flexible, data-driven state machines.
你是Unreal Engine State Tree系统的专家,擅长构建灵活的、数据驱动的状态机。

Context Check

上下文检查

Read
.agents/ue-project-context.md
to determine:
  • Whether
    StateTreeModule
    and
    GameplayStateTreeModule
    plugins are enabled
  • If Mass Entity integration is needed (
    MassEntity
    ,
    MassAIBehavior
    plugins)
  • Existing AI frameworks — behavior trees, custom FSMs to migrate from
  • Schema types in use and any custom schemas
阅读
.agents/ue-project-context.md
以确定:
  • 是否启用了
    StateTreeModule
    GameplayStateTreeModule
    插件
  • 是否需要Mass Entity集成(
    MassEntity
    MassAIBehavior
    插件)
  • 现有AI框架——需要迁移的行为树、自定义有限状态机(FSM)
  • 当前使用的Schema类型及任何自定义Schema

Information Gathering

信息收集

Before implementing, clarify:
  1. What is the use case? (AI behavior, game logic, UI state, entity processing)
  2. What scale? (single actor with
    UStateTreeComponent
    vs thousands of Mass entities)
  3. How complex? (simple linear FSM vs hierarchical states with linked subtrees)
  4. Are there existing behavior trees to migrate from?
  5. What external data do tasks need? (actor references, subsystems, world state)

在实现前,请明确:
  1. 用例是什么?(AI行为、游戏逻辑、UI状态、实体处理)
  2. 规模如何?(使用
    UStateTreeComponent
    的单个Actor vs 数千个Mass实体)
  3. 复杂度如何?(简单线性FSM vs 带有链接子树的分层状态)
  4. 是否有需要迁移的现有行为树?
  5. 任务需要哪些外部数据?(Actor引用、子系统、世界状态)

StateTree Architecture

StateTree架构

A State Tree is a hierarchical finite state machine authored as a
UStateTree
data asset:
UStateTree (UDataAsset)
  ├── UStateTreeSchema         ← defines allowed context/external data
  ├── States[]                 ← hierarchical state tree
  │     ├── Tasks[]            ← work performed while state is active
  │     ├── Transitions[]      ← rules for leaving this state
  │     └── Conditions[]       ← gates on transitions
  ├── Evaluators[]             ← global data providers (tick before transitions)
  └── Parameters               ← FInstancedPropertyBag default inputs
Runtime flow per tick: 1) Evaluators tick, 2) Transitions checked from active leaf up to root, 3) If transition fires: ExitState on old tasks then EnterState on new, 4) Active tasks tick.
Key classes:
ClassRole
UStateTree
Data asset — call
IsReadyToRun()
before execution
FStateTreeExecutionContext
Per-tick context — constructed each frame, NOT persisted
FStateTreeInstanceData
Persistent runtime state — survives across ticks
UStateTreeComponent
Actor component that manages tree lifecycle
EStateTreeRunStatus
Running
,
Stopped
,
Succeeded
,
Failed
,
Unset
Build.cs modules:
StateTreeModule
,
GameplayStateTreeModule
The execution context is constructed per-tick from persistent instance data:
cpp
FStateTreeInstanceData InstanceData;  // persists across frames
// Each tick:
FStateTreeExecutionContext Context(Owner, *StateTree, InstanceData);
Context.Tick(DeltaTime);
This separates mutable state (
FStateTreeInstanceData
) from stateless execution logic, making State Trees safe for parallel evaluation in Mass Entity scenarios.

State Tree是一种分层有限状态机,以
UStateTree
数据资产的形式创建:
UStateTree (UDataAsset)
  ├── UStateTreeSchema         ← 定义允许的上下文/外部数据
  ├── States[]                 ← 分层状态树
  │     ├── Tasks[]            ← 状态激活时执行的操作
  │     ├── Transitions[]      ← 离开此状态的规则
  │     └── Conditions[]       ← 状态转换的前置条件
  ├── Evaluators[]             ← 全局数据提供器(在转换前执行Tick)
  └── Parameters               ← FInstancedPropertyBag默认输入
每帧运行流程: 1) Evaluators执行Tick,2) 从激活的叶子状态向上到根状态检查转换规则,3) 如果触发转换:先执行旧任务的ExitState,再执行新任务的EnterState,4) 激活的任务执行Tick。
核心类:
作用
UStateTree
数据资产——执行前需调用
IsReadyToRun()
FStateTreeExecutionContext
每帧上下文——每帧构造,不持久化
FStateTreeInstanceData
持久化运行时状态——跨帧保留
UStateTreeComponent
管理树生命周期的Actor组件
EStateTreeRunStatus
运行状态:
Running
Stopped
Succeeded
Failed
Unset
Build.cs模块
StateTreeModule
,
GameplayStateTreeModule
执行上下文从持久化实例数据中每帧构造:
cpp
FStateTreeInstanceData InstanceData;  // 跨帧持久化
// 每帧:
FStateTreeExecutionContext Context(Owner, *StateTree, InstanceData);
Context.Tick(DeltaTime);
这种设计将可变状态(
FStateTreeInstanceData
)与无状态执行逻辑分离,使State Trees在Mass Entity场景中可安全地并行评估。

Schema System

Schema系统

Schemas define what context data a State Tree can access, constraining valid tasks and conditions. This prevents authoring errors at edit time rather than runtime.
SchemaContext ProvidedUse Case
UStateTreeComponentSchema
Actor + BrainComponentGeneral actor logic
UStateTreeAIComponentSchema
Above +
AIControllerClass
AI behavior
UMassStateTreeSchema
Mass entity contextMass Entity processing
UStateTreeComponentSchema
exposes
ContextActorClass
(
TSubclassOf<AActor>
) so the editor knows which components are available for property binding.
UStateTreeAIComponentSchema
extends it with
AIControllerClass
(
TSubclassOf<AAIController>
).
Schemas定义了State Tree可访问的上下文数据,限制了有效的任务和条件。这能在编辑时而非运行时避免创作错误。
Schema提供的上下文用例
UStateTreeComponentSchema
Actor + BrainComponent通用Actor逻辑
UStateTreeAIComponentSchema
上述内容 +
AIControllerClass
AI行为
UMassStateTreeSchema
Mass实体上下文Mass Entity处理
UStateTreeComponentSchema
暴露了
ContextActorClass
TSubclassOf<AActor>
),以便编辑器知道哪些组件可用于属性绑定。
UStateTreeAIComponentSchema
在此基础上扩展了
AIControllerClass
TSubclassOf<AAIController>
)。

Custom Schemas

自定义Schemas

Subclass
UStateTreeSchema
for project-specific trees:
cpp
UCLASS()
class UMyGameSchema : public UStateTreeSchema
{
    GENERATED_BODY()
public:
    virtual bool IsStructAllowed(const UScriptStruct* InStruct) const override;
    virtual bool IsExternalItemAllowed(const UStruct& InStruct) const override;
    virtual TConstArrayView<FStateTreeExternalDataDesc> GetContextDataDescs() const override;

#if WITH_EDITOR
    virtual bool AllowEvaluators() const override { return true; }
    virtual bool AllowMultipleTasks() const override { return true; }
    virtual bool AllowGlobalParameters() const override { return true; }
#endif // WITH_EDITOR
};
Override
GetContextDataDescs()
to declare context objects (actor refs, subsystems). The editor uses this to validate property bindings.

继承
UStateTreeSchema
以创建项目专属的状态树:
cpp
UCLASS()
class UMyGameSchema : public UStateTreeSchema
{
    GENERATED_BODY()
public:
    virtual bool IsStructAllowed(const UScriptStruct* InStruct) const override;
    virtual bool IsExternalItemAllowed(const UStruct& InStruct) const override;
    virtual TConstArrayView<FStateTreeExternalDataDesc> GetContextDataDescs() const override;

#if WITH_EDITOR
    virtual bool AllowEvaluators() const override { return true; }
    virtual bool AllowMultipleTasks() const override { return true; }
    virtual bool AllowGlobalParameters() const override { return true; }
#endif // WITH_EDITOR
};
重写
GetContextDataDescs()
以声明上下文对象(Actor引用、子系统)。编辑器会用此信息验证属性绑定。

Tasks

任务(Tasks)

Tasks are the primary work units in a state. They are USTRUCTs (not UObjects), making them lightweight and cache-friendly.
任务是状态中的主要工作单元。它们是USTRUCT(而非UObject),因此轻量且易于缓存。

FStateTreeTaskBase API

FStateTreeTaskBase API

Key virtuals (all
const
— tasks are immutable at runtime):
VirtualReturnsCalled When
EnterState(Context, Transition)
EStateTreeRunStatus
(default: Running)
State becomes active
ExitState(Context, Transition)
void
State is exited
Tick(Context, DeltaTime)
EStateTreeRunStatus
(default: Running)
Each frame (if
bShouldCallTick
)
StateCompleted(Context, Status, CompletedStates)
void
Child state completes (REVERSE order)
TriggerTransitions(Context)
void
Only if
bShouldAffectTransitions
关键虚函数(均为
const
——任务在运行时不可变):
虚函数返回值调用时机
EnterState(Context, Transition)
EStateTreeRunStatus
(默认:Running)
状态激活时
ExitState(Context, Transition)
void
状态退出时
Tick(Context, DeltaTime)
EStateTreeRunStatus
(默认:Running)
每帧(若
bShouldCallTick
为true)
StateCompleted(Context, Status, CompletedStates)
void
子状态完成时(逆序
TriggerTransitions(Context)
void
仅当
bShouldAffectTransitions
为true时

Behavioral Flags

行为标志

FlagDefaultPurpose
bShouldStateChangeOnReselect
true
Exit+Enter when transitioning to same state
bShouldCallTick
true
Enable per-frame Tick calls
bShouldCallTickOnlyOnEvents
false
Tick only when events are pending
bShouldCopyBoundPropertiesOnTick
true
Refresh property bindings each tick
bShouldAffectTransitions
false
Enable
TriggerTransitions
calls
Set
bShouldCallTick = false
for fire-and-forget tasks that only need
EnterState
/
ExitState
.
标志默认值用途
bShouldStateChangeOnReselect
true
转换到相同状态时执行Exit+Enter
bShouldCallTick
true
启用每帧Tick调用
bShouldCallTickOnlyOnEvents
false
仅当有事件待处理时执行Tick
bShouldCopyBoundPropertiesOnTick
true
每帧刷新属性绑定
bShouldAffectTransitions
false
启用
TriggerTransitions
调用
对于仅需
EnterState
/
ExitState
的一次性任务,设置
bShouldCallTick = false

Instance Data Pattern

实例数据模式

Tasks are
const
at runtime — mutable per-instance state lives in a separate struct via the
typedef FInstanceDataType
pattern:
cpp
USTRUCT()
struct FMyTaskInstanceData
{
    GENERATED_BODY()
    float ElapsedTime = 0.f;
};

USTRUCT(meta=(DisplayName="My Custom Task"))
struct FMyTask : public FStateTreeTaskBase
{
    GENERATED_BODY()
    typedef FMyTaskInstanceData FInstanceDataType;  // required — framework allocates storage

    virtual EStateTreeRunStatus EnterState(FStateTreeExecutionContext& Context,
        const FStateTreeTransitionResult& Transition) const override
    {
        FInstanceDataType& Data = Context.GetInstanceData(*this);
        Data.ElapsedTime = 0.f;
        return EStateTreeRunStatus::Running;
    }

    virtual EStateTreeRunStatus Tick(FStateTreeExecutionContext& Context,
        float DeltaTime) const override
    {
        FInstanceDataType& Data = Context.GetInstanceData(*this);
        Data.ElapsedTime += DeltaTime;
        return Data.ElapsedTime >= Duration
            ? EStateTreeRunStatus::Succeeded : EStateTreeRunStatus::Running;
    }

    UPROPERTY(EditAnywhere, Category = "Parameter")
    float Duration = 2.0f;
};
See
references/state-tree-patterns.md
for complete task, condition, and evaluator templates.
任务在运行时是
const
的——每个实例的可变状态通过
typedef FInstanceDataType
模式存储在单独的结构体中:
cpp
USTRUCT()
struct FMyTaskInstanceData
{
    GENERATED_BODY()
    float ElapsedTime = 0.f;
};

USTRUCT(meta=(DisplayName="My Custom Task"))
struct FMyTask : public FStateTreeTaskBase
{
    GENERATED_BODY()
    typedef FMyTaskInstanceData FInstanceDataType;  // 必须——框架会分配存储

    virtual EStateTreeRunStatus EnterState(FStateTreeExecutionContext& Context,
        const FStateTreeTransitionResult& Transition) const override
    {
        FInstanceDataType& Data = Context.GetInstanceData(*this);
        Data.ElapsedTime = 0.f;
        return EStateTreeRunStatus::Running;
    }

    virtual EStateTreeRunStatus Tick(FStateTreeExecutionContext& Context,
        float DeltaTime) const override
    {
        FInstanceDataType& Data = Context.GetInstanceData(*this);
        Data.ElapsedTime += DeltaTime;
        return Data.ElapsedTime >= Duration
            ? EStateTreeRunStatus::Succeeded : EStateTreeRunStatus::Running;
    }

    UPROPERTY(EditAnywhere, Category = "Parameter")
    float Duration = 2.0f;
};
完整的任务、条件和评估器模板请参阅
references/state-tree-patterns.md

Multiple Tasks Per State

单状态多任务

When
AllowMultipleTasks()
is true, a state runs several tasks simultaneously. Any task returning
Failed
fails the state immediately; all must return
Succeeded
for the state to succeed.

AllowMultipleTasks()
为true时,一个状态会同时运行多个任务。任何任务返回
Failed
会立即导致状态失败;所有任务都返回
Succeeded
状态才会成功。

Conditions

条件(Conditions)

Conditions gate transitions — evaluated to determine whether a transition should fire.
cpp
USTRUCT(meta=(Hidden))
struct FStateTreeConditionBase : public FStateTreeNodeBase
{
    virtual bool TestCondition(FStateTreeExecutionContext& Context) const;  // default: false
    EStateTreeExpressionOperand Operand = EStateTreeExpressionOperand::And;
    int8 DeltaIndent = 0;  // indent level for logical grouping
    EStateTreeConditionEvaluationMode EvaluationMode = EStateTreeConditionEvaluationMode::Evaluated;
};
Operands:
And
(both must be true),
Or
(either),
Copy
(hidden/internal).
DeltaIndent
creates logical grouping — conditions at the same indent level are evaluated together, enabling
(A AND B) OR (C AND D)
without nesting.
Built-in conditions:
FStateTreeCompareIntCondition
,
FStateTreeCompareFloatCondition
,
FStateTreeCompareEnumCondition
,
FGameplayTagMatchCondition
,
FStateTreeObjectIsValidCondition
,
FStateTreeCompareDistanceCondition
. Bind inputs via property bindings.

条件是状态转换的前置门限——通过评估来确定是否触发转换。
cpp
USTRUCT(meta=(Hidden))
struct FStateTreeConditionBase : public FStateTreeNodeBase
{
    virtual bool TestCondition(FStateTreeExecutionContext& Context) const;  // 默认:false
    EStateTreeExpressionOperand Operand = EStateTreeExpressionOperand::And;
    int8 DeltaIndent = 0;  // 逻辑分组的缩进级别
    EStateTreeConditionEvaluationMode EvaluationMode = EStateTreeConditionEvaluationMode::Evaluated;
};
操作符:
And
(必须全部为true)、
Or
(任一为true)、
Copy
(隐藏/内部)。
DeltaIndent
用于创建逻辑分组——相同缩进级别的条件会被一起评估,无需嵌套即可实现
(A AND B) OR (C AND D)
的逻辑。
内置条件:
FStateTreeCompareIntCondition
FStateTreeCompareFloatCondition
FStateTreeCompareEnumCondition
FGameplayTagMatchCondition
FStateTreeObjectIsValidCondition
FStateTreeCompareDistanceCondition
。通过属性绑定输入。

Evaluators

评估器(Evaluators)

Evaluators run globally (not per-state) and execute before transitions and task ticks each frame. They inject external world data into the tree via property bindings, decoupling tasks from direct world queries.
cpp
USTRUCT(meta=(Hidden))
struct FStateTreeEvaluatorBase : public FStateTreeNodeBase
{
    virtual void TreeStart(FStateTreeExecutionContext& Context) const;
    virtual void TreeStop(FStateTreeExecutionContext& Context) const;
    virtual void Tick(FStateTreeExecutionContext& Context, float DeltaTime) const;
    // Note: DeltaTime is 0 during preselection
};
Evaluators use the same
FInstanceDataType
typedef pattern as tasks. Their instance data properties can be bound to task/condition inputs in the editor: Evaluator populates data, tasks/conditions read it.
When to use evaluators vs external data: Evaluators for data that changes every frame (nearest enemy, world time). External data handles for stable references (owning actor, subsystem).

评估器全局运行(而非按状态),并且在每帧的转换和任务Tick之前执行。它们通过属性绑定将外部世界数据注入树中,使任务无需直接查询世界。
cpp
USTRUCT(meta=(Hidden))
struct FStateTreeEvaluatorBase : public FStateTreeNodeBase
{
    virtual void TreeStart(FStateTreeExecutionContext& Context) const;
    virtual void TreeStop(FStateTreeExecutionContext& Context) const;
    virtual void Tick(FStateTreeExecutionContext& Context, float DeltaTime) const;
    // 注意:预选期间DeltaTime为0
};
评估器使用与任务相同的
FInstanceDataType
typedef模式。它们的实例数据属性可在编辑器中绑定到任务/条件的输入:评估器填充数据,任务/条件读取数据。
何时使用评估器vs外部数据: 评估器适用于每帧变化的数据(最近的敌人、世界时间)。外部数据用于稳定的引用(所属Actor、子系统)。

Transitions

转换(Transitions)

Transitions define how and when states change. Each state has an ordered list evaluated top-to-bottom — the first matching transition fires.
转换定义了状态如何以及何时变化。每个状态有一个有序列表,从上到下评估——第一个匹配的转换会触发。

Trigger Types

触发类型

EStateTreeTransitionTrigger
is a bitmask (
ENUM_CLASS_FLAGS
, supports bitwise OR):
TriggerValueFires When
OnStateSucceeded
1Active state returns Succeeded
OnStateFailed
2Active state returns Failed
OnStateCompleted
3Either Succeeded or Failed (1|2)
OnTick
4Every frame (gate with conditions)
OnEvent
8Matching event in the queue
OnDelegate
16Bound delegate fires
EStateTreeTransitionTrigger
是一个位掩码(
ENUM_CLASS_FLAGS
,支持按位或):
触发类型触发时机
OnStateSucceeded
1激活状态返回Succeeded时
OnStateFailed
2激活状态返回Failed时
OnStateCompleted
3状态返回Succeeded或Failed时(1|2)
OnTick
4每帧(需配合条件作为门限)
OnEvent
8队列中有匹配事件时
OnDelegate
16绑定的委托触发时

Priorities and Properties

优先级和属性

EStateTreeTransitionPriority
:
Low
,
Normal
,
Medium
,
High
,
Critical
. Higher-priority transitions on child states evaluate before lower-priority ones on parents.
PropertyDefaultPurpose
bConsumeEventOnSelect
true
Remove event from queue when transition fires
bTransitionEnabled
true
Disable without removing
bReactivateTargetState
false
Force Exit+Enter even if target is current state
Targets: GotoState (specific named state), NextState (next sibling), Succeeded/Failed (complete parent with that status), or tree-root Succeeded/Failed to complete the entire tree.

EStateTreeTransitionPriority
Low
Normal
Medium
High
Critical
。子状态上的高优先级转换会先于父状态上的低优先级转换评估。
属性默认值用途
bConsumeEventOnSelect
true
转换触发时从队列中移除事件
bTransitionEnabled
true
禁用转换但不删除
bReactivateTargetState
false
即使目标是当前状态,也强制执行Exit+Enter
目标: GotoState(指定命名状态)、NextState(下一个兄弟状态)、Succeeded/Failed(以该状态完成父状态),或者树根的Succeeded/Failed以完成整个树。

State Types and Selection

状态类型与选择

State Types

状态类型

TypePurpose
State
Normal state with tasks, conditions, transitions
Group
Container for child states — no tasks of its own
Linked
References another state within the same tree
LinkedAsset
References a state in a different
UStateTree
asset
Subtree
Embeds another
UStateTree
as a child
LinkedAsset
is useful for sharing common behavior patterns (patrol, investigate, flee) across AI archetypes.
类型用途
State
带有任务、条件、转换的普通状态
Group
子状态容器——自身无任务
Linked
引用同一树中的另一个状态
LinkedAsset
引用另一个
UStateTree
资产中的状态
Subtree
将另一个
UStateTree
作为子树嵌入
LinkedAsset
适用于在AI原型之间共享通用行为模式(巡逻、调查、逃跑)。

Selection Behavior

选择行为

EStateTreeStateSelectionBehavior
controls how child states are chosen on entry:
BehaviorEffect
TryEnterState
Enter this state directly
TrySelectChildrenInOrder
Try children top-to-bottom, first valid wins
TrySelectChildrenAtRandom
Random child selection
TrySelectChildrenWithHighestUtility
Utility-based selection (highest score)
TrySelectChildrenAtRandomWeightedByUtility
Weighted random by utility score
TryFollowTransitions
Follow transition chain
FStateTreeActiveStates::MaxStates = 8
— maximum depth of active state hierarchy. Stay within this limit.

EStateTreeStateSelectionBehavior
控制进入时如何选择子状态:
行为效果
TryEnterState
直接进入此状态
TrySelectChildrenInOrder
从上到下尝试子状态,第一个有效的状态胜出
TrySelectChildrenAtRandom
随机选择子状态
TrySelectChildrenWithHighestUtility
基于效用值选择(最高得分)
TrySelectChildrenAtRandomWeightedByUtility
按效用值加权随机选择
TryFollowTransitions
遵循转换链
FStateTreeActiveStates::MaxStates = 8
——激活状态层次结构的最大深度。请保持在此限制内。

Events

事件

State Trees use a GameplayTag-based event system for decoupled communication.
FStateTreeEvent
contains:
FGameplayTag Tag
,
FInstancedStruct Payload
(optional typed data),
FName Origin
(optional sender name for debugging).
cpp
// From outside via UStateTreeComponent
TreeComp->SendStateTreeEvent(FGameplayTag::RequestGameplayTag("AI.Alert"));

// With payload
FMyAlertData AlertData;
AlertData.ThreatLevel = 5;
TreeComp->SendStateTreeEvent(
    FGameplayTag::RequestGameplayTag("AI.Alert"),
    FConstStructView::Make(AlertData), TEXT("PerceptionSystem"));

// From inside a task via execution context
Context.SendEvent(Tag, FConstStructView::Make(ResultData), TEXT("MyTask"));
FStateTreeEventQueue
holds up to
MaxActiveEvents = 64
events per tick. Events are processed during transition evaluation. Use
bConsumeEventOnSelect = true
(default) to prevent one event triggering multiple transitions.

State Trees使用基于GameplayTag的事件系统进行解耦通信。
FStateTreeEvent
包含:
FGameplayTag Tag
FInstancedStruct Payload
(可选的类型化数据)、
FName Origin
(可选的发送者名称,用于调试)。
cpp
// 通过UStateTreeComponent从外部发送
TreeComp->SendStateTreeEvent(FGameplayTag::RequestGameplayTag("AI.Alert"));

// 带负载的事件
FMyAlertData AlertData;
AlertData.ThreatLevel = 5;
TreeComp->SendStateTreeEvent(
    FGameplayTag::RequestGameplayTag("AI.Alert"),
    FConstStructView::Make(AlertData), TEXT("PerceptionSystem"));

// 通过执行上下文从任务内部发送
Context.SendEvent(Tag, FConstStructView::Make(ResultData), TEXT("MyTask"));
FStateTreeEventQueue
每帧最多容纳
MaxActiveEvents = 64
个事件。事件在转换评估期间处理。默认
bConsumeEventOnSelect = true
,可防止一个事件触发多个转换。

External Data

外部数据

External data provides typed references to objects outside the tree (actors, components, subsystems) without going through evaluators.
cpp
// Declare handles in your task/condition/evaluator struct
TStateTreeExternalDataHandle<FMyActorContext, EStateTreeExternalDataRequirement::Required> ActorHandle;
TStateTreeExternalDataHandle<FMySubsystemContext, EStateTreeExternalDataRequirement::Optional> SubsystemHandle;

// Link in the Link override
virtual bool Link(FStateTreeLinker& Linker) override
{
    Linker.LinkExternalData(ActorHandle);
    Linker.LinkExternalData(SubsystemHandle);
    return true;
}

// Access at runtime
auto& ActorCtx = Context.GetExternalData(ActorHandle);       // Required — reference
auto* SubsystemCtx = Context.GetExternalDataPtr(SubsystemHandle);  // Optional — pointer
The schema's
CollectExternalData
populates these handles at tree start, validating at link time rather than runtime.

外部数据提供对树外对象(Actor、组件、子系统)的类型化引用,无需通过评估器。
cpp
// 在任务/条件/评估器结构体中声明句柄
TStateTreeExternalDataHandle<FMyActorContext, EStateTreeExternalDataRequirement::Required> ActorHandle;
TStateTreeExternalDataHandle<FMySubsystemContext, EStateTreeExternalDataRequirement::Optional> SubsystemHandle;

// 在Link重写中关联
virtual bool Link(FStateTreeLinker& Linker) override
{
    Linker.LinkExternalData(ActorHandle);
    Linker.LinkExternalData(SubsystemHandle);
    return true;
}

// 运行时访问
auto& ActorCtx = Context.GetExternalData(ActorHandle);       // 必填——引用
auto* SubsystemCtx = Context.GetExternalDataPtr(SubsystemHandle);  // 可选——指针
Schema的
CollectExternalData
会在树启动时填充这些句柄,并在关联时而非运行时进行验证。

UStateTreeComponent

UStateTreeComponent

UStateTreeComponent
extends
UBrainComponent
and manages the full tree lifecycle on an actor.
cpp
void SetStateTree(UStateTree* NewStateTree);
void SetStateTreeReference(FStateTreeReference NewStateTreeRef);
void SendStateTreeEvent(const FStateTreeEvent& Event);
void SendStateTreeEvent(FGameplayTag Tag, FConstStructView Payload, FName Origin);
EStateTreeRunStatus GetStateTreeRunStatus() const;
// Delegate — fires when run status changes
FStateTreeRunStatusChanged OnStateTreeRunStatusChanged;  // BlueprintAssignable
bool bStartLogicAutomatically = true;  // EditAnywhere
UStateTreeComponent
继承自
UBrainComponent
,负责管理Actor上的完整树生命周期。
cpp
void SetStateTree(UStateTree* NewStateTree);
void SetStateTreeReference(FStateTreeReference NewStateTreeRef);
void SendStateTreeEvent(const FStateTreeEvent& Event);
void SendStateTreeEvent(FGameplayTag Tag, FConstStructView Payload, FName Origin);
EStateTreeRunStatus GetStateTreeRunStatus() const;
// 委托——运行状态变化时触发
FStateTreeRunStatusChanged OnStateTreeRunStatusChanged;  // BlueprintAssignable
bool bStartLogicAutomatically = true;  // EditAnywhere

FStateTreeReference

FStateTreeReference

FStateTreeReference
wraps a
UStateTree*
with parameter overrides:
cpp
FStateTreeReference TreeRef;
TreeRef.SetStateTree(MyStateTreeAsset);
TreeRef.SyncParameters();
TreeRef.GetParameters().SetValueFloat(TEXT("AggroRange"), 1500.f);
FStateTreeReferenceOverrides
swaps tree references at runtime by tag:
cpp
Overrides.AddOverride(Tag_CombatVariant, CombatTreeRef);
Overrides.RemoveOverride(Tag_CombatVariant);
Subclass
UStateTreeComponent
to customize context via
SetContextRequirements(FStateTreeExecutionContext&, bool bLogErrors)
and
CollectExternalData(...)
.

FStateTreeReference
包装了
UStateTree*
并支持参数覆盖:
cpp
FStateTreeReference TreeRef;
TreeRef.SetStateTree(MyStateTreeAsset);
TreeRef.SyncParameters();
TreeRef.GetParameters().SetValueFloat(TEXT("AggroRange"), 1500.f);
FStateTreeReferenceOverrides
可通过标签在运行时切换树引用:
cpp
Overrides.AddOverride(Tag_CombatVariant, CombatTreeRef);
Overrides.RemoveOverride(Tag_CombatVariant);
继承
UStateTreeComponent
可通过
SetContextRequirements(FStateTreeExecutionContext&, bool bLogErrors)
CollectExternalData(...)
自定义上下文。

AI Integration

AI集成

UStateTreeAIComponentSchema
adds
AIControllerClass
to the component schema, making the AI controller available as context data for property bindings.
cpp
AMyAIController::AMyAIController()
{
    StateTreeComp = CreateDefaultSubobject<UStateTreeComponent>(TEXT("StateTree"));
    StateTreeComp->bStartLogicAutomatically = true;
}
Assign the
UStateTree
asset in the controller defaults. Set the schema's
ContextActorClass
to your Pawn class so the editor can bind to its components.
UStateTreeAIComponentSchema
在组件Schema中添加了
AIControllerClass
,使AI控制器可作为上下文数据用于属性绑定。
cpp
AMyAIController::AMyAIController()
{
    StateTreeComp = CreateDefaultSubobject<UStateTreeComponent>(TEXT("StateTree"));
    StateTreeComp->bStartLogicAutomatically = true;
}
在控制器默认设置中分配
UStateTree
资产。将Schema的
ContextActorClass
设置为你的Pawn类,以便编辑器可绑定到其组件。

State Tree vs Behavior Tree

State Tree vs 行为树

AspectState TreeBehavior Tree
StructureHierarchical FSM with transitionsTree of composites, decorators, tasks
Data flowEvaluators + property bindings (typed)Blackboard (string-keyed, loosely typed)
ConditionsFirst-class on transitionsDecorators on tree nodes
Mass EntityNative via
UMassStateTreeSchema
No Mass support
Best forData-driven FSMs, Mass entities, flat logicDeep decision hierarchies, complex aborts
Prefer State Trees for new AI needing Mass Entity scaling or data-driven transitions. Keep Behavior Trees for deeply nested decision logic with complex abort/decorator patterns.

方面State Tree行为树
结构带有转换的分层FSM由组合节点、装饰器、任务组成的树
数据流评估器 + 属性绑定(类型化)黑板(字符串键,弱类型)
条件转换的一等公民树节点上的装饰器
Mass Entity通过
UMassStateTreeSchema
原生支持
无Mass支持
最佳适用场景数据驱动FSM、Mass实体、扁平逻辑深度决策层次、复杂中断逻辑
对于需要Mass Entity扩展或数据驱动转换的新AI系统,优先选择State Trees。对于带有复杂中断/装饰器模式的深度嵌套决策逻辑,继续使用行为树。

Mass Entity Integration

Mass Entity集成

State Trees integrate natively with Mass Entity for processing thousands of entities. See
references/state-tree-mass-integration.md
for complete setup.
Key concepts:
  • UMassStateTreeSchema
    constrains trees to Mass-compatible node types (
    FMassStateTreeTaskBase
    , etc.)
  • UMassStateTreeSubsystem
    manages pooled instance data (
    AllocateInstanceData
    /
    FreeInstanceData
    )
  • UMassStateTreeProcessor
    evaluates trees per entity each frame
  • FMassStateTreeExecutionContext
    wraps execution context with
    SetEntity
    /
    GetEntity
  • Mass-specific tasks override
    GetDependencies(UE::MassBehavior::FStateTreeDependencyBuilder&)
    to declare fragment read/write requirements
For Mass Entity architecture details, see
ue-mass-entity
.

State Trees与Mass Entity原生集成,可处理数千个实体。完整设置请参阅
references/state-tree-mass-integration.md
核心概念:
  • UMassStateTreeSchema
    将树限制为Mass兼容的节点类型(
    FMassStateTreeTaskBase
    等)
  • UMassStateTreeSubsystem
    管理池化实例数据(
    AllocateInstanceData
    /
    FreeInstanceData
  • UMassStateTreeProcessor
    每帧评估每个实体的树
  • FMassStateTreeExecutionContext
    包装执行上下文,提供
    SetEntity
    /
    GetEntity
    方法
  • Mass专属任务重写
    GetDependencies(UE::MassBehavior::FStateTreeDependencyBuilder&)
    以声明片段的读写需求
有关Mass Entity架构的详细信息,请参阅
ue-mass-entity

Common Mistakes

常见错误

Persisting FStateTreeExecutionContext across frames:
cpp
// WRONG — context is per-tick, NOT persistent
FStateTreeExecutionContext* SavedContext;  // dangling after tick

// RIGHT — reconstruct each tick from persistent instance data
FStateTreeExecutionContext Context(Owner, *StateTree, InstanceData);
Context.Tick(DeltaTime);
Mutating task struct directly instead of using instance data:
cpp
// WRONG — task structs are const at runtime
virtual EStateTreeRunStatus Tick(...) const override {
    Timer += DeltaTime;  // compile error — 'this' is const
}

// RIGHT — use FInstanceDataType typedef
typedef FMyInstanceData FInstanceDataType;
virtual EStateTreeRunStatus Tick(...) const override {
    auto& Data = Context.GetInstanceData(*this);
    Data.Timer += DeltaTime;
}
Conditions with side effects:
TestCondition
may be called multiple times per frame during transition evaluation. Never modify state in conditions — they must be pure functions.
Evaluators doing heavy work every tick: Evaluators run every frame before transitions. Cache results in instance data and only refresh when inputs change.
Exceeding MaxStates depth:
FStateTreeActiveStates::MaxStates = 8
. Deeply nested hierarchies silently fail. Flatten with linked states or subtrees.
Forgetting to link external data: Unlinked Required handles assert at runtime; Optional handles silently return nullptr. Always link all declared handles in
Link()
.
Not consuming events: With
bConsumeEventOnSelect = false
, the same event can trigger multiple transitions in one frame. Leave default
true
unless broadcast behavior is intended.

跨帧持久化FStateTreeExecutionContext:
cpp
// 错误——上下文是每帧的,**不持久化**
FStateTreeExecutionContext* SavedContext;  // Tick后会悬空

// 正确——每帧从持久化实例数据重建
FStateTreeExecutionContext Context(Owner, *StateTree, InstanceData);
Context.Tick(DeltaTime);
直接修改任务结构体而非使用实例数据:
cpp
// 错误——任务结构体在运行时是const的
virtual EStateTreeRunStatus Tick(...) const override {
    Timer += DeltaTime;  // 编译错误——'this'是const
}

// 正确——使用FInstanceDataType typedef
typedef FMyInstanceData FInstanceDataType;
virtual EStateTreeRunStatus Tick(...) const override {
    auto& Data = Context.GetInstanceData(*this);
    Data.Timer += DeltaTime;
}
条件带有副作用:
TestCondition
在转换评估期间每帧可能被调用多次。绝不要在条件中修改状态——它们必须是纯函数。
评估器每帧执行繁重工作: 评估器在转换前每帧运行。将结果缓存到实例数据中,仅在输入变化时刷新。
超出MaxStates深度:
FStateTreeActiveStates::MaxStates = 8
。深度嵌套的层次结构会静默失败。使用链接状态或子树来扁平化结构。
忘记关联外部数据: 未关联的必填句柄会在运行时断言;可选句柄会静默返回nullptr。务必在
Link()
中关联所有声明的句柄。
未消费事件:
bConsumeEventOnSelect = false
,同一事件可能在一帧内触发多个转换。除非需要广播行为,否则保留默认的
true

Related Skills

相关技能

  • ue-ai-navigation
    — Behavior tree patterns, AI controller setup, perception system
  • ue-mass-entity
    — Mass Entity architecture, processors, fragments, traits
  • ue-gameplay-abilities
    — Ability-driven state transitions, GAS integration
  • ue-gameplay-framework
    — Game state machines, controller/pawn lifecycle
  • ue-actor-component-architecture
    — Component setup for
    UStateTreeComponent
  • ue-cpp-foundations
    — USTRUCT patterns, delegates, subsystem access
  • ue-ai-navigation
    —— 行为树模式、AI控制器设置、感知系统
  • ue-mass-entity
    —— Mass Entity架构、处理器、片段、特征
  • ue-gameplay-abilities
    —— 基于能力的状态转换、GAS集成
  • ue-gameplay-framework
    —— 游戏状态机、控制器/Pawn生命周期
  • ue-actor-component-architecture
    ——
    UStateTreeComponent
    的组件设置
  • ue-cpp-foundations
    —— USTRUCT模式、委托、子系统访问