文/ 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)操作。
然而MonoBehaviour 是繼承于數(shù)個類的,且每個類包含了他們自己的數(shù)據(jù),除了Transform,上面代碼中沒有用到任何他們中的數(shù)據(jù)。這其實浪費了很多不必要的內(nèi)存,因此我們在設(shè)計一個系統(tǒng)時,需要考慮哪些數(shù)據(jù)是我們真正需要的。
ComponentSystem -邁入新的一步
在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ù)。
下一次我們將更詳細的介紹ECS。
via: 游戲扶持by騰訊游戲?qū)W院
銳亞教育,游戲開發(fā)論壇|游戲制作人|游戲策劃|游戲開發(fā)|獨立游戲|游戲產(chǎn)業(yè)|游戲研發(fā)|游戲運營| unity|unity3d|unity3d官網(wǎng)|unity3d 教程|金融帝國3|8k8k8k|mcafee8.5i|游戲蠻牛|蠻牛 unity|蠻牛
- 還沒有人評論,歡迎說說您的想法!