# Behavior Designer Pro v2.1.12 技术评估与使用手册 > **版本**: Behavior Designer Pro 2.1.12 > **作者**: Opsive > **架构范式**: ECS 调度引擎 + MonoBehaviour/DOTS 双模 Task 混合架构 > **Unity 要求**: 2022.3+ > **依赖**: `com.opsive.shared` 2.0.0、`com.opsive.graphdesigner` 2.0.0、`com.unity.burst` 1.8.17、`com.unity.entities` 1.3.8 > **许可**: Unity Asset Store EULA > **包路径**: `Packages/com.opsive.behaviordesigner/` > **官方文档**: https://opsive.com/support/documentation/behavior-designer-pro/ > **命名空间**: `BehaviorDesigner.Runtime`、`BehaviorDesigner.Runtime.Tasks` --- ## 目录 1. [概述与设计哲学](#1-概述与设计哲学) 2. [架构总览](#2-架构总览) 3. [核心组件](#3-核心组件) 4. [ECS/DOTS 集成架构](#4-ecsdots-集成架构) 5. [System Group 执行层级](#5-system-group-执行层级) 6. [核心 ECS 系统](#6-核心-ecs-系统) 7. [Task 系统架构](#7-task-系统架构) 8. [Composite 任务 (组合节点)](#8-composite-任务-组合节点) 9. [Decorator 任务 (装饰节点)](#9-decorator-任务-装饰节点) 10. [Action 任务 (行为节点)](#10-action-任务-行为节点) 11. [Conditional 任务 (条件节点)](#11-conditional-任务-条件节点) 12. [Event 系统 (事件节点)](#12-event-系统-事件节点) 13. [Conditional Abort 机制](#13-conditional-abort-机制) 14. [Subtree 系统](#14-subtree-系统) 15. [SharedVariable 系统](#15-sharedvariable-系统) 16. [序列化与持久化](#16-序列化与持久化) 17. [Editor 工具链](#17-editor-工具链) 18. [性能分析](#18-性能分析) 19. [与 BaseGames 架构集成方案](#19-与-basegames-架构集成方案) 20. [优缺点总结](#20-优缺点总结) 21. [总结与建议](#21-总结与建议) --- ## 1. 概述与设计哲学 ### 1.1 什么是 Behavior Designer Behavior Designer 是 Unity 生态中最成熟的**行为树 (Behavior Tree)** 插件之一。v2.x Pro 版本进行了重大架构升级: > **核心特性**:采用 **ECS 作为内部调度引擎**(树遍历、分支管理、条件中断均由 Burst 编译的 ECS System 驱动),同时提供 **MonoBehaviour Task** 和 **ECS Task** 两种编程模型。自定义业务逻辑通常使用传统 MonoBehaviour Task(`Task` 基类),可直接访问 `GameObject`、`Transform`、协程等 Unity 原生 API;而内置 Composite/Decorator 节点及高性能场景使用纯 ECS Task(`ECSTask` 基类),享受 Burst + Job 并行优化。两种 Task 可在同一棵行为树中混合使用。 行为树是 AI 决策的标准范式,通过树形结构组织: - **Composite** (组合) — 控制子节点执行顺序 (Sequence/Selector/Parallel) - **Decorator** (装饰) — 修饰子节点行为 (Inverter/Repeater/Cooldown) - **Action** (行为) — 执行具体操作 (移动/攻击/等待) - **Conditional** (条件) — 检查条件 (距离/Tag/碰撞) ### 1.2 v2.x vs v1.x 关键差异 | 维度 | v1.x (经典) | v2.x Pro (混合架构) | |------|------------|---------------------| | **运行时核心** | 纯 MonoBehaviour 驱动 | ECS World 调度 + MonoBehaviour/ECS 双模 Task | | **执行引擎** | 主线程递归遍历 | ECS SystemGroup 调度 + Burst 编译 (Composite/Decorator);MonoBehaviour Task 仍由 TaskObjectSystem 在主线程执行 | | **Task 数据** | C# 对象 (GC) | ECS Task → IBufferElementData (无 GC);MonoBehaviour Task → C# 对象 (堆分配) | | **并行能力** | 无 | ECS Task 可 IJobEntity 多树并行;MonoBehaviour Task 为主线程 | | **可视化编辑** | 内置窗口 | 基于 GraphDesigner 新编辑器 | | **Subtree** | ExternalBehaviorTree | Subtree ScriptableObject (Subgraph 属性) | | **Variable** | SharedVariable | SharedVariable + ECS 兼容 | | **序列化** | Unity 序列化 | Opsive 自定义序列化 | | **自定义 Task** | 继承 Task 基类 | 继承 Task (MonoBehaviour 模式) 或 ECSTask (DOTS 模式) | ### 1.3 核心设计原则 | 原则 | 说明 | |------|------| | **数据驱动** | 行为树资产独立于代码,策划可通过编辑器配置 | | **ECS 调度 + 双模 Task** | 核心树遍历由 ECS SystemGroup 驱动(Burst 编译),业务逻辑支持 MonoBehaviour Task 和 ECS Task 两种编程模型 | | **MonoBehaviour 友好** | 自定义 Task 继承 `Task` 基类即可访问 GameObject/Transform/协程等,无需 ECS 知识 | | **可组合** | Subtree 支持行为树模块化复用 | | **可中断** | Conditional Abort 实现实时条件重评估 | | **可扩展** | 自定义 Task 只需继承 `Action`/`Conditional` 基类 + 覆写 `OnUpdate()` | --- ## 2. 架构总览 ### 2.1 整体架构图 ``` ┌──────────────────────────────────────────────────────┐ │ Editor │ │ ┌──────────────────────────────────────────────────┐│ │ │ BehaviorMainWindow (GraphDesigner 编辑器) ││ │ │ ├─ 可视化行为树编辑 ││ │ │ ├─ 节点拖拽/连线/参数配置 ││ │ │ └─ TransitionLibrary 编辑 ││ │ └──────────────────────────────────────────────────┘│ │ Opsive.BehaviorDesigner.Editor.dll │ └──────────────────────────────────────────────────────┘ │ 序列化 ▼ ┌──────────────────────────────────────────────────────┐ │ Runtime │ │ ┌────────────┐ ┌─────────────┐ ┌──────────────┐│ │ │ BehaviorTree│ │ Subtree │ │BehaviorTree ││ │ │ (MonoBehav) │ │ (SO Asset) │ │ Data ││ │ └──────┬─────┘ └──────┬──────┘ └──────┬───────┘│ │ │ │ │ │ │ └────────────────┼───────────────────┘ │ │ ▼ │ │ ┌──────────────────────────────────────────────────┐│ │ │ ECS World ││ │ │ Entity + TaskComponent[] + BranchComponent[] ││ │ │ + EvaluationComponent + Flag Components ││ │ │ ││ │ │ BehaviorTreeSystemGroup ││ │ │ ├─ BeforeTraversalSystemGroup ││ │ │ │ └─ ReevaluateSystem ││ │ │ ├─ InterruptSystemGroup ││ │ │ │ └─ ConditionalAbortsInvokerSystem ││ │ │ └─ TraversalSystemGroup ││ │ │ ├─ EvaluationSystem ││ │ │ ├─ TraversalTaskSystemGroup ││ │ │ │ └─ [Task-specific Systems] ││ │ │ └─ DetermineEvaluationSystem ││ │ └──────────────────────────────────────────────────┘│ └──────────────────────────────────────────────────────┘ ``` ### 2.2 运行时目录结构 ``` Packages/com.opsive.behaviordesigner/ ├── Runtime/ │ ├── BehaviorTree.cs # MonoBehaviour 主控组件 │ ├── BehaviorTreeData.cs # 序列化数据容器 │ ├── BehaviorTreeDataStructures.cs # 辅助数据结构 │ ├── Subtree.cs # ScriptableObject 子树资产 │ ├── Components/ │ │ ├── BehaviorTreeComponents.cs # ECS 组件 (TaskComponent, BranchComponent 等) │ │ └── BakedBehaviorTree.cs # ECS Baking 支持 │ ├── Groups/ │ │ ├── BehaviorTreeSystemGroup.cs # 根系统组 │ │ ├── BeforeTraversalSystemGroup.cs │ │ ├── TraversalSystemGroup.cs # 遍历系统组(含循环逻辑) │ │ └── TaskSystemGroup.cs │ ├── Systems/ │ │ ├── TraversalSystems.cs # EvaluationSystem, DetermineEvaluationSystem │ │ ├── BeforeTraversalSystems.cs # ReevaluateSystem, ConditionalAbortsInvokerSystem │ │ ├── TaskObjectSystem.cs # GameObject Task 执行系统 │ │ └── CleanupSystem.cs # 清理系统 │ ├── Tasks/ │ │ ├── Task.cs # GameObject Task 基类 │ │ ├── ECSTask.cs # ECS Task 基类 │ │ ├── TaskStatus.cs # 状态枚举 │ │ ├── TaskInterfaces.cs # 接口定义 │ │ ├── ConditionalAbortType.cs # 条件中断类型 │ │ ├── StackedTask.cs # 堆叠任务 │ │ ├── TaskCoroutine.cs # 协程封装 │ │ ├── TaskDelegateBase.cs # 委托任务 │ │ ├── PlaceholderTasks.cs # 占位符 │ │ ├── UnknownTasks.cs # 未知任务处理 │ │ ├── ISubtreeReference.cs # 子树引用接口 │ │ ├── Composites/ (9 类型) │ │ │ ├── CompositeNode.cs # 基类 │ │ │ ├── Sequence.cs # 顺序: AND 逻辑 │ │ │ ├── Selector.cs # 选择: OR 逻辑 │ │ │ ├── Parallel.cs # 并行 │ │ │ ├── ParallelSelector.cs # 并行选择 │ │ │ ├── PrioritySelector.cs # 优先级选择 │ │ │ ├── RandomSelector.cs # 随机选择 │ │ │ ├── RandomSequence.cs # 随机顺序 │ │ │ └── UtilitySelector.cs # 效用选择 │ │ ├── Decorators/ (15 类型) │ │ │ ├── DecoratorNode.cs # 基类 │ │ │ ├── Inverter.cs # 取反 │ │ │ ├── Repeater.cs # 重复执行 │ │ │ ├── Cooldown.cs # 冷却 │ │ │ ├── Iterator.cs # 迭代 │ │ │ ├── ReturnSuccess/Failure.cs # 强制返回状态 │ │ │ ├── UntilSuccess/Failure.cs # 持续到目标状态 │ │ │ ├── ConditionalEvaluator.cs # 条件评估 │ │ │ ├── PriorityEvaluator.cs # 优先级评估 │ │ │ ├── PriorityVariableEvaluator.cs │ │ │ ├── UtilityEvaluator.cs # 效用评估 │ │ │ ├── UtilityCurveEvaluator.cs # 效用曲线 │ │ │ └── UtilityVariableEvaluator.cs │ │ ├── Actions/ (40+ 类型) │ │ │ ├── Action.cs / ActionNode.cs │ │ │ ├── Wait.cs, Idle.cs, Log.cs, LogValue.cs │ │ │ ├── SendEvent.cs, SetSubtree.cs │ │ │ ├── SubtreeReference.cs, SubtreeReferenceSelector.cs │ │ │ ├── ReturnStatus.cs, PerformInterruption.cs │ │ │ ├── Start/Stop/RestartBehaviorTree.cs │ │ │ ├── StackedAction.cs │ │ │ ├── TargetBehaviorTree/GameObjectAction.cs │ │ │ ├── Conversions/ (15+ 类型转换) │ │ │ ├── IList/ (8 集合操作) │ │ │ ├── Math/ (13 数学运算) │ │ │ └── UnityObjects/ (3 Unity 对象操作) │ │ ├── Conditionals/ (28+ 类型) │ │ │ ├── Conditional.cs / ConditionalNode.cs │ │ │ ├── HasReceivedEvent.cs, HasValue.cs │ │ │ ├── IsBehaviorTreeActive.cs, RandomProbability.cs │ │ │ ├── StackedConditional.cs │ │ │ ├── Math/ (6 比较操作) │ │ │ └── Physics/ (8 碰撞/触发检测) │ │ ├── Events/ (11 类型) │ │ │ ├── EventNode.cs, Start.cs │ │ │ ├── OnReceivedEvent.cs, OnInterrupt.cs │ │ │ └── OnCollision/Trigger Enter/Exit 2D/3D │ │ └── Templates/ │ │ ├── ECSNodes.cs # ECS Task 模板 │ │ └── GameObjectNodes.cs # GameObject Task 模板 │ └── Utility/ │ ├── TraversalUtility.cs # 树遍历工具 │ ├── ComponentUtility.cs # 组件管理工具 │ ├── SaveManager.cs # 存档管理 │ └── Types.cs # 类型工具 ├── Editor/ │ ├── Opsive.BehaviorDesigner.Editor.dll # 编辑器 (预编译 DLL) │ ├── Managers/ # 窗口/集成/欢迎屏幕 │ ├── NodeViews/ # 节点 UI 渲染 │ ├── Icons/ # 编辑器图标 │ └── Styles/ # USS 样式 └── Samples~/ # 示例场景和脚本 ``` ### 2.3 依赖关系图 ``` com.opsive.behaviordesigner (本包) ├── com.opsive.shared (v2.0.0) │ ├── 序列化系统 (Serialization) │ ├── SharedVariable 系统 │ └── 反射工具 ├── com.opsive.graphdesigner (v2.0.0) │ ├── IGraph, IGraphComponent 接口 │ ├── IEventNode, ILogicNode 接口 │ └── 图编辑器框架 ├── com.unity.entities (v1.3.8) │ ├── World, Entity, EntityManager │ ├── ISystem, IJobEntity │ └── IComponentData, IBufferElementData └── com.unity.burst (v1.8.17) └── [BurstCompile] 优化 ``` --- ## 3. 核心组件 ### 3.1 BehaviorTree (MonoBehaviour) 主入口组件,挂载在 GameObject 上,管理行为树的生命周期: ```csharp public class BehaviorTree : MonoBehaviour, IGraph, IGraphComponent, ISharedVariableContainer { // ─── 配置 ─── string m_GraphName; // 行为树名称 int m_Index; // 用户指定 ID BehaviorTreeData m_Data; // 序列化数据 bool m_StartWhenEnabled; // 启用时自动开始 bool m_PauseWhenDisabled; // 禁用时暂停而非停止 // ─── 更新模式 ─── UpdateMode m_UpdateMode; // EveryFrame | Manual EvaluationType m_EvaluationType; // EntireTree | Count int m_MaxEvaluationCount; // Count 模式下每帧最大评估数 // ─── ECS 关联 ─── World m_World; // ECS World 引用 Entity m_Entity; // 关联的 ECS Entity // ─── Subtree ─── Subtree m_Subtree; // 可选的外部子树引用 // ─── 静态注册表 ─── static Dictionary s_BehaviorTreeByEntity; static int BehaviorTreeCount; // ─── 生命周期方法 ─── void StartBehavior(World, Entity, startBranchType); void StartBranch(World, Entity, eventTaskType); void InitializeTree(World, Entity); void InitializeBranch(World, Entity, eventTask); // ─── 序列化 ─── void Serialize(); void Deserialize(bool force); // ─── 查找 ─── T FindTask(); // 找到第一个匹配类型的 Task void FindTasks(T[] array); // 找到所有匹配类型 Task GetTask(int runtimeIndex); // 按运行时索引获取 // ─── 静态工具 ─── static BehaviorTree GetBehaviorTree(Entity entity); // ─── 事件 ─── Action OnBehaviorTreeStarted; Action OnBehaviorTreeStopped; Action OnBehaviorTreeDestroyed; // ─── 物理事件转发 ─── Action OnBehaviorTreeCollisionEnter; Action OnBehaviorTreeCollisionExit; Action OnBehaviorTreeCollisionEnter2D; Action OnBehaviorTreeCollisionExit2D; Action OnBehaviorTreeTriggerEnter; Action OnBehaviorTreeTriggerExit; Action OnBehaviorTreeTriggerEnter2D; Action OnBehaviorTreeTriggerExit2D; } ``` ### 3.2 BehaviorTreeData — 序列化数据 ```csharp public class BehaviorTreeData : ISerializable { ITreeLogicNode[] m_Tasks; // 逻辑节点数组 IEventNode[] m_EventTasks; // 事件节点数组 SharedVariable[] m_SharedVariables; // 共享变量 ushort[] m_DisabledLogicNodes; // 禁用的逻辑节点索引 ushort[] m_DisabledEventNodes; // 禁用的事件节点索引 int m_UniqueID; // 唯一数据 ID int m_RuntimeUniqueID; // 运行时 ID // 变量名 → SharedVariable 映射 Dictionary m_VariableByNameMap; // 节点管理 void AddNode(ITreeLogicNode node); void RemoveNode(ITreeLogicNode node); void AddNode(IEventNode node); void RemoveNode(IEventNode node); // 序列化 void Serialize(); void Deserialize(...); } ``` ### 3.3 Subtree — ScriptableObject 子树 ```csharp public class Subtree : ScriptableObject, IGraph, ISharedVariableContainer { BehaviorTreeData Data; bool Pooled; // 是否池化复用 void Serialize(); void Deserialize(...); void DeserializeSharedVariables(bool force); void Clone(IGraph other); // 深拷贝 // 节点/事件管理 void AddNode(ITreeLogicNode); void RemoveNode(ITreeLogicNode); ITreeLogicNode GetNode(Type type); IEventNode GetEventNode(Type type); // 变量 T GetVariable(string name); void SetVariableValue(string name, T value); } ``` ### 3.4 UpdateMode & EvaluationType ```csharp public enum UpdateMode { EveryFrame, // 每帧自动评估 Manual // 手动调用 Tick() } public enum EvaluationType : byte { EntireTree, // 评估整棵树直到找到 Running 节点 Count // 每帧最多评估 N 个节点 (性能限制) } ``` --- ## 4. ECS/DOTS 集成架构 ### 4.1 核心 ECS 组件 #### TaskComponent (每个 Task 节点的运行时数据) ```csharp public struct TaskComponent : IBufferElementData { public ushort Index; // 树中的逻辑索引 public ushort ParentIndex; // 父节点索引 public ushort SiblingIndex; // 下一个兄弟节点索引 public ushort BranchIndex; // 所属分支索引 public ComponentType FlagComponentType; // 标记此 Task 活跃的 Flag 组件类型 public bool Disabled; // 是否被禁用 public TaskStatus Status; // 当前执行状态 public bool CanReevaluate; // 是否参与条件重评估 public bool Reevaluate; // 当前是否正在被重评估 } ``` #### BranchComponent (执行分支状态) ```csharp public struct BranchComponent : IBufferElementData { public ushort ActiveIndex; // 当前活跃 Task 索引 public ushort NextIndex; // 下一个要执行的 Task public ushort LastActiveIndex; // 上一个活跃 Task public ComponentType ActiveFlagComponentType; // 当前活跃 Task 的 Flag public InterruptType InterruptType; // 中断类型 public ushort InterruptIndex; // 触发中断的 Task 索引 public bool CanExecute; // 本帧是否可执行 } ``` #### Flag 组件 (控制 Task 执行的标签组件) 每种 Task 类型有对应的 Flag 组件 (`IComponentData, IEnableableComponent`): | Flag | 控制对象 | |------|---------| | `EvaluateFlag` | 树是否需要评估 | | `EnabledFlag` | 树是否启用 | | `InterruptFlag` | 分支是否需要中断 | | `InterruptedFlag` | 分支是否已被中断 | | `SequenceFlag` | Sequence 节点活跃 | | `SelectorFlag` | Selector 节点活跃 | | `ParallelFlag` | Parallel 节点活跃 | | `InverterFlag` | Inverter 节点活跃 | | `TaskObjectFlag` | GameObject Task 活跃 | | ... | 其他 Task 类型各有独立 Flag | **核心思想**:通过 Flag 组件的**启用/禁用**控制哪些系统需要执行,避免不必要的系统调度。 #### EvaluationComponent (位掩码评估跟踪) 根据树中 Task 数量选择不同大小的变体: | 变体 | 最大 Task 数 | 数据大小 | |------|-------------|---------| | `EvaluationComponent32` | < 192 | 32 字节 | | `EvaluationComponent64` | < 448 | 64 字节 | | `EvaluationComponent128` | < 960 | 128 字节 | | `EvaluationComponent512` | < 4,032 | 512 字节 | | `EvaluationComponent4096` | < 32,704 | 4,096 字节 | 每个 Task 在位掩码中占 1 bit,用 `FixedList*Bytes` 存储。 #### ReevaluateTaskComponent (条件中断数据) ```csharp public struct ReevaluateTaskComponent : IBufferElementData { public ushort Index; // Task 索引 public ConditionalAbortType AbortType; // 中断类型 public ComponentType ReevaluateFlagComponentType; // 重评估 Flag public ushort LowerPriorityLowerIndex; // 低优先级范围下界 public ushort LowerPriorityUpperIndex; // 低优先级范围上界 public ushort SelfPriorityUpperIndex; // 自身优先级范围 public ReevaluateStatus ReevaluateStatus; // Active/Inactive/Dirty public TaskStatus OriginalStatus; // 重评估前的原始状态 } ``` #### InterruptType ```csharp public enum InterruptType : byte { None, // 无中断 Branch, // 条件中断/效用触发 ImmediateSuccess, // 立即成功中断 ImmediateFailure // 立即失败中断 } ``` ### 4.2 Baking 支持 ```csharp public class BakedBehaviorTree : IComponentData { public int StartEventConnectedIndex; public bool StartEvaluation; public string[] ReevaluateTaskSystems; // 重评估系统类型名 public string[] InterruptTaskSystems; // 中断系统类型名 public string[] TraversalTaskSystems; // 遍历系统类型名 public ulong[] TagStableTypeHashes; // Flag 组件类型哈希 public ulong[] ReevaluateFlagStableTypeHashes; } ``` `StartBakedBehaviorTreeSystem` 负责将 Baked 数据还原为运行时组件。 --- ## 5. System Group 执行层级 ### 5.1 完整执行顺序 ``` SimulationSystemGroup └── BehaviorTreeSystemGroup (根) ├── BeforeTraversalSystemGroup (OrderFirst=true) │ ├── ReevaluateTaskSystemGroup │ │ └── [各 Task 类型的重评估系统] │ └── [其他预遍历系统] │ ├── InterruptSystemGroup │ ├── ReevaluateSystem ← 标记需要重评估的 Task │ ├── ConditionalAbortsInvokerSystem ← 比较重评估结果,触发中断 │ ├── InterruptSystem ← 执行中断 │ ├── InterruptedCleanupSystem (可选) ← 清理中断标志 │ └── InterruptTaskSystemGroup (UpdateAfter=InterruptSystem) │ └── [各 Task 类型的中断处理系统] │ └── TraversalSystemGroup (UpdateAfter=InterruptSystemGroup) ├── EvaluationSystem ← Phase 1: 遍历树,激活/停用节点 │ ├── TraversalTaskSystemGroup ← Phase 2: 执行活跃 Task │ ├── OnPreUpdate() callback │ ├── [各 Task 类型的执行系统] │ │ ├── SequenceTaskSystem (Burst) │ │ ├── SelectorTaskSystem (Burst) │ │ ├── ParallelTaskSystem (Burst) │ │ ├── InverterTaskSystem (Burst) │ │ ├── TaskObjectSystem ← GameObject Task 执行 │ │ └── ... │ └── OnPostUpdate() callback │ ├── DetermineEvaluationSystem ← Phase 3: 检查是否需要继续 │ └── EvaluationCleanupSystem (OrderLast=true) ← Phase 4: 重置标志 ``` ### 5.2 System Group 类说明 | 类 | 职责 | |----|------| | `BehaviorTreeSystemGroup` | 根组,位于 SimulationSystemGroup 内。无活跃行为树时自动禁用 | | `BeforeTraversalSystemGroup` | 预处理:条件重评估。OrderFirst=true 确保最先执行 | | `TraversalSystemGroup` | 核心遍历循环:执行 Task → 评估 → 判断是否继续 → 循环 | | `TraversalTaskSystemGroup` | 实际 Task 执行,提供 OnPreUpdate/OnPostUpdate 扩展点 | **遍历循环机制**:`TraversalSystemGroup` 实现内部循环 — 如果 `DetermineEvaluationSystem.Evaluate == true`(仍有 Running 叶子节点),则重复执行 `EvaluationSystem` + `TraversalTaskSystemGroup` + `DetermineEvaluationSystem`,直到所有分支稳定。 --- ## 6. 核心 ECS 系统 ### 6.1 EvaluationSystem ```csharp [BurstCompile] public partial struct EvaluationJob : IJobEntity { // 对每个分支: // 1. 检查活跃 Task 状态是否变为 Success/Failure → 回溯到父节点 // 2. 如果 NextIndex != ActiveIndex → 切换活跃 Task // - 禁用旧 Task 的 Flag 组件 // - 启用新 Task 的 Flag 组件 // - 设置 TaskComponent.Status = Queued // 3. 处理禁用节点 (跳过) // 4. 重置子节点状态 } ``` ### 6.2 DetermineEvaluationSystem ```csharp // 检查是否有叶子 Task 处于 Running 状态 // 使用 5 种 EvaluationComponent 大小变体的 Job 并行查询 // 输出: // Active = true → 树仍在运行 // Evaluate = true → 需要继续评估循环 ``` ### 6.3 ReevaluateSystem ```csharp // 处理 Conditional Abort: // 1. 遍历 ReevaluateTaskComponent 缓冲区 // 2. 检查 Task 是否满足重评估条件 (abort type + 范围) // 3. 设置 ReevaluateStatus = Active // 4. 启用重评估 Flag // 5. 记录原始状态用于后续比较 ``` ### 6.4 ConditionalAbortsInvokerSystem ```csharp // 比较重评估后的 Task 状态与原始状态: // 如果状态发生变化 → 触发 InterruptFlag → 设置 BranchComponent.InterruptType ``` ### 6.5 TaskObjectSystem ```csharp // 执行 GameObject-based Task 的生命周期: // 1. Queued → OnStart() → Running // 2. Running → OnUpdate() → 返回 TaskStatus // 3. Success/Failure → OnEnd() // // 对于 ITaskObjectParentNode: // 使用 NextChildIndex 确定下一个子节点 // 父节点返回 Success/Failure 时中断所有子节点 ``` ### 6.6 EvaluationCleanupSystem ```csharp [BurstCompile] // 每帧遍历结束后: // - 启用 EvaluateFlag (若 EnabledFlag 启用) // - 重置 BranchComponent.CanExecute = true // - 重置 BranchComponent.LastActiveIndex = ushort.MaxValue ``` --- ## 7. Task 系统架构 ### 7.1 TaskStatus 枚举 ```csharp public enum TaskStatus : byte { Inactive, // 未激活 Queued, // 已排队,下次 Update 开始执行 Running, // 正在执行 Success, // 执行成功 Failure // 执行失败 } ``` ### 7.2 Task 基类 (GameObject-based) ```csharp public class Task { // ─── 引用 ─── GameObject m_GameObject; Transform m_Transform; BehaviorTree m_BehaviorTree; ushort m_RuntimeIndex; TaskStatus m_Status; // ─── 生命周期 ─── virtual void Reset(); // 重置 Task 值 virtual void Initialize(BehaviorTree, int index); // 初始化 virtual void OnAwake(); // 初始化后 virtual void OnBehaviorTreeStarted(); // 行为树启动 virtual TaskStatus OnStart(); // Task 开始 (Queued → Running) virtual TaskStatus OnUpdate(); // 每帧更新 (Running) virtual void OnEnd(); // Task 结束 (Success/Failure) // ─── 物理回调 ─── virtual bool ReceiveCollisionEnterCallback => false; virtual void OnCollisionEnter(Collision collision); // ... 2D 版本同理 // ─── 协程支持 ─── Coroutine StartCoroutine(string methodName); Coroutine StartCoroutine(IEnumerator routine); void StopCoroutine(string methodName); void StopAllCoroutines(); } ``` ### 7.3 ECSTask\ (ECS-based) ```csharp public abstract class ECSTask where TSystem : ISystem where TBufferElement : unmanaged, IBufferElementData { // 派生具体类型: // ECSActionTask : IAction // ECSCompositeTask : IComposite, IParentNode // ECSConditionalTask : IConditional // ECSDecoratorTask : IDecorator, IParentNode abstract ComponentType Flag { get; } abstract TBufferElement GetBufferElement(); } ``` ### 7.4 双模式 Task 体系 | 模式 | 基类 | 数据存储 | 执行系统 | 性能 | 适用场景 | |------|------|---------|---------|------|---------| | **GameObject Task** | `Task` / `ActionNode` | C# 对象 (堆) | `TaskObjectSystem` | 一般 | 需访问 MonoBehaviour、自定义逻辑 | | **ECS Task** | `ECSTask` | `IBufferElementData` (ECS) | Burst 编译 `ISystem` | 最优 | 纯数据逻辑、大量实体 | ### 7.5 Task 接口体系 ```csharp // ─── 类型标记 ─── IAction // 行为节点 IComposite // 组合节点 IConditional // 条件节点 ([ReflectedType(typeof(bool))]) IDecorator // 装饰节点 IConditionalReevaluation // 可重评估 // ─── 核心接口 ─── IAuthoringTask // ECS 创作接口 ComponentType Flag { get; } Type SystemType { get; } int AddBufferElement(World, Entity, GameObject); void ClearBufferElement(World, Entity); IReevaluateResponder // 条件重评估 ComponentType ReevaluateFlag { get; } Type ReevaluateSystemType { get; } IInterruptResponder // 中断响应 Type InterruptSystemType { get; } // ─── 节点层级 ─── ITreeLogicNode // 逻辑节点基接口 IParentNode // 有子节点 IParallelNode // 并行执行子节点 IContainerNode // 堆叠容器 IEventNode // 事件入口 // ─── Task Object ─── ITaskObjectParentNode // GameObject 模式下的父节点 ushort NextChildIndex { get; } ``` ### 7.6 StackedTask 允许在单个节点中堆叠多个 Task(类似行为栈): ```csharp public class StackedTask { Task[] m_Tasks; // 堆叠的 Task 数组 ComparisonType m_ComparisonType; // Sequence (AND) | Selector (OR) ushort m_ActiveIndex; // 当前活跃 Task 索引 enum ComparisonType { Sequence, Selector } void Add(object taskOrMethod); void Remove(int index); } ``` ### 7.7 TaskCoroutine 协程支持 ```csharp public class TaskCoroutine { Coroutine Coroutine; void RunCoroutine(); // 执行完整协程 void Stop(); // 停止协程 delegate void TaskCoroutineEnded(TaskCoroutine, string name); } ``` ### 7.8 TaskDelegate 系统 支持方法代理到 Task 的绑定: ```csharp TaskDelegate // 无参无返回 TaskDelegate // 1-10 参数,无返回 TaskValueDelegate // 无参有返回 TaskValueDelegate // 1-10 参数有返回 ``` --- ## 8. Composite 任务 (组合节点) 组合节点控制子节点的执行顺序和逻辑组合方式。 ### 8.1 类型总览 | 类型 | 逻辑 | 子节点执行 | 典型用途 | |------|------|-----------|---------| | **Sequence** | AND | 从左到右,遇 Failure 即停 | 完整行动链 (检测→移动→攻击) | | **Selector** | OR | 从左到右,遇 Success 即停 | 行为选择 (攻击 \| 追击 \| 巡逻) | | **Parallel** | 全部 | 同时执行,任一 Failure 则 Failure | 边走边瞄准 | | **ParallelSelector** | 全部 | 同时执行,任一 Success 则 Success | 多种方式尝试 | | **PrioritySelector** | 优先级 | 按优先值排序执行 | 动态优先级决策 | | **UtilitySelector** | 效用 | 按效用分数选择 | 效用 AI | | **RandomSelector** | 随机 | 随机顺序执行选择 | 随机行为 | | **RandomSequence** | 随机 | 随机顺序执行顺序 | 随机化巡逻 | ### 8.2 Sequence (顺序节点) ```csharp // ECS 实现: public struct SequenceComponent : IBufferElementData { public ushort Index; public ushort ActiveChildIndex; } // Burst 编译系统: [BurstCompile] public partial struct SequenceTaskSystem : ISystem { ... } // 逻辑: // 1. 子节点 Success → 执行下一个子节点 // 2. 子节点 Failure → Sequence 返回 Failure // 3. 所有子节点 Success → Sequence 返回 Success // 4. 支持 ConditionalAbort (IConditionalAbortParent) ``` ### 8.3 Selector (选择节点) ```csharp // 逻辑: // 1. 子节点 Success → Selector 返回 Success // 2. 子节点 Failure → 执行下一个子节点 // 3. 所有子节点 Failure → Selector 返回 Failure // 4. 支持 ConditionalAbort ``` ### 8.4 Parallel (并行节点) ```csharp public struct ParallelComponent : IBufferElementData { public ushort Index; } // 特殊机制: // - 每个子节点获得独立的 BranchComponent (独立执行分支) // - 初始化时添加中断组件 // - 任一子节点 Failure → 中断所有其他子节点 → Parallel Failure // - 所有子节点 Success → Parallel Success ``` ### 8.5 Composite 基类 ```csharp public abstract class CompositeNode : Task, ITreeLogicNode, IParentNode, IComposite, ITaskObjectParentNode { ushort Index { get; set; } ushort ParentIndex { get; set; } ushort SiblingIndex { get; set; } ushort RuntimeIndex { get; set; } virtual int MaxChildCount => int.MaxValue; virtual ushort NextChildIndex => (ushort)(RuntimeIndex + 1); } ``` --- ## 9. Decorator 任务 (装饰节点) 装饰节点包装单个子节点,修改其行为。 ### 9.1 类型总览 | 类型 | 行为 | 典型用途 | |------|------|---------| | **Inverter** | 取反子节点状态 (Success↔Failure) | 否定条件 | | **Repeater** | 重复执行子节点 N 次 | 多次攻击 | | **Cooldown** | 冷却期间返回 Failure | 技能冷却 | | **Iterator** | 遍历列表执行子节点 | 遍历目标 | | **ReturnSuccess** | 强制返回 Success | 忽略失败 | | **ReturnFailure** | 强制返回 Failure | 强制中止 | | **UntilSuccess** | 重复直到 Success | 等待成功 | | **UntilFailure** | 重复直到 Failure | 等待失败 | | **ConditionalEvaluator** | 条件满足才执行子节点 | 条件守卫 | | **PriorityEvaluator** | 按优先级评估子节点 | 动态优先级 | | **PriorityVariableEvaluator** | 变量驱动的优先级评估 | 变量优先级 | | **UtilityEvaluator** | 按效用分数评估 | 效用 AI | | **UtilityCurveEvaluator** | 曲线驱动的效用评估 | 平滑效用 | | **UtilityVariableEvaluator** | 变量驱动的效用评估 | 变量效用 | ### 9.2 Inverter (取反器) ```csharp public struct InverterComponent : IBufferElementData { public ushort Index; } // Flag: InverterFlag // System: InverterTaskSystem (Burst) // // 逻辑: // - 子节点 Success → Inverter Failure // - 子节点 Failure → Inverter Success // - 子节点 Running → Inverter Running ``` ### 9.3 Decorator 基类 ```csharp public abstract class DecoratorNode : Task, ITreeLogicNode, IDecorator, IParentNode, ITaskObjectParentNode { int MaxChildCount => 1; // 只允许一个子节点 ushort NextChildIndex => (ushort)(RuntimeIndex + 1); } ``` --- ## 10. Action 任务 (行为节点) 行为节点是行为树的叶子节点,执行具体操作。 ### 10.1 内置 Action 分类 #### 流程控制 | Task | 功能 | |------|------| | `Wait` | 等待指定时长 | | `Idle` | 空操作,立即返回 Success | | `Log` | 输出日志 | | `LogValue` | 输出变量值 | | `ReturnStatus` | 返回指定状态 | | `PerformInterruption` | 手动触发中断 | #### 行为树控制 | Task | 功能 | |------|------| | `StartBehaviorTree` | 启动另一棵行为树 | | `StopBehaviorTree` | 停止另一棵行为树 | | `RestartBehaviorTree` | 重启行为树 | | `TargetBehaviorTreeAction` | 作用于目标行为树 | | `TargetGameObjectAction` | 作用于目标 GameObject | #### 事件与子树 | Task | 功能 | |------|------| | `SendEvent` | 发送命名事件 | | `SetSubtree` | 设置活跃子树 | | `SubtreeReference` | 引用子树 | | `SubtreeReferenceSelector` | 选择性引用子树 | #### 数学运算 | Task | 功能 | |------|------| | `BoolFlip` | 布尔取反 | | `BoolOperator` | AND/OR/XOR | | `FloatOperator` | 加/减/乘/除 float | | `IntOperator` | 加/减/乘/除 int | | `RandomBool/Float/Integer` | 随机值 | | `SetBool/Float/Int/String` | 设置变量 | | `SetVector2/Vector3` | 设置向量 | #### 集合操作 | Task | 功能 | |------|------| | `AddGameObjectToArray/List` | 添加到集合 | | `RemoveGameObjectFromArray/List` | 从集合移除 | | `SelectGameObjectFromArray/List` | 按索引选择 | | `RandomGameObjectFromArray/List` | 随机选择 | #### 类型转换 | Task | 功能 | |------|------| | `ConvertBoolToFloat/Int/String` | Bool 转换 | | `ConvertFloatToInt/String/Bool` | Float 转换 | | `ConvertIntToFloat/String` | Int 转换 | | `ConvertStringToBool/Float/Int` | String 转换 | | `ConvertGameObjectToTransform` | GO ↔ Transform | #### Unity 对象 | Task | 功能 | |------|------| | `SetEnabled` | 启用/禁用 GameObject | | `SetGameObject` | 设置 GameObject 变量 | | `WaitForAnimatorState` | 等待 Animator 状态 | ### 10.2 自定义 Action 编写示例 ```csharp [TaskCategory("MyGame")] [TaskDescription("向目标移动")] public class MoveToTarget : Action { [SerializeField] private SharedGameObject _target; [SerializeField] private SharedFloat _speed; [SerializeField] private SharedFloat _stopDistance; public override void OnStart() { // 初始化 } public override TaskStatus OnUpdate() { if (_target.Value == null) return TaskStatus.Failure; float dist = Vector2.Distance( transform.position, _target.Value.transform.position); if (dist <= _stopDistance.Value) return TaskStatus.Success; Vector2 dir = (_target.Value.transform.position - transform.position).normalized; transform.position += (Vector3)(dir * _speed.Value * Time.deltaTime); return TaskStatus.Running; } } ``` --- ## 11. Conditional 任务 (条件节点) 条件节点检查运行时条件,返回 Success (true) 或 Failure (false)。 ### 11.1 内置条件分类 #### 基础条件 | Task | 功能 | |------|------| | `HasReceivedEvent` | 是否收到指定事件 | | `HasValue` | 变量是否有值 | | `IsBehaviorTreeActive` | 行为树是否活跃 | | `RandomProbability` | 随机概率检查 | | `StackedConditional` | 堆叠多个条件 | #### 比较条件 | Task | 功能 | |------|------| | `BoolComparison` | 布尔比较 | | `FloatComparison` | 浮点比较 (==, <, >, <=, >=, !=) | | `IntComparison` | 整数比较 | | `Vector2Comparison` | 向量距离比较 | | `Vector3Comparison` | 3D 向量距离比较 | | `GameObjectComparison` | 对象引用比较 | #### 物理条件 | Task | 功能 | |------|------| | `HasEnteredCollision` | 是否发生 3D 碰撞进入 | | `HasExitedCollision` | 是否发生 3D 碰撞退出 | | `HasEnteredCollision2D` | 2D 碰撞进入 | | `HasExitedCollision2D` | 2D 碰撞退出 | | `HasEnteredTrigger` | 3D 触发器进入 | | `HasExitedTrigger` | 3D 触发器退出 | | `HasEnteredTrigger2D` | 2D 触发器进入 | | `HasExitedTrigger2D` | 2D 触发器退出 | ### 11.2 条件重评估 条件节点实现 `IConditionalReevaluation`,支持 Conditional Abort 机制: ```csharp public abstract class ConditionalNode : Task, ITreeLogicNode, IConditional, IConditionalReevaluation { // 默认 OnReevaluateUpdate() 调用 OnUpdate() virtual TaskStatus OnReevaluateUpdate() => OnUpdate(); } ``` --- ## 12. Event 系统 (事件节点) Event 节点是行为树的**入口点**,定义分支的触发条件。 ### 12.1 EventNode 基类 ```csharp public abstract class EventNode { ushort ConnectedIndex; // 连接的第一个逻辑节点索引 BehaviorTree BehaviorTree; // 父树引用 void Initialize(IGraph graph); } ``` ### 12.2 内置事件类型 | Event | 触发时机 | |-------|---------| | `Start` | 行为树启动时 (默认入口) | | `OnReceivedEvent` | 收到命名事件时 | | `OnInterrupt` | 分支被中断时 | | `OnCollisionEnter` | 3D 碰撞进入 | | `OnCollisionExit` | 3D 碰撞退出 | | `OnCollisionEnter2D` | 2D 碰撞进入 | | `OnCollisionExit2D` | 2D 碰撞退出 | | `OnTriggerEnter` | 3D 触发器进入 | | `OnTriggerExit` | 3D 触发器退出 | | `OnTriggerEnter2D` | 2D 触发器进入 | | `OnTriggerExit2D` | 2D 触发器退出 | ### 12.3 多分支执行 每个 Event 节点创建一个独立的 Branch。多个 Event 可以同时触发,意味着行为树可以有**多个并发执行分支**。 ``` BehaviorTree ├── Start Event → Branch 0 │ └── Selector [主行为逻辑] ├── OnReceivedEvent("Alert") Event → Branch 1 │ └── Sequence [警报响应] ├── OnCollisionEnter2D Event → Branch 2 │ └── Sequence [碰撞处理] └── OnInterrupt Event → Branch 3 └── Sequence [中断恢复] ``` --- ## 13. Conditional Abort 机制 Conditional Abort 是行为树中实现**实时响应**的核心机制。 ### 13.1 ConditionalAbortType ```csharp public enum ConditionalAbortType : byte { None, // 不中断 Self, // 中断当前组合内的执行 LowerPriority, // 中断右侧低优先级兄弟 Both // Self + LowerPriority } ``` ### 13.2 中断范围图解 ``` Selector (LowerPriority Abort) ├── Sequence [高优先级 - 战斗] │ ├── IsEnemyVisible ← 条件 (ConditionalAbort = LowerPriority) │ └── AttackEnemy │ └── Sequence [低优先级 - 巡逻] ← 可被中断 ├── HasPatrolRoute └── Patrol 场景: 1. 初始无敌人 → IsEnemyVisible=Failure → 跳到 Patrol 2. 巡逻中,IsEnemyVisible 被周期性重评估 3. 发现敌人 → IsEnemyVisible=Success → 中断 Patrol 分支 4. 切换到 AttackEnemy ``` ``` Sequence (Self Abort) ├── IsHealthAbove50 ← 条件 (ConditionalAbort = Self) └── AggressiveAttack 场景: 1. 初始血量 > 50% → 执行 AggressiveAttack 2. 受伤血量 < 50% → IsHealthAbove50 重评估=Failure 3. Self 中断 → 停止 AggressiveAttack → Sequence Failure ``` ### 13.3 执行流程 ``` 1. BeforeTraversalSystemGroup: ReevaluateSystem: ├─ 遍历所有 ReevaluateTaskComponent ├─ 检查 AbortType 和范围 ├─ 标记需要重评估的条件 └─ 启用重评估 Flag 2. 各 Task 重评估系统执行: └─ 调用 task.OnReevaluateUpdate() 或 ECS 重评估 Job 3. InterruptSystemGroup: ConditionalAbortsInvokerSystem: ├─ 比较重评估结果与原始状态 ├─ 如果变化 → 设置 InterruptFlag └─ 设置 InterruptType = Branch InterruptSystem: ├─ 在被中断的分支上调用 OnEnd() └─ 设置新的执行起点 ``` ### 13.4 Abort 范围计算 - **Self**: 只能中断当前 Composite 的子节点范围 (`[taskIndex, SelfPriorityUpperIndex]`) - **LowerPriority**: 中断右侧兄弟子树 (`[LowerPriorityLowerIndex, LowerPriorityUpperIndex]`) - **Both**: 合并两者范围 --- ## 14. Subtree 系统 ### 14.1 概念 Subtree 允许将行为树的一部分存储为 ScriptableObject 资产,实现**模块化复用**。 ``` 主行为树 ├── Selector │ ├── Sequence [Combat] │ │ ├── IsEnemyNear │ │ └── SubtreeReference → CombatSubtree.asset │ └── Sequence [Patrol] │ └── SubtreeReference → PatrolSubtree.asset CombatSubtree.asset (独立文件): ├── Start Event └── Selector ├── Sequence [近战] │ └── MeleeAttack └── Sequence [远程] └── RangedAttack ``` ### 14.2 数据结构 ```csharp // 子树注入数据 struct SubtreeAssignment { int ReferenceIndex; // SubtreeNodesReference 索引 ushort NodeIndex; // ISubtreeReference Task 索引 int SubtreeIndex; // 子树索引 Subtree Subtree; // 实际子树引用 ushort IndexOffset; // 索引偏移 (多子树累加) ushort ParentIndex, SiblingIndex, NodeCount; } // 子树节点引用 struct SubtreeNodesReference { ISubtreeReference SubtreeReference; // 引用 Task ushort NodeIndex; // 节点索引 ushort NodeCount; // 子树节点总数 Subtree[] Subtrees; // 加载的子树 ITreeLogicNode[][] Nodes; // 反序列化的节点 } ``` ### 14.3 关键 Action 节点 | 节点 | 功能 | |------|------| | `SubtreeReference` | 静态引用一棵子树 | | `SubtreeReferenceSelector` | 动态选择引用哪棵子树 | | `SetSubtree` | 运行时切换活跃子树 | ### 14.4 变量覆写 子树可以有自己的 SharedVariable,注入主树时支持**变量覆写** — 主树的变量值覆盖子树同名变量。 --- ## 15. SharedVariable 系统 ### 15.1 概念 SharedVariable 是行为树节点之间**共享数据**的机制。每个变量有名称和作用域。 ### 15.2 作用域 (Sharing Scope) | 作用域 | 可见范围 | 存储位置 | |--------|---------|---------| | `Graph` | 当前行为树/子树 | BehaviorTreeData | | `GameObject` | 同 GameObject 上所有 BT | SharedVariableContainer | | `Scene` | 当前场景所有 BT | SceneVariable | | `Global` | 全局所有 BT | GlobalVariable | ### 15.3 内置 SharedVariable 类型 | 类型 | 包装值 | |------|--------| | `SharedBool` | `bool` | | `SharedFloat` | `float` | | `SharedInt` | `int` | | `SharedString` | `string` | | `SharedVector2` | `Vector2` | | `SharedVector3` | `Vector3` | | `SharedGameObject` | `GameObject` | | `SharedTransform` | `Transform` | | `SharedObject` | `object` (任意引用) | ### 15.4 使用模式 ```csharp // 在自定义 Task 中声明 public class MyTask : Action { public SharedGameObject Target; // Inspector 中可配置 public SharedFloat Speed; public override TaskStatus OnUpdate() { // 读取 var targetGO = Target.Value; float speed = Speed.Value; // 写入 Speed.Value = 10f; return TaskStatus.Running; } } ``` ```csharp // 从外部代码设置 BehaviorTree bt = GetComponent(); bt.SetVariableValue("Target", playerGameObject); bt.SetVariableValue("Speed", 5f); ``` --- ## 16. 序列化与持久化 ### 16.1 序列化系统 Behavior Designer 使用 Opsive 自定义序列化系统(非 Unity 内置序列化): ```csharp BehaviorTreeData ├── m_TaskData: Serialization[] // 逻辑节点序列化数据 ├── m_EventTaskData: Serialization[] // 事件节点序列化数据 ├── m_SharedVariableData: Serialization[] // 变量序列化数据 ├── m_DisabledEventNodesData: Serialization[] └── m_DisabledLogicNodesData: Serialization[] ``` ### 16.2 序列化流程 ``` 编辑时: Editor → BehaviorTreeData.Serialize() → m_TaskData[], m_EventTaskData[] 运行时: BehaviorTree.Deserialize() → 从 m_TaskData[] 重建 ITreeLogicNode[] → 从 m_EventTaskData[] 重建 IEventNode[] → 从 m_SharedVariableData[] 重建 SharedVariable[] → 解析 Task 间引用 (TaskAssignment) → 解析变量引用 (VariableField → VariableAssignment) ``` ### 16.3 SaveManager ```csharp public class SaveManager { void Save(); // 保存所有实现 ISavableTask 的 Task 状态 void Load(); // 恢复已保存状态 } ``` --- ## 17. Editor 工具链 ### 17.1 可视化编辑器 基于 `com.opsive.graphdesigner` 的图形编辑器,通过 `Opsive.BehaviorDesigner.Editor.dll` 提供: **核心窗口**: `BehaviorMainWindow` — 节点拖拽、连线、参数配置。 | 功能 | 描述 | |------|------| | **节点编辑** | 可视化拖拽 Composite/Decorator/Action/Conditional 节点 | | **连线** | 点击连接父子关系 | | **参数面板** | Inspector 中配置每个节点的 SharedVariable 和属性 | | **运行时调试** | 运行时高亮活跃节点、显示 Task 状态 | | **分组** | 将节点分组管理 | | **注释** | 添加文本注释节点 | ### 17.2 NodeView 控件 | 控件 | 用途 | |------|------| | `EventNodeViewControl` | 事件节点渲染 | | `TaskNodeViewControl` | 通用 Task 节点渲染 | | `StackedTaskNodeViewControl` | 堆叠 Task 渲染 | | `PriorityEvaluatorNodeViewControl` | 优先级评估 UI | | `UtilityEvaluatorNodeViewControl` | 效用评估 UI | | `WaitNodeViewControl` | Wait 节点特殊 UI | ### 17.3 管理器 | 管理器 | 功能 | |--------|------| | `AddOnsManager` | 附加组件管理 | | `IntegrationsManager` | 第三方集成 | | `SamplesManager` | 示例场景 | | `Startup` | 编辑器初始化 | | `WelcomeScreenManager` | 欢迎屏幕 | ### 17.4 USS 样式 `TaskStyles.uss` — Task 节点的统一样式定义。 ### 17.5 Editor 为预编译 DLL **重要**:编辑器核心代码以 `Opsive.BehaviorDesigner.Editor.dll` 形式提供,无法直接查看/修改源码。运行时代码为完整源码。 --- ## 18. 性能分析 ### 18.1 Burst 编译优化 所有核心系统使用 `[BurstCompile]` 标记: | 系统 | Burst | 说明 | |------|-------|------| | `EvaluationSystem` | ✅ | 树遍历 | | `DetermineEvaluationSystem` | ✅ | 评估判断 | | `EvaluationCleanupSystem` | ✅ | 标志清理 | | `SequenceTaskSystem` | ✅ | 顺序节点 | | `SelectorTaskSystem` | ✅ | 选择节点 | | `ParallelTaskSystem` | ✅ | 并行节点 | | `InverterTaskSystem` | ✅ | 取反节点 | | `ReevaluateSystem` | ✅ | 重评估 | | `TaskObjectSystem` | ❌ | GameObject 模式 (需要 Managed 引用) | ### 18.2 内存优化 | 优化 | 说明 | |------|------| | **位掩码评估** | 用 ulong 位掩码追踪 Task 评估状态,极致紧凑 | | **大小自适应** | 根据 Task 数量选择 32~4096 字节变体 | | **ushort 索引** | 用 2 字节索引代替完整引用 | | **IBufferElementData** | ECS 数据存储,无 GC 压力 | | **Subtree 池化** | `Subtree.Pooled` 支持对象池复用 | ### 18.3 并行执行 ``` Job System (多线程): ├── 多个 BehaviorTree Entity 可并行处理 (IJobEntity) ├── 位掩码操作天然线程安全 └── 不同的 Task System 可以安排在不同线程 单帧内执行流: Frame N: [Thread 1] EvaluationJob for Entity A, B, C... [Thread 2] EvaluationJob for Entity D, E, F... [Main Thread] TaskObjectSystem (GameObject tasks) ``` ### 18.4 扩展性限制 | 限制 | 值 | 说明 | |------|-----|------| | 最大 Task 数 | 32,704 | 受 4096 字节 EvaluationComponent 限制 | | Parallel 子分支 | 无限制 | 每个子节点独立分支 | | 层级深度 | 无限制 | 但深树影响遍历性能 | | 变量作用域 | 4 级 | Graph/GameObject/Scene/Global | ### 18.5 性能建议 | 场景 | 建议 | |------|------| | 大量简单敌人 (100+) | 使用 ECS Task 而非 GameObject Task | | 频繁条件检查 | 合理设置 ConditionalAbort,避免每帧重评估不必要的条件 | | 深度行为树 | 使用 `EvaluationType.Count` 限制每帧评估数 | | 子树复用 | 启用 `Subtree.Pooled` 减少实例化 | | 纯 ECS AI | 使用 Baked 行为树,避免 MonoBehaviour 开销 | --- ## 19. 与 BaseGames 架构集成方案 ### 19.1 项目定位 根据 BaseGames 架构文档(`00_Architecture_Overview.md`、`20_Enemy_AI.md`): > **Behavior Designer 通过 Adapter 层包装,驱动所有敌人 AI 行为决策。** > > 业务代码永远不直接调用 Behavior Designer API,所有交互通过 `IBehaviorAdapter` 接口代理。 ### 19.2 防腐层设计 ``` ┌───────────────────────────────────────────────┐ │ 业务层 (Foundation / Entity) │ │ EnemyController, BossPhaseController │ │ AbilitySystem, TagContainer │ │ │ │ 通过接口交互,不引用 BehaviorDesigner 类型 │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────┐ │ │ │ IBehaviorAdapter (接口) │ │ │ │ Enable() / Disable() │ │ │ │ SetVariable(name, value) │ │ │ │ SendEvent(eventName) │ │ │ └──────────┬───────────────────────┘ │ │ │ │ │ ┌──────────▼───────────────────────┐ │ │ │ BehaviorDesignerAdapter (Adapter) │ │ │ │ ├─ Enable → bt.EnableBehavior() │ │ │ │ ├─ Disable → bt.DisableBehavior()│ │ │ │ ├─ SetVariable → bt.SetVariable()│ │ │ │ └─ SendEvent → bt.SendEvent() │ │ │ └──────────┬───────────────────────┘ │ │ │ │ │ ┌──────────▼───────────────────────┐ │ │ │ BehaviorTree (B.D. 原生组件) │ │ │ │ ├─ 行为树遍历 │ │ │ │ ├─ 自定义 Task 节点 │ │ │ │ └─ SharedVariable │ │ │ └──────────────────────────────────┘ │ └───────────────────────────────────────────────┘ ``` ### 19.3 IBehaviorAdapter 接口 ```csharp public interface IBehaviorAdapter { void Enable(); void Disable(); void SetVariable(string name, object value); void SendEvent(string eventName); } ``` ### 19.4 BehaviorDesignerAdapter 实现 ```csharp [RequireComponent(typeof(BehaviorTree))] public sealed class BehaviorDesignerAdapter : MonoBehaviour, IBehaviorAdapter { private BehaviorTree _bt; private void Awake() => _bt = GetComponent(); public void Enable() => _bt.StartBehavior(); public void Disable() => _bt.StopBehavior(); public void SetVariable(string name, object value) { switch (value) { case float f: _bt.SetVariableValue(name, f); break; case int i: _bt.SetVariableValue(name, i); break; case bool b: _bt.SetVariableValue(name, b); break; case GameObject go: _bt.SetVariableValue(name, go); break; case Vector3 v: _bt.SetVariableValue(name, v); break; } } public void SendEvent(string eventName) => _bt.SendEvent(eventName); } ``` ### 19.5 EnemyController 集成 ```csharp [RequireComponent(typeof(ActorCore))] public sealed class EnemyController : MonoBehaviour, IDeathListener { [SerializeField] private EnemyProfileSO _profile; private void Awake() { // 初始化行为树 var bt = GetComponent(); if (bt != null && _profile.BehaviorTree != null) { // v2.x 使用 Subgraph 属性注入 Subtree SO bt.Subgraph = _profile.BehaviorTree; bt.SetVariableValue("DetectionRange", _profile.DetectionRange); bt.SetVariableValue("AttackRange", _profile.AttackRange); bt.SetVariableValue("PatrolSpeed", _profile.PatrolSpeed); bt.SetVariableValue("ChaseSpeed", _profile.ChaseSpeed); } } public void OnOwnerDeath() { var bt = GetComponent(); bt?.StopBehavior(); } } ``` ### 19.6 自定义 BT Task 节点 BaseGames 定义了 `[TaskCategory("BaseGames")]` 的自定义节点,桥接架构内部系统: | Task 名 | 类型 | 功能 | |---------|------|------| | `ActivateAbilityTask` | Action | 通过 AbilitySystem 激活技能 | | `CheckTagTask` | Conditional | 检查 ActorCore.Tags 是否包含指定 Tag | | `GrantTagAction` | Action | 向 ActorCore.Tags 添加 Tag | | `RemoveTagAction` | Action | 从 ActorCore.Tags 移除 Tag | | `SetMovementModeAction` | Action | 切换 IPhysicsBody 重力模式 | | `NavigateToTargetTask` | Action | 通过 INavigationAdapter 寻路 | | `MoveToTargetTask` | Action | 通过 IPhysicsBody 直线移动 | | `IsWithinRange` | Conditional | 自定义距离检查 | ### 19.7 EnemyStateHandler — Tag 驱动状态切换 BT 不直接操作组件开关,而是通过 **GameTag + EnemyStateHandler** 间接控制: ``` BT Task: GrantTagAction(State.Dormant) → TagContainer.Add(State.Dormant) → EnemyStateHandler 收到 TagAddedEvent → 禁用 Hitbox, 导航, 行为树...(根据 StateBinding 配置) BT Task: RemoveTagAction(State.Dormant) → TagContainer.Remove(State.Dormant) → EnemyStateHandler 收到 TagRemovedEvent → 恢复 Hitbox, 导航, 行为树... ``` ### 19.8 BossPhaseController — 行为树阶段切换 ```csharp // Boss 根据血量阈值切换不同的 Subtree: private void TransitionToPhase(int phaseIndex) { _bt.StopBehavior(); _bt.Subgraph = _phases[phaseIndex].PhaseBehaviorTree; // v2.x Subtree SO _bt.StartBehavior(); } ``` ### 19.9 典型行为树结构 (敌人) ``` BT: SkeletonPatroller ├── Selector │ ├── Sequence [追击] ← ConditionalAbort: LowerPriority │ │ ├── IsWithinRange(DetectionRange) ← 条件节点 (持续重评估) │ │ ├── NavigateToTarget(Player) │ │ └── Sequence [攻击] │ │ ├── IsWithinRange(AttackRange) │ │ └── ActivateAbility: SwordSlash │ └── NavigatePatrol(PatrolPoints) ← 低优先级 (可被中断) ``` ### 19.10 敌人实体组件装配 ``` [EnemyEntity] ├── ActorCore # 属性/技能/Hitbox/Hurtbox ├── EnemyController # 初始化和配置 ├── EnemyStateHandler # Tag 驱动状态切换 ├── BehaviorTree # Behavior Designer 原生组件 ├── BehaviorDesignerAdapter # IBehaviorAdapter 实现 ├── NavAgent # PathBerserker2d 寻路 ├── NavAgentAdapter # INavigationAdapter 实现 ├── NavMovementBridge # 寻路 ↔ 物理桥接 ├── NavAbilityGate # 能力 ↔ Link 桥接 ├── RaycastBody2D # 物理移动 ├── AnimancerComponent # 动画 ├── Hitbox (ContactHitbox) # 接触伤害 └── Hurtbox # 受击判定 ``` ### 19.11 数据驱动配置流 ``` EnemyProfileSO (ScriptableObject) ├── DisplayName, FactionTag ├── AttributeTemplate → AttributeSet 初始化 ├── Abilities[] → AbilitySystem.GrantAbility() ├── BehaviorTree (Subtree SO) → BehaviorTree.Subgraph ├── DetectionRange, AttackRange → SharedVariable 注入 ├── PatrolSpeed, ChaseSpeed → SharedVariable 注入 ├── LootTable → 死亡掉落 ├── HitCue, DeathCue → 反馈配置 ├── InitialStateTags → 初始状态 (Dormant 等) ├── MovementMode → 移动模式 (Ground/Flying/CeilingHang) └── AbilityLinkMappings → 导航能力桥接 ``` --- ## 20. 优缺点总结 ### 20.1 技术评分 | 维度 | 评分 (1-10) | 说明 | |------|-------------|------| | 功能完整度 | **9** | 覆盖行为树全部标准功能 + Utility AI + Parallel + Subtree | | API 设计 | **8** | 双模式 Task 灵活;自定义 Task 采用熟悉的 MonoBehaviour 模式,学习成本低 | | 文档质量 | **7** | 官方文档完整,但未充分强调 MonoBehaviour Task 的主流地位 | | 性能 | **9** | Composite/Decorator 由 Burst + ECS 驱动,核心遍历极高效;MonoBehaviour Task 主线程执行,性能可接受 | | 易用性 | **9** | 可视化编辑器直观,自定义 Task 只需继承 Action/Conditional + 覆写 OnUpdate,与 v1.x 编程体验基本一致 | | 可维护性 | **7** | Editor 为预编译 DLL 不可修改,Runtime 完整源码 | | 与项目契合度 | **9** | 通过 Adapter 层完美集成,Tag 驱动架构天然契合;无需 ECS 知识即可开发自定义 Task | | **综合** | **8.3** | 项目 AI 核心框架 | ### 20.2 核心优势 | 优势 | 说明 | |------|------| | **混合架构 (ECS 调度 + MonoBehaviour Task)** | ECS 作为调度引擎提供高性能树遍历,自定义 Task 仍用熟悉的 MonoBehaviour 模式编写 | | **MonoBehaviour Task 为主流开发模式** | 内置 42+ 个任务中 80%+ 采用 MonoBehaviour Task,示例代码全部采用此模式,自定义业务 Task 无需 ECS 知识 | | **Burst 编译核心遍历** | Composite/Decorator 等树结构节点全部 ECS + Burst 编译,零 GC | | **位掩码评估** | 极低评估开销 | | **Conditional Abort** | 实时响应环境变化,无需手动管理中断逻辑 | | **Subtree 复用** | 行为模块化,Boss 阶段切换简洁 | | **SharedVariable** | 灵活的数据共享机制 | | **可视化编辑器** | 策划可参与 AI 调试和配置 | | **事件驱动分支** | 物理/自定义事件触发独立执行分支 | | **运行时源码** | 可调试可扩展 | ### 20.3 风险与缓解 | 风险 | 缓解方案 | |------|---------| | DOTS 依赖 (com.unity.entities) | Entities 是 Unity 官方组件,长期维护有保障 | | Editor 为 DLL | Runtime 完整开源,Editor 通过 API 扩展 | | 第三方维护风险 | Opsive 活跃维护 10+ 年,Runtime 源码可自维护 | | ECS 学习曲线 | 使用 GameObject Task 模式可避免直接写 ECS | | v1→v2 API 变化 | v2 API 更现代,Subtree 替代 ExternalBehaviorTree | ### 20.4 与备选方案对比 | 特性 | Behavior Designer v2 | NodeCanvas | GOAP (ReGoap) | 自研 FSM | |------|---------------------|------------|---------------|---------| | 行为树 | ✅ 完整 | ✅ 完整 | ❌ | ❌ | | DOTS/ECS 调度 | ✅ 内部引擎 | ❌ | ❌ | 需自建 | | MonoBehaviour Task | ✅ 主流模式 | ✅ | N/A | N/A | | Burst 编译 | ✅ (Composite/Decorator) | ❌ | ❌ | 需自建 | | 可视化编辑 | ✅ | ✅ | ✅ | ❌ | | Utility AI | ✅ 内置 | ❌ | ✅ | 需自建 | | Conditional Abort | ✅ | ✅ | N/A | 需自建 | | 价格 | $90 Pro | $60 | 免费 | 免费 | | 社区/维护 | 活跃 10+ 年 | 活跃 | 较小 | N/A | --- ## 21. 总结与建议 ### 21.1 总体评价 Behavior Designer Pro v2.1.12 采用 **ECS 作为内部调度引擎,同时提供 MonoBehaviour Task 和 ECS Task 双模式编程模型**的混合架构行为树解决方案。对于 BaseGames 这一项目: 1. **AI 决策核心** — 所有敌人和 Boss 行为由行为树驱动 2. **架构契合** — Adapter 层隔离完美符合 BaseGames 防腐层设计 3. **开发友好** — 自定义 Task 采用熟悉的 MonoBehaviour 模式(继承 `Action`/`Conditional` + 覆写 `OnUpdate()`),无需 ECS 知识 4. **Tag 驱动** — BT Task(GrantTag/RemoveTag)+ EnemyStateHandler 实现声明式状态管理 5. **数据驱动** — EnemyProfileSO + SharedVariable 注入,策划零代码配置敌人行为 6. **Boss 阶段化** — BossPhaseController 通过切换 Subtree SO 实现多阶段 AI ### 21.2 最佳实践 | 实践 | 建议 | |------|------| | **Task 模式选择** | 自定义业务 Task(如 ActivateAbility、CheckTag)使用 MonoBehaviour Task(继承 `Action`/`Conditional`);仅极端性能场景考虑 ECS Task | | **Conditional Abort** | 检测条件 (如 IsEnemyInRange) 放在高优先级 Sequence 首位 + LowerPriority | | **行为树深度** | 控制在 5-8 层以内,过深用 Subtree 拆分 | | **SharedVariable 命名** | 统一命名约定:`DetectionRange`、`Target`、`AttackRange` | | **自定义 Task** | 统一 `[TaskCategory("BaseGames")]` 标签分类 | | **Adapter** | 业务层只通过 `IBehaviorAdapter` 交互 | | **Tag 驱动** | 优先用 GrantTag/RemoveTag 间接控制,而非直接操作组件 | | **Boss 设计** | 每个阶段独立行为树文件,通过 BossPhaseController 切换 | | **事件通信** | 使用 SendEvent/OnReceivedEvent 替代轮询 | | **性能** | 大量小怪考虑 `EvaluationType.Count` 限制帧评估量 | ### 21.3 关键文件速查 | 用途 | 文件 | 路径 (相对 Runtime/) | |------|------|---------------------| | 主入口 | `BehaviorTree` | `BehaviorTree.cs` | | 数据容器 | `BehaviorTreeData` | `BehaviorTreeData.cs` | | 子树资产 | `Subtree` | `Subtree.cs` | | ECS 组件 | `TaskComponent` / `BranchComponent` | `Components/BehaviorTreeComponents.cs` | | Baking | `BakedBehaviorTree` | `Components/BakedBehaviorTree.cs` | | Task 基类 | `Task` | `Tasks/Task.cs` | | ECS Task 基类 | `ECSTask` | `Tasks/ECSTask.cs` | | TaskStatus | `TaskStatus` | `Tasks/TaskStatus.cs` | | 条件中断 | `ConditionalAbortType` | `Tasks/ConditionalAbortType.cs` | | 接口 | 全部 Task 接口 | `Tasks/TaskInterfaces.cs` | | Sequence | `Sequence` | `Tasks/Composites/Sequence.cs` | | Selector | `Selector` | `Tasks/Composites/Selector.cs` | | Parallel | `Parallel` | `Tasks/Composites/Parallel.cs` | | Inverter | `Inverter` | `Tasks/Decorators/Inverter.cs` | | Repeater | `Repeater` | `Tasks/Decorators/Repeater.cs` | | Cooldown | `Cooldown` | `Tasks/Decorators/Cooldown.cs` | | Wait | `Wait` | `Tasks/Actions/Wait.cs` | | SendEvent | `SendEvent` | `Tasks/Actions/SendEvent.cs` | | SubtreeReference | `SubtreeReference` | `Tasks/Actions/SubtreeReference.cs` | | Start Event | `Start` | `Tasks/Events/Start.cs` | | OnReceivedEvent | `OnReceivedEvent` | `Tasks/Events/OnReceivedEvent.cs` | | 遍历系统 | `EvaluationSystem` | `Systems/TraversalSystems.cs` | | 重评估系统 | `ReevaluateSystem` | `Systems/BeforeTraversalSystems.cs` | | GO Task 执行 | `TaskObjectSystem` | `Systems/TaskObjectSystem.cs` | | 清理系统 | `CleanupSystem` | `Systems/CleanupSystem.cs` | | 根系统组 | `BehaviorTreeSystemGroup` | `Groups/BehaviorTreeSystemGroup.cs` | | 遍历系统组 | `TraversalSystemGroup` | `Groups/TraversalSystemGroup.cs` | | 遍历工具 | `TraversalUtility` | `Utility/TraversalUtility.cs` | | 组件工具 | `ComponentUtility` | `Utility/ComponentUtility.cs` | | 保存管理 | `SaveManager` | `Utility/SaveManager.cs` | | ECS 模板 | `ECSNodes` | `Tasks/Templates/ECSNodes.cs` | | GO 模板 | `GameObjectNodes` | `Tasks/Templates/GameObjectNodes.cs` | --- > **文档版本**: 1.0 > **基于**: Behavior Designer Pro v2.1.12 源码分析 + 官方文档 + BaseGames 架构文档 > **架构参考**: `Docs/Architecture/00_Architecture_Overview.md`、`Docs/Architecture/20_Enemy_AI.md`