Unity Dots介绍
Dots 概述
什么是Dots
- Data Oriented Technology Stack 面向数据的技术栈
The C# Jobs:多线程控制
The Burst compiler:更快速的编译器
Unity Mathematics
Collections
Entities:数据和模组分开
为什么要用Dots
Unity 传统方法
- 面向对象的方法原本数据在内存中随机分布,每次需要调用一个组件或者方法的时候在内存上找毫无规律,查找效率慢
- 只有一个主线程,虽然有协程,实际上也是在主线程上控制的
- GameObject 在使用时,在调用其某些属性时,其他属性也还在 GameObject 上,浪费内存空间
Unity Dots 特点
- 与面向对象的设计相比,Dots面向数据和内存,可以多线程能够更好的应用到多核CPU
- ECS 的数据是有规律存放,在找的时候可以很快找到并且更快找到其类似的数据,提高了效率,有利于批量处理
- Data 和 Component 分开,在不需要某些 Component 时可以关闭
- 在大型开放世界,多人场景,需要多线程加载的情况效果最好
怎么用Dots
- ECS
ECS 概述
- Entity
- Compoment
- System
Entity
托管对象(Managed objects):零散随机分布在内存中,使用CG机制,创建和销毁都需要很大的消耗,例如 GameObject,这类对象不可以用在 Jobs 也不接受 Burst 编译
非托管对象(UnManaged objects):Entity
Entity 实际上是不包含数据的一个抽象的对象,是很多组件集合在一起的
- 每一个Entity 具有在 World 唯一的
Index
,是这个 Index 关联的一系列 Component 和 Data 的特别组合,Component 和 Data 是对应的 - Entity 的另一个标识符是
Version
,每次 Index 被回收的时候,版本就更新,保证在Entity被回收后不会引用同一个 Index
- 每一个Entity 具有在 World 唯一的
World
是 Entity 的集合,不同世界的 Entity 可能会有相同的 IndexEntityManager
管理世界所有 Entities- Entity 的查询实际上是找到特定组合的 Archetype
Entity 在内存的存储
Chuck
UnManagered Memory:非托管内存,不由GC控制,需要手动分配释放
- 一块 UnManagered Memory 16Kb 就是一个
Chunk
,它包含组件的实际数值 - 包含数据的 Chunk 会交替放到 CPU 中,这样可以快速遍历到需要的数据,不需要去 RAM 里面随机找,速度更快
每块 Chunk 里面有 n 个 Entity 相同 Component 组合的数据
- 在一个 Chunk 里 Entity 的属性越多,存放的 Entity 的数量越少
假设一个 Chunk 里面有3个实体,每一种属性是一个数组,那么这里4个数组的相同位置对应的就是同一个 Entity
数据结构变化
- 原始的数据结构,引用分布在内存随机的位置,查找效率低
- 面向内存的数据结构,相同的数据相邻,查找效率高
Archetype
Archetype
原型是 Chunk 中组件结构相同的标识符,方便数据并行计算;即每个 Chunk 保存的都是同一种 Archetype- 增删组件会导致重新组织内存块,原型发生变化消耗大
Component
- 组件,不包含数据,使用 Archetype 保存
System
- 每一个 System 实例属于一个世界
- System 是一个层级结构,具有
Child System
和Child System Groups
- Initialization:
Initialization System Group
- Update:
Simulation System Group
- PreLate Update:
Presentation System Group
- Initialization:
SystemBase
- 在主线程的托管类,不能被 Burst 编译
ISystem
- 非托管类,可以被 Burst 编译
Jobs
- 多线程并发处理
- 需要注意线程之间的依赖关系
Run() | Schedule | ScheduleParallel |
---|---|---|
主线程 | 子线程调度 | 平行调度 |
一个简单的流程
例如:NPC向前走
安装
Unity 2022.2.0b16
+com.unity.entities 1.0.0-exp8
新建子场景(World)
- 创建 SubScene,也就是一个 World
创建Entity
IComponent
- 为 GameObject 创建向前走需要的速度变量
1 | public struct NPCMoveProperties : IComponentData |
Baker
- 创建自定义数据集,将 GameObject 转换为 Entity,也就是将 Authoring 下的数据转换为 Runtime 的数据,可以在 Inspector 窗口上对于 GameObject 赋值
1 | public class NPCMono : MonoBehaviour |
Aspect
- 将 ICompoment 封装在一起,方便 System 调用
1 | public readonly partial struct NPCAspect: IAspect |
System 运行(Job)
- 在子线程上进行调度,多个NPC行走是并行任务
1 | [ ] |
- 在System上运行
1 | [ ] |
扩展
Unity ECS 1.0 Full Project Tutorial | Step-by-Step
动画
unity.entity.animation
目前不适配 Entity 1.0版本,没有官方的动画处理- 开源的 dmotion 适用于 Entity 1.0版本,但其依赖的 Latios-Framework 不支持 Transform V2,导致
LocalTransform
等结构体无法使用
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 五里霧中!