ECS概念
實體組件系統 (ECS) 架構將身份(實體)、數據(組件)和行為(系統)分開。該架構專注於數據。系統讀取組件數據流,然后將數據從輸入狀態轉換為輸出狀態,然后實體對其進行索引。
下圖說明了這三個基本部分如何協同工作:
在此圖中,系統讀取Translation
和Rotation
組件,將它們相乘,然后更新相應的LocalToWorld
組件 ( L2W = T*R
)。
實體 A 和 B 有一個Renderer
組件而實體 C 沒有,這一事實不會影響系統,因為系統不關心Renderer
組件。
您可以設置一個系統,使其需要一個Renderer
組件,在這種情況下,系統將忽略實體 C 的組件;或者,您可以設置一個系統來排除具有Renderer
組件的實體,然后忽略實體 A 和 B 的組件。
原型Archetypes
組件類型的獨特組合稱為EntityArchetype。例如,一個 3D 對象可能有一個用於其世界變換的組件,一個用於線性運動,一個用於旋轉,一個用於其視覺表示。這些 3D 對象之一的每個實例對應於單個實體,但由於它們共享相同的組件集,ECS 將它們分類為單個原型:
在此圖中,實體 A 和 B 共享原型 M,而實體 C 具有原型 N。
要順利更改實體的原型,您可以在運行時添加或刪除組件。例如,如果您Renderer
從實體 B 中移除組件,則它會移動到原型 N。
內存塊Memory Chunks
實體的原型決定了 ECS 存儲該實體組件的位置。ECS 以“塊”的形式分配內存,每個塊由一個ArchetypeChunk對象表示。塊總是包含單個原型的實體。當一塊內存變滿時,ECS 會為使用相同原型創建的任何新實體分配一塊新內存。如果您添加或刪除組件,然后更改實體原型,ECS 會將該實體的組件移動到不同的塊。
這種組織方案提供了原型和塊之間的一對多關系。這也意味着找到具有給定組件集的所有實體只需要搜索現有的原型,這些原型通常數量很少,而不是所有實體,它們的數量通常要大得多。
ECS 不會以特定順序存儲塊中的實體。當一個實體被創建或更改為新的原型時,ECS 將其放入存儲原型的第一個塊中,該塊有空間。然而,塊仍然緊緊地包裝在一起。當實體從原型中移除時,ECS 將塊中最后一個實體的組件移動到組件數組中新騰出的插槽中。
筆記
原型中共享組件的值還決定了哪些實體存儲在哪個塊中。給定塊中的所有實體對於任何共享組件都具有完全相同的值。如果您更改共享組件中任何字段的值,則修改后的實體將移動到不同的塊,就像您更改該實體的原型一樣。如有必要,將分配一個新塊。
當一起處理它們更有效時,使用共享組件將原型內的實體分組。例如,Hybrid Renderer 定義了它的RenderMesh 組件來實現這一點。
實體查詢Entity queries
要確定系統應該處理哪些實體,請使用EntityQuery。實體查詢在現有原型中搜索具有符合您要求的組件的原型。您可以使用查詢指定以下組件要求:
- All — 原型必須包含All類別中的所有組件類型。
- Any — 原型必須至少包含Any類別中的一種組件類型。
- None — 原型不得包含None類別中的任何組件類型。
實體查詢提供包含查詢所需組件類型的塊列表。然后,您可以直接使用IJobEntityBatch迭代這些塊中的組件。
工作Jobs
要利用多線程,您可以使用C# Job system。ECS 提供SystemBase類Entities.ForEach
以及IJobEntityBatch Schedule()
和ScheduleParallel()
方法,用於在主線程之外轉換數據。Entities.ForEach
是最簡單的使用方法,通常需要更少的代碼來實現。您可以將 IJobChunk 用於更復雜的Entities.ForEach
無法處理的情況。
ECS 按照系統的排列順序在主線程上調度作業。當作業被調度時,ECS 會跟蹤哪些作業讀取和寫入哪些組件。讀取組件的作業依賴於寫入同一組件的任何先前計划作業,反之亦然。作業調度程序使用作業依賴關系來確定哪些作業可以並行運行,哪些必須按順序運行。
系統組織
ECS 按World然后按組組織系統。默認情況下,ECS 使用一組預定義的組創建一個默認世界。它找到所有可用的系統,實例化它們,並將它們添加到默認世界中的預定義模擬組。
您可以指定同一組內系統的更新順序。組是一種系統,因此您可以將一個組添加到另一個組並指定其順序,就像任何其他系統一樣。組內的所有系統在下一個系統或組之前更新。如果您不指定順序,ECS 會以不依賴於創建順序的確定性方式將系統插入到更新順序中。換句話說,即使您沒有明確指定順序,同一組系統在其組內始終以相同的順序更新。
系統更新發生在主線程上。但是,系統可以使用作業將工作卸載到其他線程。SystemBase提供了一種直接的方式來創建和調度作業。
有關系統創建、更新順序以及可用於組織系統的屬性的更多信息,請參閱有關系統更新順序的文檔。
ECS創作authoring
當您在 Unity 編輯器中創建游戲或應用程序時,您可以使用 GameObjects 和 MonoBehaviours 創建一個轉換系統,將這些 UnityEngine 對象和組件映射到實體。有關更多信息,請參閱創建游戲玩法。