总览
StateTree 的 Binding 可以先理解成“接水管”:左边是水源,右边是水龙头。来源属性的值会被复制到目标属性。比如 GuardPerception.PlayerLocation 是来源,Move To.Destination 是目标。接好以后,Move To 每次执行时就知道要去哪。
新手最常见的问题不是“不会写 Task”,而是“Destination 为什么没有值”。十有八九是绑定没接、接反、类型不匹配、或者来源根本没更新。
绑定面板怎么看
绑定时先问三句话:
- 我要给哪个目标属性赋值?例如 Move To 的 Destination。
- 这个值从哪里来?例如 Evaluator 的 PlayerLocation。
- 什么时候复制?Enter、Tick、Exit,还是只初始化一次?
编辑器里目标通常在当前 Task/Condition 的 Details 里。来源可以来自 Context、Parameters、Evaluator、Global Task、State Parameter、其他 Task 输出、Transition Event 等。
守卫追击绑定
目标:Chase 状态里 Move To 玩家当前位置。
步骤:
- 在 Chase 状态添加
Move ToTask。 - 找到
Destination。 - 点击绑定按钮。
- 来源选择
GuardPerceptionEvaluator。 - 选择
PlayerLocation。 - 确认类型都是 Vector。
- 如果玩家会移动,确认 Task 或绑定会在 Tick 时更新。
如果你只在 Enter 时复制一次,守卫会冲向“进入 Chase 那一瞬间”的玩家位置,而不是持续追玩家。这不是 Move To 坏了,是绑定更新时机不符合需求。
输入和输出
有些属性是 Input,有些是 Output。Input 是喂给节点的数据,例如 Move To 的 Destination。Output 是节点执行后产出的数据,例如某个自定义 Task 算出的 NextPatrolPoint。绑定方向错了,编辑器可能不让你接,或者运行时值不变。
| 类型 | 例子 | 方向 |
|---|---|---|
| Input | MoveTo.Destination | 来源 -> 目标 |
| Parameter | AcceptableRadius | 参数 -> 目标 |
| Output | PickPatrolPoint.NextPoint | Task -> 后续来源 |
| Event Payload | NoiseLocation | Event -> Condition/Task |
源码依据
FStateTreeBindableStructDesc 记录可绑定结构的来源类型,EStateTreeBindableStructSource 包含 Context、Parameter、Evaluator、GlobalTask、StateParameter、Task、Condition、TransitionEvent、StateEvent 等。FStateTreePropertyPathBinding 表示一个属性路径绑定,包含 SourcePath、TargetPath、SourceDataHandle 和 bIsOutputBinding。FStateTreeTaskBase 里有 bShouldCopyBoundPropertiesOnTick、bShouldCopyBoundPropertiesOnExitState,说明绑定不是玄学,确实有拷贝时机。
架构分析
Binding 是 StateTree 的数据管线,不是临时变量连线。架构上应该让数据从“稳定来源”流向“执行节点”:Parameter、Context、Evaluator 是常见来源,Task 输入是常见目标。只有当某个 Task 明确产出结果时,才把它作为后续来源。这样树越大,数据流仍然能追踪。
使用案例
自定义 PickNextPatrolPoint Task 输出下一个巡逻点,然后 Patrol 的 Move To 使用它:
USTRUCT()
struct FPickPatrolPointInstanceData
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, Category="Output")
FVector NextPoint = FVector::ZeroVector;
};
编辑器连接:
- Idle 完成后进入 PickPatrolPoint 状态。
- PickPatrolPoint Task 设置
NextPoint。 - Transition 到 PatrolMove。
- PatrolMove 的 Move To Destination 绑定到
PickPatrolPoint.NextPoint。
项目落地
团队里建议给所有 Evaluator 输出加前缀或分组,例如 Perception.CanSeeTarget、Perception.TargetLocation、Patrol.NextPoint。绑定面板源很多时,命名清楚比写文档更有用。复杂树里,每个关键状态旁边写注释:这个状态的关键输入来自哪里。
常见坑
不要把 Vector 绑定到 Actor,除非节点明确支持 TargetActor。不要忘记 Tick 更新,追击移动目标时尤其常见。不要从一个只在某个状态激活的 Task 输出绑定到另一个长期状态,离开状态后数据可能不是你以为的生命周期。不要把所有数据都互相绑定成网,绑定太密会让树难调试。
源码路径索引
StateTreeModule/Public/StateTreePropertyBindings.hStateTreeModule/Public/StateTreePropertyRef.hStateTreeModule/Public/StateTreeTaskBase.hStateTreeModule/Public/StateTreeTypes.h