fwalker 发表于 2021-12-7 16:34

unity DOTS 学习记录

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 queuejob 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 还没有深入了解

参考:https://docs.unity3d.com/Manual/JobSystem.html
页: [1]
查看完整版本: unity DOTS 学习记录