如何在实体组件系统中查找具有特定组件的实体?

问题描述 投票:2回答:2

如何在实体组件系统中查找具有特定组件的实体?

在我目前的实现中,我将组件存储在一个 std::unordered_map< entity_id, std::unordered_map<type_index, Component *> >

因此,如果系统需要访问具有特定组件的实体,那么访问它们的最有效方法是什么。

我目前有2个想法:

  1. 遍历地图并跳过没有这些组件的实体。
  2. 创建“mappers”或“views”,其中包含指向实体的指针,并在每次将组件分配给实体或从实体中删除时更新它们。

我看到了一些使用bitmasks等的方法,但这似乎不具备可扩展性。

c++ game-engine
2个回答
1
投票

您的情况需要std :: unordered_multimap。

“find”方法将返回第一个元素的迭代器,该元素与multimap中的键匹配。 “equal_range”方法会返回一对,包含与您的键匹配的第一个和最后一个对象的迭代器。

实际上,unordered_multimap允许你创建的是一个内存中的键值数据库,它存储同一个键的一堆对象。

如果你的“查询”比“给我所有带有组件T的对象”变得更复杂,并变成类似“给我所有组件同时具有组件T和B”的东西,那么你就更适合创建一个类有unordered_multimap作为成员,并有一堆实用程序方法来查询的东西。

更多关于这个问题:


0
投票

我这样做的方法是从组件(32位)向实体存储一个反向索引。它增加了一些内存开销,但是我的组件的总内存开销大约是8个字节,这对我的用例来说通常不是太糟糕,每个实体大约4个字节。

现在,当您拥有实体的反向索引时,在满足具有2个或更多组件类型的所有实体的查询时,您可以执行的操作是使用并行位集。

例如,如果您正在寻找具有两种组件类型的实体,MotionSprite,那么我们首先迭代运动组件并为拥有它们的实体设置相关位。

接下来,我们遍历sprite组件并查找已通过运动组件设置的实体位。如果实体索引同时出现在运动组件和精灵组件中,那么我们将实体添加到包含两者的实体列表中。该想法的图表以及如何多线程并池化实体并行位数组:

enter image description here

这给了你一个线性时间和一个非常小的m的集合交集(每次迭代非常非常便宜的工作,因为我们只是标记和检查一点 - 比哈希表更多,更多,更便宜,例如)。实际上,我可以使用这种技术在两秒内执行一组交集,每个集合中有1亿个元素。作为奖励,通过一些小的努力,如果您使用bitset来获取属于2个或更多组件的实体的索引,您可以使它按照排序顺序返回实体,以获得缓存友好的访问模式。

有很多方法可以比线性时间(Log(N)/Log(64))更好地实现这一点,尽管它实际上可以在一个毫秒内实现两个包含一亿个元素的集合之间的集合交集。这是一个提示:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.