文/ Karm1ng

了解過ECS的開發(fā)者都知道ECS與Unity原本的開發(fā)理念相差很大,需要所有Unity開發(fā)者重新去學(xué)習(xí)和適應(yīng)新的開發(fā)框架的代價還是很大的,Unity為何要做出這么大跨度的嘗試呢?

Unity正在嘗試解決什么問題?

以前我們基于Unity的GameObject/MonoBehaviour機制,可以非常簡單為創(chuàng)作游戲編寫代碼,但最終往往讓代碼陷入難以閱讀,維護和優(yōu)化的境地。這是一系列因素聯(lián)合導(dǎo)致的:
?

  • 面向?qū)ο竽P?/li>
  • 由Mono編譯的非最優(yōu)機器碼
  • GC機制
  • 單線程開發(fā)


Entity-Component-System 登場

Entity-Component-System 是一種編寫代碼的方式,簡稱ECS,近年因OW被廣泛熟知,ECS主要關(guān)注開發(fā)中一個很基本的問題:如何組建并處理游戲中的數(shù)據(jù)和行為。

后續(xù)文章我們會更具體的講解ECS的概念,本章我們簡單介紹ECS在Unity中的使用。

采用ECS不但在設(shè)計上可以更好的進行游戲編程,還可以利用Unity提供的JobSystem和Brush編譯器充分發(fā)揮多核處理器的性能。

Unity2017以后已經(jīng)發(fā)布了JobSystem,基于JobSystem可以在C#代碼中更好的實現(xiàn)多線程批處理技術(shù),JoySystem底層為多線程間的競爭提供的安全保障。

對于開發(fā)者而言,更重要的是要使用一種新的思維方式和編碼方式來充分利用JobSystem。

ECS有什么不同?

MonoBehavior -我們的老戰(zhàn)友

MonoBehavior 既包含數(shù)據(jù)也包含行為。下面這段代碼演示了Rotator組件每幀都要對Transform組件進行旋轉(zhuǎn)操作。

115126asjwkbokrsebaose.jpg
然而MonoBehaviour 是繼承于數(shù)個類的,且每個類包含了他們自己的數(shù)據(jù),除了Transform,上面代碼中沒有用到任何他們中的數(shù)據(jù)。這其實浪費了很多不必要的內(nèi)存,因此我們在設(shè)計一個系統(tǒng)時,需要考慮哪些數(shù)據(jù)是我們真正需要的。

ComponentSystem -邁入新的一步

115127o72nfwz00f20f77a.jpg
115127n0kdn3kw84w88own.jpg
在ECS模型中,Component(組件)只包含數(shù)據(jù)。

ComponentSystem 則包含行為,一個 ComponentSystem 更新所有與之組件類型匹配的GameObject。

混合ECS:使用與 ComponentSystem 現(xiàn)有的 GameObject components 一起工作

目前,現(xiàn)有的Unity工程基本都是基于MonoBehaviourGameObjectcomponents,如果想與現(xiàn)有GameObjectcomponents一起使用ECS,混合ECS將是個不錯的選擇。上面的例子演示了我們可以簡單的遍歷訪問即包含Rotator又包含Transform組件的實體對象。

ComponentSystem 是怎么訪問Rotator和Transform的?

為了能像上面例子中那樣可以遍歷所有匹配組件類型的實體,這些實體必須由 EntityManager 創(chuàng)建。

ECS 框架提供了一個叫 GameObjectEntity 的組件,在OnEnable時,GameObjectEntity會在GameObject上創(chuàng)建一個含有所有組件的實體(Entity)。所以ComponentSystems 可以獲取完整的GameObject及其所有組件。

因此在目前的情況下,如果你需要在ComponentSystems訪問一個GameObject,則必須在該GameObject上添加一個GameObjectEntity組件。

如何將現(xiàn)有代碼轉(zhuǎn)為混合ECS?

我們要把MonoBehaviour.Update轉(zhuǎn)換為ComponentSystems.OnUpdate的方式,可以繼續(xù)將所有的數(shù)據(jù)保存在MonoBehaviour中,這是一種很簡單向ECS的過渡方式。

因此場景數(shù)據(jù)仍然存在于GameObjects components中,可以繼續(xù)使用GameObject.Instantiate以創(chuàng)建實例等。

混合ECS的優(yōu)點:

?

?

  • 數(shù)據(jù)與行為的分離的方式,會讓代碼整體看起來更清晰
  • 系統(tǒng)對許多對象是可以進行批量操作的,避免了一些無意義的調(diào)用。(見上面deltaTime優(yōu)化)
  • 我們可以繼續(xù)使用現(xiàn)有的Inspectors, Editor tools等工具

混合ECS的缺點:

?

?

  • 實例化時間并沒有得到優(yōu)化
  • 加載時間并沒有得到優(yōu)化
  • 數(shù)據(jù)是隨機訪問的,沒有線性內(nèi)存訪問的高效性
  • 沒有發(fā)揮多核功能
  • 沒有SIMD

因此,使用ComponentSystem, GameObject 和 MonoBehaviour 結(jié)合是編寫ECS代碼的一個簡易的改變。混合ECS提供了一些簡單的性能改進,但是它并沒有充分發(fā)揮ECS的所有性能優(yōu)勢。

純ECS: 使用IComponentData Jobs全面提升性能

通常讓游戲具有更好的性能是選擇ECS的一個重要原因,但如果我們利用CPU的SIMD特性來編寫所有代碼,其實最終的性能和基于ECS編寫的是差不多的。

結(jié)合ECS與C# JobSystem將提供SIMD的可能性,以發(fā)揮CPU最大性能。

C# JobSystem 只支持structs和NativeContainers,并不支持托管數(shù)據(jù)類型。所以,在C# JobSystem中,只有IComponentData數(shù)據(jù)可以被安全的訪問。

另外,EntityManager內(nèi)部保證了ComponentData(組件)數(shù)據(jù)的線性內(nèi)存布局,這是C# JobSystem中可以高效的使用IComponentData最重要的依據(jù)。

115128z2a6v7gd4gg35gak.jpg
115128f76vtqlcktl70pvq.jpg
115129y0khslv0m0nmuhne.jpg
下一次我們將更詳細的介紹ECS。
via: 游戲扶持by騰訊游戲?qū)W院



銳亞教育

銳亞教育,游戲開發(fā)論壇|游戲制作人|游戲策劃|游戲開發(fā)|獨立游戲|游戲產(chǎn)業(yè)|游戲研發(fā)|游戲運營| unity|unity3d|unity3d官網(wǎng)|unity3d 教程|金融帝國3|8k8k8k|mcafee8.5i|游戲蠻牛|蠻牛 unity|蠻牛