101_Component 組件

組件 Component

Component是ECS中最簡單的原料。它是數據的最原子性的呈現。它可以是空的、有一個或多個屬性,甚至可以被標記為唯一的(類似單例)。接下來我將解釋Entitas的組件實現方式。

最簡單的組件 - 標誌組件 (Flag Component)

我會用 Match-One 項目中定義的組件作為例子。

using Entitas;public sealed class MovableComponent : IComponent {}

正如你所看到的,一個組件是一個實現了IComponent介面的類。它沒有任何屬性,因此它是標誌組件。Flag component是用於定義Flag Entity。在這種情況下,我們說有些東西是可移動的(is Movable對應MovableComponent)。所以如果我們有一個Entity,我們可以通過查詢entity.isMovable並返回true或false。我們也可以要求所有擁有MovableComponent的Entity,但是我想稍後再討論這種用法。

數據組件 (Data Component)

Data Component可以有多個可以存儲純數據的屬性:

using Entitas;public sealed class PositionComponent : IComponent { public int x; public int y;}

在Entitas-CSharp中,我們可以使用以下語句為Entity添加一個Position:

entity.AddPosition(1, 2);

有一種方法來檢查一個實體是否有對應的組件(hasPosition)。我們也可以獲取(position),替換(ReplacePosition)和刪除(RemovePosition)組件。每個實體只能有一種類型的組件集。這就是為什麼我們有Replace方法。但我們可以將所有不同類型的組件結合在一個實體中。這就是為什麼最好將組件儘可能粒子化(thin)。這在肆意組合(improvisation)方面給了你很大的好處。

引用組件 (Reference Component)

一個Reference Component在技術上等同於Data Component,主要是邏輯上的差別。

using Entitas;using UnityEngine;public sealed class ViewComponent : IComponent { public GameObject gameObject;}

從技術上講,Reference Component也是具有多個屬性的Component,但是這些屬性不代表數據。它們引用一個複雜的對象,這有一個更深一層的含義。這些組件很難被序列化,它們指向在運行時創建的一些對象,因此持久化指針是沒有用的。我們將在Receipt章節深入研究Reference Component

操作組件 (Action Component)

這又是一個Data Component的衍生物。只是在這種情況下,屬性是屬於一個功能/操作。

using Entitas;using System;public sealed class DelegateComponent : IComponent { public Action action;}

在這種情況下,我們可以將一個函數/委託/操作存儲在一個組件中,並將其附加到一個Entity中。雖然組件能夠這樣使用,但它的壞處比好處更多,而不是我們將會在Reciept部分討論的那樣。

唯一組件 (Unique Component)

在每個應用程序中,有許多情況下你只想要一個物體的一個實例。這個想法一般呈現在大家多知道並且常常討厭的單例模式中。在Entitas中,我們有類似的但更好的東西。

我們之前討論的每種類型的組件都可以定義為一個唯一組件。

using Entitas;using Entitas.CodeGeneration.Attributes;[Unique]public sealed class GameBoardComponent : IComponent { public int columns; public int rows;}

為此,我們只需要將該類(通過Attribute)注釋為唯一(Unique)的。

該框架(Entitas)將確保在上下文(Context)中只有一個唯一組件實例可以存在(請參閱Context章節)。這就是為什麼在Entitas-CSharp中,我們可以用下面的表達式 - context.gameBoard來獲得一個獨特組件的實例。

怎麼樣,是不是比單例模式更好呢?由於我們將狀態與行為分開,這會比單列模式更好。這個組件也可以被替換和移除。所以它打破了單例模式的習慣用法 - 一個對象在整個應用程序生命周期中是唯一且持久的。一個獨特的組件比單例更像是一個全局變數。

通常來說一個程序需要多少個組件呢?

這個問題始終是專門針對ECS的新手。和往常一樣,正確答案是 - 看!情!況!不過從我的經驗來看,中端核心手機遊戲上,150個組件相當不錯。事實上,我對比了我參與制作的兩個完全不同的手機遊戲,大約都在150個組件左右。也就是說,我用EntitasKit構建的iOS應用程序(Swift實現)包含大約50個組件,也並不令人意外,因為遊戲往往比應用程序複雜得多。

推薦閱讀:

(轉)Unity遊戲開發過程中提升80%開發效率的插件
[Unity]面試題整理(一)
BGE:在3D軟體里做遊戲 (2)
2016年工作與學習總結

TAG:Unity遊戲引擎 | 遊戲開發 |