談?wù)撌裁?/h1>
這里我主要從工程或設(shè)計的角度討論, 至于ecs對性能的優(yōu)化方面
的事情我這不做過多介紹.
為什么要把ec系統(tǒng)里的c分為coponent與system兩快
ecs系統(tǒng)的優(yōu)點(diǎn)
ecs系統(tǒng)的缺點(diǎn)
從編程演化看ecs系統(tǒng)
ecs總結(jié)
吐槽一下unity 的ecs系統(tǒng)
為什么要把c與s分開
這是我在用ecs系統(tǒng)時最大的一個問題枷莉,現(xiàn)將我的一點(diǎn)想法與大家分享
原因在于將c與s分開之后,就可以降低邏輯之間的關(guān)系,極大的降低系統(tǒng)復(fù)雜度
原理如下:
當(dāng)system(邏輯)需要其他數(shù)據(jù),直接找到entity好了工腋,數(shù)據(jù)都在上面。
沒有必要與其他system(邏輯)有關(guān)聯(lián)
所有的關(guān)聯(lián)都在entity及其component上
在拓?fù)潢P(guān)系里途样,若將所有entity看成一個節(jié)點(diǎn)备蚓,那么所有system都依賴這個
節(jié)點(diǎn)熙兔,而且entity與compoent又不依賴system,這樣一個星形的單方向的拓?fù)浣Y(jié)構(gòu)
極大的簡化了系統(tǒng)的之間的關(guān)系與復(fù)雜度挽懦。
下面講的優(yōu)點(diǎn)都在這基礎(chǔ)上具體的表現(xiàn)翰意。
ecs系統(tǒng)的優(yōu)點(diǎn)
- 規(guī)則簡單易于推廣
只有component能存數(shù)據(jù),只有system能有行為信柿, entity結(jié)構(gòu)永遠(yuǎn)不變
規(guī)則就這么簡單冀偶,比較容易記住
- 降低了復(fù)雜度
由于ecs系統(tǒng)的所有操作都是對entity內(nèi)的數(shù)據(jù)(Component)的直接修改
因此大大的降低了不確定性與花費(fèi)的 精力
舉例: 系統(tǒng)龐大之后, 做一個系統(tǒng)或功能可能要依賴好幾個系統(tǒng)
用面向?qū)ο蠡騟c系統(tǒng)的時候,你可能需要調(diào)
用一些函數(shù)
而這些函數(shù)有可能代價很高很復(fù)雜, 比如內(nèi)部調(diào)用的文件存儲渔嚷、
網(wǎng)絡(luò)进鸠、渲染api這類復(fù)雜的操作,需要很小心的調(diào)用
不然很可能就會有性能問題形病。
而在ecs系統(tǒng)中即便是調(diào)用的輔助函數(shù), 本質(zhì)都是對數(shù)據(jù)的操作
能夠很方容易估算出調(diào)用的代價客年,而且代價也相對較小。
- 不需要緩存機(jī)制
正因?yàn)閑cs創(chuàng)建entity代價小漠吻,
創(chuàng)建對象直接生產(chǎn)量瓜,不需要內(nèi)存池對象池也相應(yīng)減少了代碼復(fù)雜性
- 容易寫出好的代碼
由于ecs系統(tǒng)強(qiáng)制把數(shù)據(jù)和行為分開了, 寫邏輯的程序就不容易出錯了。
因?yàn)楸举|(zhì)上寫的東西就是對純數(shù)據(jù)的操作途乃。
規(guī)范更容易推進(jìn), system里面不保存任何數(shù)據(jù), 規(guī)則也很清晰绍傲,容易執(zhí)行
- 統(tǒng)一數(shù)據(jù)的存放方式
需要記錄的東西都使用component來記錄
這樣大家就不會出現(xiàn)數(shù)據(jù)存儲在一些奇怪的地方
- 統(tǒng)一了數(shù)據(jù)的獲取方式
原有的方式,每個系統(tǒng)的調(diào)用, 需要用到的數(shù)據(jù)可能有各種獲取方式
比如調(diào)用某個或多個方法來獲取耍共。
而ecs系統(tǒng)則統(tǒng)一使用類型的組合作為數(shù)據(jù)的獲取條件
- 二進(jìn)制友好
游戲中常需要保存游戲進(jìn)度, 或是同步數(shù)據(jù)給服務(wù)器烫饼。
ecs系統(tǒng)里只要把特定的component篩選出來序列化就可以, 非常方便
- 降低了代碼間的耦合
所有的system 可以做到只依賴 相應(yīng)的component
直接的交互也使用component來進(jìn)行, 這樣就極大的降低了代碼間的耦合
ecs系統(tǒng)缺點(diǎn)
- 模塊獨(dú)立性不強(qiáng)與系統(tǒng)強(qiáng)關(guān)聯(lián)
一些功能的重用必須要有整個ecs環(huán)境才能運(yùn)作, 模塊獨(dú)立性不高
一些底層功能, 如網(wǎng)絡(luò)试读,文件操作使用ecs就不好做封裝
- 模塊間無法隱藏數(shù)據(jù)
正因?yàn)槟K間無法隱藏數(shù)據(jù), 導(dǎo)致一個問題就是設(shè)計不好的數(shù)據(jù)會影響所有系統(tǒng)
對寫的不好的代碼容忍度比較低
- 無法統(tǒng)一編程模型, 只能解決特定問題
無法像ec系統(tǒng), 比如com組件那樣將所有的代碼都用一套來封裝
- 新的思考模型
新的編程模型需要新的思考方式杠纵,大家需要習(xí)慣一下
- 對異步處理支持不好
編程演化
-
01編程
- 有就行了, 要求不要那么高
-
匯編
- 人類容易記住字母的命令,而不是01的數(shù)字
-
c語言
- 演化為數(shù)據(jù)結(jié)構(gòu)與算法鹏往, 因?yàn)榘l(fā)現(xiàn)代碼通常不會改變淡诗。
這樣把結(jié)構(gòu)與算法分開更加容易寫出健壯的代碼,
代價是不能在運(yùn)行時通過動態(tài)修改代碼獲得最高的性能
- 演化為數(shù)據(jù)結(jié)構(gòu)與算法鹏往, 因?yàn)榘l(fā)現(xiàn)代碼通常不會改變淡诗。
-
oop 初代
- 人類對事物的認(rèn)知本來就是對對象進(jìn)行分類來思考的
oop能降低大家的思考難度骇塘,而且可以將垃圾代碼隱藏起來
代價是性能有所降低
- 人類對事物的認(rèn)知本來就是對對象進(jìn)行分類來思考的
-
oop ec編程
- 在自然的環(huán)境下分類思考是可行的, 因?yàn)轭惗际遣蛔兊?br>
但在游戲里的類是會變的啊, 通過配置加個類型跟玩似的
于是就強(qiáng)調(diào)面向行為
具體做法是限制 類的繼承伊履,只使用組合。強(qiáng)調(diào)設(shè)計接口的不變款违。
-
oop ecs編程
- 系統(tǒng)之間關(guān)系太復(fù)雜唐瀑,性能要求也有所需要。
通過限制編程的方式插爹,邏輯上只對數(shù)據(jù)進(jìn)行操作
達(dá)到簡化系統(tǒng)哄辣,降低大家對系統(tǒng)的理解成本请梢,降低對邏輯編程的要求
基本編程方式的發(fā)展就是各種簡化
一種是將編程方式與人類思考方式靠近, 簡化理解的成本,簡化編程的難度.(設(shè)計一門新語言)
一種是通過對已有編程方式的限制力穗,簡化系統(tǒng)的復(fù)雜度毅弧,出錯的可能。(編碼規(guī)范)
ecs系統(tǒng)總結(jié)
ecs的最大收益的当窗,其實(shí)是做邏輯的程序够坐,可以更加容易的寫出優(yōu)秀的代碼。
ecs系統(tǒng)在我看來就是ec系統(tǒng)的一個子集崖面,在ec系統(tǒng)上加上一些
限制條件容易做成一個ecs系統(tǒng)元咙,ecs系統(tǒng)的好處是我們能夠
更加容易的寫出高質(zhì)量的代碼。
由于ecs的局限性, 主要用于上層架構(gòu), 不會用于底層架構(gòu)
至于在ecs中需要調(diào)用到的外部api巫员,通常都會在ecs中加個中間層并入已有的ecs系統(tǒng)中
比如要做網(wǎng)絡(luò)同步, 就需要創(chuàng)間一個網(wǎng)絡(luò)相關(guān)的system庶香,再把數(shù)據(jù)同步出去
吐槽一下unity 的ecs系統(tǒng)
unity 的ecs系統(tǒng)更多是在性能上的優(yōu)化方便上的便利,而不是保持ecs本身的簡單化
-
unity ecs系統(tǒng)本身弄的復(fù)雜, 復(fù)雜在下面幾個方面
unity 內(nèi)部隱藏了太多細(xì)節(jié)
隱藏了入口简识, 不方便從整體上來學(xué)習(xí)了解
-
使用來太多attribute, 還有特定結(jié)構(gòu)來實(shí)現(xiàn)基礎(chǔ)功能
比如system 之間的調(diào)用次序
正由于unity ecs系統(tǒng)過于復(fù)雜, 導(dǎo)致無法直接將邏輯代碼拷貝到服務(wù)器