🧭
这不是容器 API 清单:选择数据结构时,先看最频繁的操作、数据规模、顺序要求、生命周期和线程环境,再决定用什么。

数据结构是什么

数据结构决定数据如何组织,以及查询、插入、删除和遍历要付出什么成本。Unity 开发除了关注时间复杂度,还必须考虑:
  • 连续内存与 CPU 缓存
  • 托管分配和 GC
  • Inspector 序列化
  • GameObject / UnityEngine.Object 生命周期
  • Jobs、Burst 和线程安全
  • 是否需要稳定、确定的遍历顺序
Vector3ColorRect 是常用值类型,但不是本系列所说的集合数据结构。

先按需求选择

核心需求
优先选择
典型 Unity 场景
固定长度、按索引访问
Array
技能槽、出生点
动态连续列表
List
敌人、任务、UI 项
按 ID 找对象
Dictionary
配置表、实体注册表
去重或成员判断
HashSet
已访问节点、触发区域
后进先出
Stack
UI 返回、撤销、DFS
先进先出
Queue
BFS、消息、分帧任务
按优先级取出
Binary Heap
A*、AI 调度
已知节点处频繁插删
LinkedList
LRU、特殊调度链
严格父子层级
Tree
Transform、UI、行为树
任意节点关系
Graph
寻路、任务依赖
邻域与范围查询
Spatial Index
大量单位、可见性
Jobs / Burst
Native Container
批量数值计算

决策流程

时间复杂度速查

结构
索引/查询
尾部添加
中间删除
Array
索引 O(1)
不可变长
O(n)
List
索引 O(1)、查值 O(n)
均摊 O(1)
O(n)
Dictionary / HashSet
平均 O(1)
平均 O(1)
平均 O(1)
LinkedList
O(n)
有尾节点时 O(1)
已知节点时 O(1)
Binary Heap
堆顶 O(1)
O(log n)
弹出堆顶 O(log n)
Tree / Graph
取决于索引与算法
取决于表示
取决于表示
大 O 描述增长趋势,不等于实际耗时。数据只有十几个时,连续 List 的线性扫描可能比哈希表更快;链表虽然插入复杂度低,却可能因节点分配和缓存局部性表现更差。

Unity 特有的判断维度

Inspector 与序列化

Array 和 List 能直接序列化。标准 Dictionary 默认不能直接显示,通常要用序列化 Entry 列表,在加载阶段构建运行时索引。

UnityEngine.Object

被 Destroy 的对象可能表现为“伪 null”。长期集合要在对象销毁或禁用时及时注销,避免残留引用和无效遍历。

GC

预设 List/Dictionary 容量、复用集合、避免热路径 LINQ。不要为了“零 GC”过早迁移 Native Container,原生内存和同步也有成本。

Jobs 与 Burst

托管集合不能直接进入 Burst Job。Native Container 要显式管理 Allocator、JobHandle 和 Dispose。

确定性

Dictionary、HashSet 和并行 Writer 的遍历/插入顺序不应作为确定性游戏逻辑依据。需要稳定结果时显式排序或使用稳定索引。

学习顺序

  1. Array 与 List:掌握连续内存、容量和删除成本。
  1. Dictionary 与 HashSet:掌握哈希键、去重和索引。
  1. Stack、Queue、Heap:掌握处理顺序。
  1. LinkedList:理解引用结构与缓存代价。
  1. Tree 与 Graph:表达层级和关系。
  1. Spatial Index:解决大量对象邻域查询。
  1. Native Containers:进入 Jobs/Burst 与数据导向。

系列导航

  1. 🗒️
    常用数据结构:Unity/C# 选择指南
  1. 🗒️
    数组、List 与 NativeArray:Unity 连续存储怎么选
  1. 🗒️
    Dictionary、HashSet 与 NativeHashMap:Unity 高速查找指南
  1. 🗒️
    栈、队列与二叉堆:Unity 中的顺序和优先级
  1. 🗒️
    链表:Unity 中何时使用,何时避开
  1. 🗒️
    树结构:Unity 层级、技能树与行为树的基础
  1. 🗒️
    图结构:Unity 寻路、任务依赖与关系网络
  1. 🗒️
    空间数据结构:Grid、Spatial Hash、Quadtree 与 Octree
  1. 🗒️
    Unity Native Containers:Jobs、Burst 与零 GC 数据结构

实践原则

  • 先写清主要操作,再选容器。
  • 先用简单结构实现正确版本,再用 Profiler 找热点。
  • 预估容量并复用高频集合。
  • 不依赖未承诺的遍历顺序。
  • 数据结构负责组织数据,算法决定如何使用它。

相关阅读