🌳
一句话理解:树是一种没有环的层级结构。Unity 的 Transform 层级、UI 树、技能树和行为树,都可以用“节点 + 子节点”建模。

树的基本概念

  • Root:没有父节点的入口。
  • Parent / Child:父子关系。
  • Leaf:没有子节点。
  • Depth:节点距离根的层数。
  • Subtree:某节点及其全部后代。
一棵普通树不允许形成环;每个非根节点通常只有一个父节点。如果节点能有多个父节点或形成回路,它更接近图。

一个安全的通用节点

公开 IReadOnlyList,避免外部绕过父子关系规则直接修改内部 List。

DFS:先走到底

递归 DFS 简洁,但层级异常深时可能栈溢出。迭代版本更稳:
适合遍历完整子树、序列化、层级查找和行为树 Tick。

BFS:按层访问

BFS 适合寻找离根最近的满足条件节点、按层布局 UI 和计算深度。

Unity Transform 本身就是树

不要在每帧反复调用深层 Transform.Find。初始化时缓存组件引用,或建立 ID 到节点的索引。

技能树与行为树

技能树

技能树常常不是真正的树:一个技能可能依赖多个前置技能,此时结构是有向无环图(DAG)。若硬套单父节点,会丢失依赖关系。

行为树

Selector、Sequence 是组合节点,Action、Condition 是叶子。行为树强调每帧执行语义;树结构只是承载节点关系。

UI 树

UGUI 和 UI Toolkit 都有层级。批量激活、样式传播和布局遍历会沿树执行,过深层级会增加重建与遍历成本。

扁平化存储

对象节点易读,但每个节点对象会带来引用追踪和缓存不友好。大量静态树可扁平化:
连续数组更适合 Burst、序列化和批量遍历。编辑器阶段可使用对象树,构建时烘焙为扁平数组。

复杂度

  • 遍历整棵树:O(n)
  • 已知父节点添加子节点:通常 O(1)
  • 未建索引时按值查找:O(n)
  • 沿父链计算深度:O(h)
  • 平衡二叉搜索树查询:O(log n),但普通 Unity 层级树不保证平衡

常见坑

  • 创建循环父子关系。
  • 把技能依赖图误当作普通树。
  • 递归处理来自外部数据的超深结构。
  • 每帧从根扫描寻找一个节点。
  • 在遍历 Children 时直接修改同一集合。
  • 为性能敏感数据创建海量小节点对象。

系列导航

  1. 常用数据结构:Unity/C# 选择指南
  1. Array / List / NativeArray:连续内存容器
  1. Dictionary / HashSet / NativeHashMap:哈希容器
  1. Stack / Queue / Binary Heap:顺序与优先级
  1. 链表:Unity 中何时使用,何时避开
  1. Tree:层级、搜索与决策
  1. Graph:寻路、依赖与关系网络
  1. 空间索引:Grid / Spatial Hash / Quadtree / Octree
  1. Unity Native Containers:Jobs / Burst 下的数据结构

相关阅读