102_Entity 實體
實體 Entity
一個Entity只是一個裝滿Component的容器。我們可以將Component添加到Entity中、從Entity中獲取Component、也可以將一個Component從Entity上刪除。在Entitas-CSharp中,有一種內部/通用的方式來執行這些操作:
entity.AddComponent(index, component);entity.GetComponent(index);entity.RemoveComponent(index);
我們必須使用索引,因為這個容器是以IComponent
數組的形式實現的。在Entitas-CSharp中,我們選擇使用數組是出於性能原因。然而,有些實現選擇使用哈希表(HashMap),使Component類型成為Key,Component實例成為Value。
在你抱怨API太麻煩之前,讓我向你展示如何在實際發開中添加、獲取和刪除Entitas-CSharp中的Component。
先假設我們有個Component PositionComponent
。
public sealed class PositionComponent : IComponent { public IntVector2 value;}
那麼實際上的API是這樣的:
entity.AddPosition(new IntVector2(x, y));entity.position;entity.RemovePosition();
由於我們為Entitas-CSharp實現了一套代碼生成工具(Code Generator),我們最終能直接使用這個漂亮的API。你可以在「器具(Appliances)」關於「代碼生成(Code Generation)」一章中找到有關此主題的更多信息。
Entity的創建
Entity應始終是Context的一部分。這就是為什麼我們不能直接實例化Entity,而必須調用context.CreateEntity()
。Context是一個管理型的數據結構,用於監控Entity的生命周期,你可以在Context章節中找到關於Context的更多細節。
非常重要的一點,雖然可以創建和銷毀Entity,Entitas-CSharp中銷毀的Entity並未真正銷毀,而是在Context中被緩存了起來(pooled in the context)。這是一個避免GC的性能優化。這個優化的副作用是:如果用戶在自己的代碼中保留對Entity的引用,那麼這個引用的使用必須額外小心。
當一個Entity被銷毀時,它將被放入一個臨時池中,並在引用數量是0的時候被重用。
什麼是引用數量?
引用數量是一種內部機制,它確保Entity在不再被引用之前不會被重用。Entity有兩種方法處理引用:
public void Retain(object owner)
public void Release(object owner)
當你想保持對一個Entity的引用時,你必須調用entity.Retain(this);
當你需要刪除引用時,調用entity.Release(this);
,這是非常重要的!這些調用會增加和減少引用計數。 Entitas-CSharp的所有內部類都遵守這種機制,所以你的代碼也應該如此。如果您在保留對Entity的引用的同時不調用保留(Retain)
,則最終可能會引用一個已被銷毀並重新生成的Entity。如果您忘記在保留的Entity上調用釋放(Release)
,它將永遠停留在對象池中,從而使您的內存消耗隨著時間的推移而增長。
Entity的觀察模式(entity observation)
一個Entity可以有多個用戶訂閱的事件,反映到Entity的生命周期上。
以下是Entitas-CSharp當前中所有事件的實現列表:- OnComponentAdded
- OnComponentRemoved
- OnComponentReplaced
- OnEntityReleased
- OnDestroyEntity
這些事件是Context 用於監視Entity 的相同事件。它們也暴露在外部使用,但我不建議直接使用它們。在典型的使用案例中,您更希望擁有一個Group,一個Collector 或一個Reactive System(這些都會在下面的章節中介紹)。
不管怎麼樣,知道這些設施的存在是很好的事情,如果您正在實現一些自己的工具,那麼使用這些內置的設施可能就會變得很重要。
推薦閱讀:
※一道技術美術的面試題
※換個角度去看棋牌遊戲
※在GMS2中製作對話系統(2/2)
※遊戲開發之伺服器技術選型淺析
※GMS2官方教程系列1/8——角色移動