DOTS是什么?

 

DOTS是给几项优化技术打包起了个名字,主要还是为了宣传考虑。

它主要包含3个技术:

  1. ECS模式。这种编程模式,要求游戏逻辑和引擎功能,都要按照 实体+组件+系统 的框架构建。采用ECS模式后,可以得到性能与多线程并行的优化。
  2. JobSystem。一套先进的多线程任务管理系统,搭配ECS时可以获得最佳性能。不搭配ECS也能在引擎的基本功能方面享受到好处。
  3. Burst,可以代替.Net原来的运行时环境(Mono或IL2CPP),用全新的编译器编译为原生代码,得到比IL2CPP更快的执行速度。当然代码最好能配合Burst做一些代码上的改动,以得到充分优化、避免BUG :)

DOTS系统成熟以后,游戏的脚本逻辑部分会和现有的组件式系统完全不同。原有脚本写法和ECS写法的区别,比两种语言的差别要大得多。所以起个好名字逐步发展新体系也是必要的。

3、ECS是什么?

首先ECS并非一种全新的技术,也不是Unity首先提出的。

这种技术的出现非常早,而近几年突然火爆,是因为暴雪的《守望先锋》。《守望先锋》的服务器和客户端框架完全基于ECS构建,在游戏机制、网络、渲染方面都有非常出色的表现,这种技术上的巨大成功,必然会引领一波ECS的潮流。

这篇GDC分享3年前火了一阵

ECS不属于某种“设计模式”,之前我们常说的“设计模式”是在面向对象的框架之下讨论的,而ECS完全是另一种面向对象的编程方法,它对传统编程方法的颠覆性比Actor模式更强。至少目前来看,ECS仅适合于游戏开发领域。

  1. E代表实体(Entity)。实体在逻辑意义上是组件的容器,每个实体有若干个组件;但在实现上它只需要一个整数ID,区分不同的实体。
  2. C代表组件(Component),它不是目前Unity中的组件,而是一种只拥有数据,不能具有任何方法的结构体。
  3. S代表系统(System),和C相反,系统只能具有方法而不具有任何数据。

系统是程序逻辑的载体,游戏中有很多System会反复执行。每个System执行时它不管什么Entity,而只做两个步骤:

  1. 从所有的组件中筛选合适的“组件组合”。例如某个移动system,只关心同时具有“移动组件”和“旋转组件”的对象。
  2. 对筛选出的组件进行某种操作。例如上面的移动system,会修改移动组件中保存的位置变量,再修改旋转组件中保存的朝向变量。

一个游戏中,大量的Component每一帧被很多System修改,就形成了游戏逻辑。

那为什么说ECS非常厉害呢?关键是:

  1. 每个system所做的事情都非常简单,非常容易并行执行。而且只要标记出哪些数据是只读的、哪些是可写的,就能让ECS系统进一步优化。现代手机和PC核心数都挺多,可以达到恐怖的并行效率。
  2. 由于组件C只是单纯的数据,大量组件数据在内存中很容易按顺序排好位置,系统处理这些整整齐齐的数据极为高效。而且,这种内存布局可以提高CPU缓存命中率,现代CPU动辄有十几兆、几十兆的缓存,在缓存中执行比火箭还快。

4、ECS目前的发展阻力是什么?

通过前面的介绍可以看出,ECS可不是什么“易学易用”的新技术,它对现有的开发模式,甚至现有的Unity编辑器来说都是颠覆性的。

不仅如此,ECS对初学者来说有着巨大障碍:除了游戏技术圈,人们很难在任何其它地方学到ECS编程方法

无论你在什么地方学习编程,能搞清楚传统的面向对象已经很不错了,ECS只能在你有一定编程基础后,通过网络资料实践自学。这一问题在ECS的推广方面是致命的。

因为ECS这一技术本身还是比较新颖的,高手们都还没有把ECS系统摸透,没有系统化,更别提能够在不误人子弟的前提下教会新人。

但是话说回来,ECS虽然是一种全新的编程思想,但对于一些专业开发者来说并不难,比如咱们专栏里已经有写过一些实践分享:

ProcessCA:Unity 实体组件系统(ECS)——性能测试

