ue-state-trees
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUE 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 to determine:
.agents/ue-project-context.md- Whether and
StateTreeModuleplugins are enabledGameplayStateTreeModule - If Mass Entity integration is needed (,
MassEntityplugins)MassAIBehavior - 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:
- What is the use case? (AI behavior, game logic, UI state, entity processing)
- What scale? (single actor with vs thousands of Mass entities)
UStateTreeComponent - How complex? (simple linear FSM vs hierarchical states with linked subtrees)
- Are there existing behavior trees to migrate from?
- What external data do tasks need? (actor references, subsystems, world state)
在实现前,请明确:
- 用例是什么?(AI行为、游戏逻辑、UI状态、实体处理)
- 规模如何?(使用的单个Actor vs 数千个Mass实体)
UStateTreeComponent - 复杂度如何?(简单线性FSM vs 带有链接子树的分层状态)
- 是否有需要迁移的现有行为树?
- 任务需要哪些外部数据?(Actor引用、子系统、世界状态)
StateTree Architecture
StateTree架构
A State Tree is a hierarchical finite state machine authored as a data asset:
UStateTreeUStateTree (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 inputsRuntime 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:
| Class | Role |
|---|---|
| Data asset — call |
| Per-tick context — constructed each frame, NOT persisted |
| Persistent runtime state — survives across ticks |
| Actor component that manages tree lifecycle |
| |
Build.cs modules: ,
StateTreeModuleGameplayStateTreeModuleThe 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 () from stateless execution logic, making State Trees safe for parallel evaluation in Mass Entity scenarios.
FStateTreeInstanceDataState Tree是一种分层有限状态机,以数据资产的形式创建:
UStateTreeUStateTree (UDataAsset)
├── UStateTreeSchema ← 定义允许的上下文/外部数据
├── States[] ← 分层状态树
│ ├── Tasks[] ← 状态激活时执行的操作
│ ├── Transitions[] ← 离开此状态的规则
│ └── Conditions[] ← 状态转换的前置条件
├── Evaluators[] ← 全局数据提供器(在转换前执行Tick)
└── Parameters ← FInstancedPropertyBag默认输入每帧运行流程: 1) Evaluators执行Tick,2) 从激活的叶子状态向上到根状态检查转换规则,3) 如果触发转换:先执行旧任务的ExitState,再执行新任务的EnterState,4) 激活的任务执行Tick。
核心类:
| 类 | 作用 |
|---|---|
| 数据资产——执行前需调用 |
| 每帧上下文——每帧构造,不持久化 |
| 持久化运行时状态——跨帧保留 |
| 管理树生命周期的Actor组件 |
| 运行状态: |
Build.cs模块:,
StateTreeModuleGameplayStateTreeModule执行上下文从持久化实例数据中每帧构造:
cpp
FStateTreeInstanceData InstanceData; // 跨帧持久化
// 每帧:
FStateTreeExecutionContext Context(Owner, *StateTree, InstanceData);
Context.Tick(DeltaTime);这种设计将可变状态()与无状态执行逻辑分离,使State Trees在Mass Entity场景中可安全地并行评估。
FStateTreeInstanceDataSchema 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.
| Schema | Context Provided | Use Case |
|---|---|---|
| Actor + BrainComponent | General actor logic |
| Above + | AI behavior |
| Mass entity context | Mass Entity processing |
UStateTreeComponentSchemaContextActorClassTSubclassOf<AActor>UStateTreeAIComponentSchemaAIControllerClassTSubclassOf<AAIController>Schemas定义了State Tree可访问的上下文数据,限制了有效的任务和条件。这能在编辑时而非运行时避免创作错误。
| Schema | 提供的上下文 | 用例 |
|---|---|---|
| Actor + BrainComponent | 通用Actor逻辑 |
| 上述内容 + | AI行为 |
| Mass实体上下文 | Mass Entity处理 |
UStateTreeComponentSchemaContextActorClassTSubclassOf<AActor>UStateTreeAIComponentSchemaAIControllerClassTSubclassOf<AAIController>Custom Schemas
自定义Schemas
Subclass for project-specific trees:
UStateTreeSchemacpp
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 to declare context objects (actor refs, subsystems). The editor uses this to validate property bindings.
GetContextDataDescs()继承以创建项目专属的状态树:
UStateTreeSchemacpp
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
};重写以声明上下文对象(Actor引用、子系统)。编辑器会用此信息验证属性绑定。
GetContextDataDescs()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 — tasks are immutable at runtime):
const| Virtual | Returns | Called When |
|---|---|---|
| | State becomes active |
| | State is exited |
| | Each frame (if |
| | Child state completes (REVERSE order) |
| | Only if |
关键虚函数(均为——任务在运行时不可变):
const| 虚函数 | 返回值 | 调用时机 |
|---|---|---|
| | 状态激活时 |
| | 状态退出时 |
| | 每帧(若 |
| | 子状态完成时(逆序) |
| | 仅当 |
Behavioral Flags
行为标志
| Flag | Default | Purpose |
|---|---|---|
| | Exit+Enter when transitioning to same state |
| | Enable per-frame Tick calls |
| | Tick only when events are pending |
| | Refresh property bindings each tick |
| | Enable |
Set for fire-and-forget tasks that only need /.
bShouldCallTick = falseEnterStateExitState| 标志 | 默认值 | 用途 |
|---|---|---|
| | 转换到相同状态时执行Exit+Enter |
| | 启用每帧Tick调用 |
| | 仅当有事件待处理时执行Tick |
| | 每帧刷新属性绑定 |
| | 启用 |
对于仅需/的一次性任务,设置。
EnterStateExitStatebShouldCallTick = falseInstance Data Pattern
实例数据模式
Tasks are at runtime — mutable per-instance state lives in a separate struct via the pattern:
consttypedef FInstanceDataTypecpp
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 for complete task, condition, and evaluator templates.
references/state-tree-patterns.md任务在运行时是的——每个实例的可变状态通过模式存储在单独的结构体中:
consttypedef FInstanceDataTypecpp
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.mdMultiple Tasks Per State
单状态多任务
When is true, a state runs several tasks simultaneously. Any task returning fails the state immediately; all must return for the state to succeed.
AllowMultipleTasks()FailedSucceeded当为true时,一个状态会同时运行多个任务。任何任务返回会立即导致状态失败;所有任务都返回状态才会成功。
AllowMultipleTasks()FailedSucceededConditions
条件(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: (both must be true), (either), (hidden/internal). creates logical grouping — conditions at the same indent level are evaluated together, enabling without nesting.
AndOrCopyDeltaIndent(A AND B) OR (C AND D)Built-in conditions: , , , , , . Bind inputs via property bindings.
FStateTreeCompareIntConditionFStateTreeCompareFloatConditionFStateTreeCompareEnumConditionFGameplayTagMatchConditionFStateTreeObjectIsValidConditionFStateTreeCompareDistanceCondition条件是状态转换的前置门限——通过评估来确定是否触发转换。
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;
};操作符: (必须全部为true)、(任一为true)、(隐藏/内部)。用于创建逻辑分组——相同缩进级别的条件会被一起评估,无需嵌套即可实现的逻辑。
AndOrCopyDeltaIndent(A AND B) OR (C AND D)内置条件: 、、、、、。通过属性绑定输入。
FStateTreeCompareIntConditionFStateTreeCompareFloatConditionFStateTreeCompareEnumConditionFGameplayTagMatchConditionFStateTreeObjectIsValidConditionFStateTreeCompareDistanceConditionEvaluators
评估器(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 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.
FInstanceDataTypeWhen 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
};评估器使用与任务相同的 typedef模式。它们的实例数据属性可在编辑器中绑定到任务/条件的输入:评估器填充数据,任务/条件读取数据。
FInstanceDataType何时使用评估器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
触发类型
EStateTreeTransitionTriggerENUM_CLASS_FLAGS| Trigger | Value | Fires When |
|---|---|---|
| 1 | Active state returns Succeeded |
| 2 | Active state returns Failed |
| 3 | Either Succeeded or Failed (1|2) |
| 4 | Every frame (gate with conditions) |
| 8 | Matching event in the queue |
| 16 | Bound delegate fires |
EStateTreeTransitionTriggerENUM_CLASS_FLAGS| 触发类型 | 值 | 触发时机 |
|---|---|---|
| 1 | 激活状态返回Succeeded时 |
| 2 | 激活状态返回Failed时 |
| 3 | 状态返回Succeeded或Failed时(1|2) |
| 4 | 每帧(需配合条件作为门限) |
| 8 | 队列中有匹配事件时 |
| 16 | 绑定的委托触发时 |
Priorities and Properties
优先级和属性
EStateTreeTransitionPriorityLowNormalMediumHighCritical| Property | Default | Purpose |
|---|---|---|
| | Remove event from queue when transition fires |
| | Disable without removing |
| | 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.
EStateTreeTransitionPriorityLowNormalMediumHighCritical| 属性 | 默认值 | 用途 |
|---|---|---|
| | 转换触发时从队列中移除事件 |
| | 禁用转换但不删除 |
| | 即使目标是当前状态,也强制执行Exit+Enter |
目标: GotoState(指定命名状态)、NextState(下一个兄弟状态)、Succeeded/Failed(以该状态完成父状态),或者树根的Succeeded/Failed以完成整个树。
State Types and Selection
状态类型与选择
State Types
状态类型
| Type | Purpose |
|---|---|
| Normal state with tasks, conditions, transitions |
| Container for child states — no tasks of its own |
| References another state within the same tree |
| References a state in a different |
| Embeds another |
LinkedAsset| 类型 | 用途 |
|---|---|
| 带有任务、条件、转换的普通状态 |
| 子状态容器——自身无任务 |
| 引用同一树中的另一个状态 |
| 引用另一个 |
| 将另一个 |
LinkedAssetSelection Behavior
选择行为
EStateTreeStateSelectionBehavior| Behavior | Effect |
|---|---|
| Enter this state directly |
| Try children top-to-bottom, first valid wins |
| Random child selection |
| Utility-based selection (highest score) |
| Weighted random by utility score |
| Follow transition chain |
FStateTreeActiveStates::MaxStates = 8EStateTreeStateSelectionBehavior| 行为 | 效果 |
|---|---|
| 直接进入此状态 |
| 从上到下尝试子状态,第一个有效的状态胜出 |
| 随机选择子状态 |
| 基于效用值选择(最高得分) |
| 按效用值加权随机选择 |
| 遵循转换链 |
FStateTreeActiveStates::MaxStates = 8Events
事件
State Trees use a GameplayTag-based event system for decoupled communication.
FStateTreeEventFGameplayTag TagFInstancedStruct PayloadFName Origincpp
// 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"));FStateTreeEventQueueMaxActiveEvents = 64bConsumeEventOnSelect = trueState Trees使用基于GameplayTag的事件系统进行解耦通信。
FStateTreeEventFGameplayTag TagFInstancedStruct PayloadFName Origincpp
// 通过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"));FStateTreeEventQueueMaxActiveEvents = 64bConsumeEventOnSelect = trueExternal 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 — pointerThe schema's populates these handles at tree start, validating at link time rather than runtime.
CollectExternalData外部数据提供对树外对象(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的会在树启动时填充这些句柄,并在关联时而非运行时进行验证。
CollectExternalDataUStateTreeComponent
UStateTreeComponent
UStateTreeComponentUBrainComponentcpp
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; // EditAnywhereUStateTreeComponentUBrainComponentcpp
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; // EditAnywhereFStateTreeReference
FStateTreeReference
FStateTreeReferenceUStateTree*cpp
FStateTreeReference TreeRef;
TreeRef.SetStateTree(MyStateTreeAsset);
TreeRef.SyncParameters();
TreeRef.GetParameters().SetValueFloat(TEXT("AggroRange"), 1500.f);FStateTreeReferenceOverridescpp
Overrides.AddOverride(Tag_CombatVariant, CombatTreeRef);
Overrides.RemoveOverride(Tag_CombatVariant);Subclass to customize context via and .
UStateTreeComponentSetContextRequirements(FStateTreeExecutionContext&, bool bLogErrors)CollectExternalData(...)FStateTreeReferenceUStateTree*cpp
FStateTreeReference TreeRef;
TreeRef.SetStateTree(MyStateTreeAsset);
TreeRef.SyncParameters();
TreeRef.GetParameters().SetValueFloat(TEXT("AggroRange"), 1500.f);FStateTreeReferenceOverridescpp
Overrides.AddOverride(Tag_CombatVariant, CombatTreeRef);
Overrides.RemoveOverride(Tag_CombatVariant);继承可通过和自定义上下文。
UStateTreeComponentSetContextRequirements(FStateTreeExecutionContext&, bool bLogErrors)CollectExternalData(...)AI Integration
AI集成
UStateTreeAIComponentSchemaAIControllerClasscpp
AMyAIController::AMyAIController()
{
StateTreeComp = CreateDefaultSubobject<UStateTreeComponent>(TEXT("StateTree"));
StateTreeComp->bStartLogicAutomatically = true;
}Assign the asset in the controller defaults. Set the schema's to your Pawn class so the editor can bind to its components.
UStateTreeContextActorClassUStateTreeAIComponentSchemaAIControllerClasscpp
AMyAIController::AMyAIController()
{
StateTreeComp = CreateDefaultSubobject<UStateTreeComponent>(TEXT("StateTree"));
StateTreeComp->bStartLogicAutomatically = true;
}在控制器默认设置中分配资产。将Schema的设置为你的Pawn类,以便编辑器可绑定到其组件。
UStateTreeContextActorClassState Tree vs Behavior Tree
State Tree vs 行为树
| Aspect | State Tree | Behavior Tree |
|---|---|---|
| Structure | Hierarchical FSM with transitions | Tree of composites, decorators, tasks |
| Data flow | Evaluators + property bindings (typed) | Blackboard (string-keyed, loosely typed) |
| Conditions | First-class on transitions | Decorators on tree nodes |
| Mass Entity | Native via | No Mass support |
| Best for | Data-driven FSMs, Mass entities, flat logic | Deep 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 | 通过 | 无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 for complete setup.
references/state-tree-mass-integration.mdKey concepts:
- constrains trees to Mass-compatible node types (
UMassStateTreeSchema, etc.)FMassStateTreeTaskBase - manages pooled instance data (
UMassStateTreeSubsystem/AllocateInstanceData)FreeInstanceData - evaluates trees per entity each frame
UMassStateTreeProcessor - wraps execution context with
FMassStateTreeExecutionContext/SetEntityGetEntity - Mass-specific tasks override to declare fragment read/write requirements
GetDependencies(UE::MassBehavior::FStateTreeDependencyBuilder&)
For Mass Entity architecture details, see .
ue-mass-entityState Trees与Mass Entity原生集成,可处理数千个实体。完整设置请参阅。
references/state-tree-mass-integration.md核心概念:
- 将树限制为Mass兼容的节点类型(
UMassStateTreeSchema等)FMassStateTreeTaskBase - 管理池化实例数据(
UMassStateTreeSubsystem/AllocateInstanceData)FreeInstanceData - 每帧评估每个实体的树
UMassStateTreeProcessor - 包装执行上下文,提供
FMassStateTreeExecutionContext/SetEntity方法GetEntity - Mass专属任务重写以声明片段的读写需求
GetDependencies(UE::MassBehavior::FStateTreeDependencyBuilder&)
有关Mass Entity架构的详细信息,请参阅。
ue-mass-entityCommon 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: may be called multiple times per frame during transition evaluation. Never modify state in conditions — they must be pure functions.
TestConditionEvaluators 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: . Deeply nested hierarchies silently fail. Flatten with linked states or subtrees.
FStateTreeActiveStates::MaxStates = 8Forgetting 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 , the same event can trigger multiple transitions in one frame. Leave default unless broadcast behavior is intended.
bConsumeEventOnSelect = falsetrue跨帧持久化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 = falsetrueRelated Skills
相关技能
- — Behavior tree patterns, AI controller setup, perception system
ue-ai-navigation - — Mass Entity architecture, processors, fragments, traits
ue-mass-entity - — Ability-driven state transitions, GAS integration
ue-gameplay-abilities - — Game state machines, controller/pawn lifecycle
ue-gameplay-framework - — Component setup for
ue-actor-component-architectureUStateTreeComponent - — USTRUCT patterns, delegates, subsystem access
ue-cpp-foundations
- —— 行为树模式、AI控制器设置、感知系统
ue-ai-navigation - —— Mass Entity架构、处理器、片段、特征
ue-mass-entity - —— 基于能力的状态转换、GAS集成
ue-gameplay-abilities - —— 游戏状态机、控制器/Pawn生命周期
ue-gameplay-framework - ——
ue-actor-component-architecture的组件设置UStateTreeComponent - —— USTRUCT模式、委托、子系统访问
ue-cpp-foundations