組合優於繼承
ecs的概念很早就有了,最初的主要目的應該還是為了改善設計。
e-c-s三者都有其意義,e-c是組合優於繼承,主要用以改善oo的繼承耦合過重以及多繼承菱形問題。
oop常見設計里,每個gameobject有父類,子類繼承來實現不同類型的對象,很容易產生過多\過深的繼承以及多繼承,而這兩者理論上都不好(依賴、冗余),
繼承更應該用來隔離接口與實現(父類提供接口,子類提供實現,調用方只關心父類接口,不關心具體子類實現),而不是用來重用父類的代碼。
Entity抽象成容器
e-c里gameobject是entity,只是個類似容器的抽象概念,entity里包含的component決定了對象是什么
component可以給不同的gameobject重用,通過組合多種component而不是繼承來構造不同的對象。
Unity中的ECS
unity一直以來都是component based,可以看成e-c,此外還有很多現代引擎也是e-c(ue、cryengine等).
對同一類型的component,通常會進行相同的操作(比如用render組件進行渲染),一個直觀的想法就是把這些操作集中在一起,就是system。
一個理想的設計里,包含多種不同的system,每個system只處理一個類型的component,每幀對所有compoent實例進行相同的操作,繼而可以做到數據和邏輯分離,component里放純數據,邏輯在system里。
ECS的好處有幾個
-
邏輯集中在system里,職責單一,讀\改\控制(初始化、順序依賴等等)都方便。
-
容易擴展,很容易新增e\c\s. 新增任何entity,這些entity上有各種component,這些component可以(自動)共享現有的system,不需要單獨寫。
-
靈活,e-c-s之間,s-s之間,e-e之間,c-c之間耦合較松,便於讀\改\擴展。理想情況下不同的system之間,不同的compoent之間沒有任何依賴,但通常很難做到。
-
cache friendly, system會連續對同一類component進行操作,保證了時間上的局部性(連續性),如果這些component能保證空間上的局部性(內存布局連續),則顯而易見對緩存是很友好的。
-
simd, 如果能保證同一個system對大量compoent實例的操作順序無關,那么很自然的可以並發。 但實際中,component很難完全獨立,經常需要和其它component進行交互,也就是system很難做到只負責一類component,通常需要和多種component(甚至其它系統)進行交互,交互的開銷,遍歷compoent的開銷都需要考慮。
摘自:a(704757217)