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

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