組件-實體-系統 Entiy-Compoent-System ECS架構整理

繼承體系的問題,爲何要用ECS

面向對象的問題

  • 當一個新的類型須要多個老類型的不一樣功能的時候,不能很好的繼承出來
  • 遊戲開發後期會有很是多的類,很難維護
  • 遊戲中子系統不少,它們對一個對象的關注點每每互不相關,好比渲染.網絡,戰鬥數據,若是都對應一個基礎角色對象,這個類就會很大

ECS,經過組合而不是繼承的方法來進行實體的構建

  • ECS的設計目的是用來把大量的模塊進行集成並解耦,用最小的耦合來集成大量分散的系統
  • 每一個System能夠只關注實體有什麼,而不是實體是什麼,這是與OOP的最大區別
  • 在網絡同步的預測錯誤後能夠很方便的糾正(全部元素都用Component分離了)
  • ECS的一個重要特性就是併發優點,由於提供了數據隔離

Unity推薦ESC的緣由

  • ECS專一於您正在解決的實際問題,即構成遊戲的數據和行爲。
  • 爲了配合使用Job System和Burst 編譯器。
  • 從以對象爲導向的設計轉到以數據爲導向的設計,代碼更爲容易,也更易於他人掌握。

示例

假設一個簡單的遊戲,有石頭,樹,敵人,玩家三種物體
這個時候須要一個新的類型,能夠攻擊的樹php

  • 按照OOP的設計大體是這樣的
  • ECS的設計大體是這樣的

    EvilTree擁有: Position,AI,Sprite,AABB

ECS結構圖示

ECS基礎規則

* Entity輕量級,甚至只有一個Id;
* System沒有狀態, Component 不帶行爲
* System不能調用其餘System的函數,共享代碼要放到Utils裏(如敵對關係),Utils函數無反作用;
* 組件裏複雜的反作用要經過隊列的方式推遲處理,尤爲是單例組件;

實體

一個實體指的是存在於你的遊戲世界中的物體。實體在代碼上就是一個組件的列表。
因爲實體的結構實在是太簡單了,因此不少實現都沒有專門的設計一個實體的數據結構。相反的,一個實體就是一個ID,全部組成這個實體的組件將會被這個ID給標記,從而明確的知道哪些組件是屬於哪一個實體的。若是你想的話,你能夠在運行時,動態的將組件從實體中移除或者增長一個或多個你感興趣的組件。好比說,若是玩家發出了一個冰系魔法,將敵人凍住,你只要簡單的將它的速度組件移除,那麼敵人就靜止住了。

組件

沒有行爲(改變數據),只是用來存儲一些數據(所有公開), 每個組件都描述了實體的某個屬性特徵。
每一個System會以本身的角度對待組件,不一樣的觀察者區別對待主體
單例組件: 屬於單一匿名實體,能夠直接訪問,存放System大部分狀態.好比Ipnut單例,從InputSys中剝離的數據.

系統

真正處理遊戲邏輯的地方.
System不關注實體究竟是什麼,只關心組件集合,在這個集合上執行一組行爲
只會有不多的System改變組件狀態,本身管理複雜性
系統會指明所須要的組件集合,由主邏輯篩選出全部知足要求的實體

守望先鋒的ECS


EntityAdmin是個World,存儲了一個全部System的集合,和一個全部實體的哈希表(ID爲unit32)。html

單例組件

示例:命中處理System

  • ModifyHealthQueue組件,記錄實體身上全部傷害和治療效果
  • MovementState組件,移動數據處理
  • 一組Utility函數處理錯誤糾錯,回滾相關Component

幾個建議git

  • System定義組件的組合時,能夠把組件標記爲只讀
  • 實體生命週期建議當即建立,延時銷燬
  • 某些遺留子系統不能接入ECS時,就不要強行接入,保持子系統的整潔
  • 事實證實,網絡同步真的很複雜,因此必須儘量的與引擎其他部分解耦,ECS是解決這個問題的好辦法。

Unity中的ECS

在PackageManager中下載Entitiesgithub

參考

相關文章
相關標籤/搜索