DOTS 是 data oriented tech stack 的缩写
主要包括3部分
ECS:Entity Component System 组件化/数据化的开发模式
job system:更加安全,简便的实现多线程
burst compile:LLVM-based, math-aware的后端编译器(backend compiler),将C#代码编译成更加高效的C++代码
burst compile 了解的不深入,主要从 ECS 和 job system 入手
ECS:前提:unity 一直是基于组件的设计,开发中常常采用面向对象的设计模式,复杂的项目会导致继承链过长,父类臃肿,一般引入组合的设计模式加以改善。
Entity:对象实体,可以简单的认为是 GameObject,持有 Component 组件,Entity 中没有数据和属性,包含的 Component 决定了属性和数值,可以认为是 Component 的集合,决定了对象的性质
Component :组件,基础的数据结构,主要包含数值,
System:系统,相同类型的 Component 组成了 System,他们拥有同样的行为。运行中 System 遍历/更新 Entity 中的 Component,最终表现为 Entity 的行为多样
如果只是软件设计上使用了 ECS,只是设计模式的改变,并不能有质的改变,unity 在 ECS 中主要加入的内存的管理,让相同的组件在内存中连续分布,这样遍历相同组件的时候速度就会快很多,多个不同组件组成的 Entity,在内存中使用 Chuck 数据类型,使其也能连续分布,增加或者删除组件,会改变 Chuck 类型,移动到对应的 Chuck 中,始终保持内存紧凑/连续
job system:主要是为了更安全,更方便的利用多核来实现多线程
传统的多线程编程,是在程序中创建多个线程,然后需要手动控制多个线程运行/切换,数据共享/锁定等,为了保证数据的一致性,会引入锁的机制,会导致效率不高,没有完全发挥多线程的优势
为了解决数据一致性的问题,引入了 NativeContainer 的数据类型
实现机制是复主线程和job工作线程共享内存,减少了上下文切换和数据交换。job 线程并不能直接操作主线程的对象和数据,只能通过 NativeContainer 来和主线程交互,一旦启动任务,主线程不能修改 NativeContainer 中的数据,只能读取
job system 使用新的方式,创建 job (任务)来实现多线程
- job 创建后会被 job system 分成 batches
- 然后系统根据运行环境的核心数量生成多个 job queue
- job queue 定期从 batches 中获取 job batches ,开始执行
- 最后将执行的结果写入 NativeContainer 中
主线程通过调用 Complete 来使 job 线程完成任务并更新 NativeContainer 中的数据,完成任务
一些注意事项
Entity 的创建可以在场景中的 GameObject 中添加 Convert To Entity 组件,也可以使用脚本动态创建,但是不能在job运行中直接创建和销毁,需要借助于 EntityCommandBuffer,一般在BeginInitializationEntityCommandBufferSystem 中创建,EndInitializationEntityCommandBufferSystem 中销毁
使用 ParallelFor job,完成并行任务,可通过指定 batch 中的 job 数量,来分配 job
一定记得调用 Complete 来使 job 执行,否则 job 不会执行,job 中不能调用主线程中的方法,
如:Time / Mathf 等,数学和物理都有专门的 API
burst compile 还没有深入了解