zhazha chen:Unity ECS 高性能探索

对于专业开发者来说,目前在Unity中实践ECS,阻力来自于:Unity官方对于DOTS依然是缓慢开发中,还远远谈不上成熟

例如,由于ECS的游戏对象不再兼容原来的GameObject,导致ECS物体在场景编辑器中看不到。如何解决官方给出了至少两种方案:加个代理适配,或是彻底换成新编辑器窗口(比如Entity Debugger之类的工具)。但是这些方案都还不完善…… :)

还有ECS在渲染方便和原系统存在兼容问题,雨松Momo的ECS分享视频中,用了较多篇幅解释在DOTS技术栈下如何妥善渲染。可以看出问题还很多,针对不同项目要考虑不同的方法。

5、我们应该如何看待DOTS?

重点是,虽然Unity的DOTS技术存在巨多问题,无论Unity ECS还是Burst,说起来都是各种吐槽。但作为专业的软件工程师,应当以最大程度的积极性拥抱这些新技术

纵观历史,新技术出现时总是带着一身毛病——还没马车跑得快的汽车,还没蒸汽机好用的内燃机,还没滑膛枪可靠的线膛枪,感觉随时会核爆的核电站。一切当今习以为常的东西,在当年都被无情地嘲笑过。

就算发展慢、就算发展中出现下滑和反复。ECS技术在内存布局、缓存友好性、多线程友好性等方面达到了传统编程模式望尘莫及的高度。甚至可以说,很常规的ECS代码就已经能达到某些深度优化过的传统代码的性能。

所以从发展趋势看,我们没有理由故步自封、拒绝这一新技术。

PS:话说回来,现在学DOTS并不是现在就要用到商业项目里。在商业项目中,采用这种尚不成熟的新技术一定要得到团队的一致同意和Leader的支持,否则就是非常不负责任的决定。 :)

 

 

泻药,个人观点有3条:

  1. ECS是好东西,Unity的ECS不是。
  2. Job System是好东西,Unity的Job System也不错,但还有一定的进步空间。
  3. Burst目前看来提升确实很大,但是没有跟手写SIMD比较过。

ECS的思想其实从十几年前机能严重不足的时候,到现在都一直在影响游戏开发行业,无论是里边有过程式编程的影子,还是函数式编程的影子,亦或是针对缓存和CPU密集运算的优化思想,都是在切实的解决游戏逻辑和渲染中的痛点,而且即使不是纯ECS,许多团队的框架也在向这个方向靠拢。Unity的ECS一方面完成度太低,之前看到版本号还是0.x,就比较尴尬,另外从我个人自私的角度分析(本人是个写渲染的)就是没大有和渲染层接壤,比如VLK和DX12这种现代的API是可以直接并行产生PSO,并行准备CommandBuffer(CommandList) 等等,在这些方面Unity只提供了SRP这种很上层的封装,很难将Job System和ECS灵活的应用上去。

Job System这种线程调度方式,应该是同步多线程中速度最快的方法,因为队列数量提前可知所以几乎不存在高消耗的锁和等待,同时一次性触发不会涉及到上下文,线程启动消耗等。但是官方的Demo好像有涉及到一些异步多线程,个人认为Job System这种一次性触发的设计模式并不适合异步多线程,平时我在开发时也经常会用到Job System这种多线程思想,对性能的提升大有裨益。

之前有人问Job System,Unreal的Task Graph有什么关系和区别,看起来Task Graph在设计时更多的考虑了异步能力,而不是这么注重一口气憋住的同步能力,而且Unreal官方似乎推荐使用Task作为延时的逻辑触发,而Unity推荐使用协程做等待,让其他线程做纯运算,在设计理念上应该存在一些不同,本人在此不置褒贬。

Burst据说是处理SIMD的效果很好,经过一些测试发现效果也确实不错,但是平常这种优化手写也是能做到的,所以究竟和平常手写的带_m128这种的数学库,比如DX提供的DirectX::XMVECTOR DirectX::XMMATRIX有多少提升,这一点还有待探索,这里持保留态度。

 

引用:https://www.zhihu.com/question/363824849/answer/1069372037

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章