官网:https://unity.com/cn/dots
手册:https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/index.html
样例:https://github.com/Unity-Technologies/EntityComponentSystemSamples
ECS Physics 手册:https://docs.unity3d.com/Packages/com.unity.physics@1.3/manual/index.html
ECS Physcis 工作流:https://learn.unity.com/tutorial/ecs-physics-havok-physics-for-unity-and-unity-physics#63089698edbc2a43aba17b9c
软浮点确定性物理:https://www.reddit.com/r/Unity3D/comments/lkxb9d/crossplatform_deterministic_physics_with_unity/
DOTS 最佳实践:https://learn.unity.com/course/dots-best-practices
最新样例(2024.07):https://github.com/Unity-Technologies/ECSGalaxySample
前言
-
DOTS(Data-Oriented Technology Stack)面向数据的技术栈
-
通常游戏要处理大量数据时可以考虑用。用于核心战斗模块等,ui啥的不用考虑这些。
- 截至目前(2024年9月),Unity Entity出到1.3+版本,ChatGPT的知识库最新是2023年10月,对应Unity Entities包是1.0+版本,有些差异,但大部分问题还是能教。
子场景
-
因为原来Unity场景不支持ECS组件,所以单独弄了个“子场景”来烘培ECS组件。
-
子场景也可以用来多人协作,比如美术做地编避免冲突。
实体和组件烘培
- 用来将传统MonoBehaviour组件转换成ECS中的Component,需要自己写具体转成代码。根据需要可以生成生成多个Component。
- Unity DOTS Physics 也支持以组件形式挂在预制体上,创建时烘培。
- 一些传统MonoBehaviour也可以有兼容自动转成Component组件,比如SpriteRenderer。
系统
-
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/systems-comparison.html#differences-between-systems
-
继承实现主要分两种,
ISystem
接口和SystemBase
类。-
ISystem
:纯ECS代码,不需要被外部调用这个系统时,用这种。性能比`SystemBase`好。 -
SystemBase
:需要被外部系统调用,或者跑一些传统托管代码,用这种。
-
系统执行顺序
-
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/systems-update-order.html#default-system-groups
-
默认不指定顺序时,是在MonoBehaivor的Update后执行。总体分三组:
- 菜单打开 Windows/Entities/Systems,可以查看当前系统执行顺序。
遍历处理实体
-
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/systems-iterating-data-intro.html
-
效率:
IJobChunk
>IJobEntity
>SystemAPI.Query
>Entities.ForEach
-
编写难度:
IJobChunk
>IJobEntity
>Entities.ForEach
>SystemAPI.Query
-
IJobChunk
:需要属性ECS底层直接操作Chunk代码,要求较高。 -
SystemAPI.Query
:效率比IJobEntity
差一点点,写得方便,建议只在简单操作时用。 -
推荐首选
IJobEntity
:
-
Entities.ForEach
:如果要操作一些unity还未支持的托管代码,要求必须在主线程执行时,比如要修改SpriteRender.sprite
:
特性 | GetComponentTypeHandle | SystemAPI.GetComponentLookup |
---|---|---|
数据处理范围 | 适合批量、块(Chunk)级别处理。 | 更适合单个实体的按需查询。 |
性能优化 | 通过缓存 ComponentTypeHandle 提供更高效的批量处理。 | 每次查询生成新的 ComponentLookup ,单独查询实体时可能开销较大。 |
常见使用场景 | 需要处理大量实体,常用于 IJobChunk 、Entities.ForEach 等场景。 | 按需访问特定实体的组件,更灵活但不适合大量实体查询。 |
线程安全 | 适用于并行作业(如 IJobChunk ),可以安全并行处理多个实体。 | 主要用于主线程上下文,适合单线程或少量实体查询。 |
缓存机制 | 可以每帧缓存一次 ComponentTypeHandle ,减少不必要的查询。 | 每次使用 GetComponentLookup 时都创建新的访问器,无法缓存。 |
块级别处理 | 能够高效处理整个 ArchetypeChunk ,块级优化较好。 | 逐实体查询,没有按块的优化。 |
增删改实体组件
-
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/iterating-entities-foreach-ecb.html
-
EntityCommandBuffer
:创建删除实体、添加删除组件,修改组件等修改实体指令,指令队列,是延迟的异步执行,统一执行,线程安全。缺点也是因为异步,有需要立即生效就不要用。- 如果添加的对应在对应命令系统之后,会等到下一帧这个系统时候再执行。
调试
-
ECS的代码相比传统代码编译更复杂一点,要断点调试时,需要生成额外的代码,有时候断点不上时,可以尝试重启Unity,编辑器先附加Unity再启动游戏。
-
ECS提供一些菜单工具,方便查看ECS系统相关内容。
Hierarchy
- 专门看Entity的层级面板
Components
- 查看当前定义了哪些Components和其依赖。
Systems
- 查看当前所有ECS的系统
Archetypes
-
原型:https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/concepts-archetypes.html
-
有相同种类组件的算一种原型,同一种原型查询处理更快,频繁增删导致原型变化(产生同步点)影响性能。
Journaling
-
日志:https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/entities-journaling.html
-
比如要查一个实体表现异常了,通过搜索过滤可以查到这段时间内的所有组件操作。
-
也有API可以在调试时用Watching查指定Job的操作记录,见上面链接。
Profiler
-
CPU:除了在主线程可以看System中Update的主线程耗时,也可以看Job在子线程中耗时
-
EntitiesMemory:查看每个Archetype原型总的内存分配占用
-
EntitiesStructuralChange:每个实体变化产生开销
实际应用
-
碰撞触发计算:500+个实体,原来使用[Box2D]改造耗时90ms,用DOTS后主线程耗时2ms。
-
怪物避免堆叠的集群移动:300+实体,优化前后37ms->7ms,优化不完全,7ms里还有6ms其实是回调旧系统重新同步坐标,因为还未把实体完全移植到DOTS中。
-
经验豆掉落道具,这种只有sprite的对象,去掉了GameObject,只用Entity来绘制Sprite,但因为DOTS没有计划支持SpriteRender,所以还是用SpriteRenderer在主线程设置,会有较高耗时(0.6ms)。后续可以考虑使用Entities.Graphics代替,或者用Graphics.DrawMeshInstance来处理。
真机兼容性
-
Entities 1.3.5 兼容HybridCLR压缩包:
- https://download.csdn.net/download/l773575310/90373769
-
HybridCLR 免费版目前最新仅支持Entity1.0.16(上面1.3.5是自己对比升级,可以用),需要替换package,否则真机无法使用DOTS。
-
https://hybridclr.doc.code-philosophy.com/docs/basic/dots
-
经测试,在顶层
Assembly-CSharp.dll
加的dots代码,打包有报错,还未查到具体原因。(最小测试Demo正常,没用热更整个程序集)
-
测试dots代码单独封装dll,加载热更正常。
-
-
demo测试工程如下
https://download.csdn.net/download/l773575310/90373786 -
未解决的问题:游戏demo工程命令行打包出现不该出现的调试断言宏生效情况,再次手动打包后正常。是HybridCLR加的,catch异常,测试正常
右边是命令行打包,在ecs的TypeManagerSystem注册系统类型出现了个应该编辑器用的
[Conditional(“UNITY_ASSERTIONS”)] 真机不应该生效,导致异常中断,这个方法是HybridCLR加的
注意事项
-
不要在Job中删除容器数据,并发情况下容易出问题。
-
因为job执行异步,
EntityCommandBuffer
的等待批处理,还有系统的执行顺序,可能有不少时序问题。