2014-07-22 14 views
1

我的GameObject我的基於組件 - 遊戲引擎抽象的實現如下:優勢和數組和地圖之間的缺點遊戲對象

遊戲對象

  • 唯一ID
  • isActive flag
  • 組件數組

我一直在閱讀關於基於組件的設計,並且引起我注意的一件事是由於緩存導致數組的線性遍歷很快,所以這使我決定使用基本數組來保存實體/遊戲對象。

現在另一件引起我注意的事情是有些資源將組件從遊戲對象中分離出來。他們所做的是在一個實體經理內部有一張地圖。該地圖將遊戲對象作爲鍵和作爲值的組件數組。在這種情況下,A GameObject只有一個ID。

是否有一個優勢(性能和/或設計明智)有一個地圖附加遊戲對象的組件,而不是在GameObject類內的組件?

此外,GameObjects將從Pool對象合併(循環),以避免頻繁的內存分配。

+1

如果'GameObject'有一個組件數組,你的對象的大小是很大的,因爲它包含了它的東西。如果你有一張保持這種相關性的地圖,那麼'GameObject'的創建/複製/刪除便宜得多。話雖如此,我還建議你考慮'std :: vector'來保存你的組件,雖然這是你原來的任務的正交關係。 – CoryKramer

+0

如果一個'GameObject'已經有了它的組件的引用,並且maps鍵是'GameObject's,那麼這個映射就完全沒用了。一般來說,地圖用於通過某些鍵提供對值的快速訪問,例如'Map '可能有意義。 –

+0

我澄清了一下。在地圖情況下,'GameObject's只有一個ID而不是組件數組。 – starhacker

回答

3

在大多數遊戲組件系統中,您將需要數組和字典(地圖)。

對於線性遍歷(即在更新過程中),該數組用於枚舉對象和組件。

對於通過ID,名稱或其他屬性進行查找,可以使用一個或多個字典來查找相應類型的組件。這主要是在數組上的線性搜索加起來明顯的性能損失時所需要的。

此外,還可能有其他數組存儲按組件排序的遊戲對象,例如具有特定組件(如CombatComponent)的遊戲對象數組。

通常這將被包裝在一個類中,允許您通過索引訪問組件(或遊戲對象),枚舉它們或通過某些標準(如ID)獲取它們。然後可以隨着時間更新類的實現,通過交換更高的內存使用量以獲得更好的性能(例如引入額外的字典來按啓用狀態對組件進行索引或按空間位置對遊戲對象進行索引)來加速對特定組件的訪問。

總之:總是存在折衷。開始使用額外的字典和數組主要是便利性和性能問題,但它絕不是任何一個/或決定。

如果需要按順序枚舉對象,則默認存儲實現應始終以數組開頭。詞典的主要問題是枚舉的順序可能會改變幀的幀,這在遊戲中必須避免。

1

這還取決於你所做的遊戲類型。

根據我的經驗,鬆散耦合的對象幾乎總是執行得更好,因爲內存分配很少發生,而引用對象通常以批處理方式出現,並且出現在特定任務中。我喜歡這種方法,因爲它可以防止你搞亂大量的虛擬表和類層次結構。虛擬指針破壞代碼緩存。因此,在這種情況下,我將對象保存在不同的管理器中,但使用相同的句柄/標識,並且只是跨相關集合運行。

如果昂貴的知名度查詢都參與其中,它往往是便宜保持幾個列表方便和更新它們只在必要時(如時間分片)

另一種方法是使用鏈表與父母建立依賴遍歷樹/子對象只關聯到相關對象(一種基於樹的跳過列表)。這很有用,因爲有些事情要預先構建變換,或者循環遍歷所有發光器,或者首先通過碰撞檢測和響應等運行所有對象。邏輯上,任何類型的「事件」必須發生在您的然後可以在鏈接列表遍歷中翻譯遊戲世界。它爲您節省了管理人員,但是它創建了大量的內存跳躍和管理,以保持父/孩子的最新狀態。

如果你可以向量化你的計算並獲得100倍加速,那麼這是一個很好的理由來看看對齊和打包。有一段時間,我們使用了一個小對象緩存,只保留那些經常需要的內存中的比特,比如變換等等。但實際上,在你到達之前,最終會有很多isXYZ()調用變革,這並沒有真正得到回報。這個想法很好,當時有一些加速,但邏輯錯綜複雜,變得毫無意義。

正確的說法當然是取決於您必須處理的任務和對象或其子集的數量。如果你一時不知道這一點,但你懷疑它可能會失控,這取決於你的時間:如果相當多,鬆散耦合可能只是一件事情。額外的好處是重構類型並不會真的影響你。否則,你可能會更好的只是把所有東西放在一起,並希望最好..