用于基于类型的查询的最佳数据结构是什么?
我正在制作一个游戏,在这个过程中我遇到了一些问题。
我有许多不同类型的游戏元素。这些都是Entity
类型。
实体有很多种类型,包括可见且需要在屏幕上绘制的实体。这些实体的类型为VisibleEntity
,它扩展了Entity
。
像这样,我对游戏中的元素有许多不同的层次类型。
我的问题是:
在发出以下类型的查询时,哪种数据结构具有最佳的运行时复杂性?
1) 获取 Entity
类型的对象
2) 获取 VisibleEntity
类型的对象
3) 获取 SomeSpecificGameObject
类型的对象
最简单的解决方案是将它们全部存储起来放在一个列表中,并遍历它们全部,如果它们是指定的类型,则将它们添加到要返回的列表中。
显然,对于屏幕中的某些元素每帧都进行计算是不可行的。
跟踪这一切的最佳方法是什么?
我很感激任何回应!
I am in the process of making a game, and in that process I have come across a bit of a problem.
I have many different types of game elements. These are all of type Entity
.
There are many types of Entities, including ones that are visible and need to be drawn on the screen. These entities are of type VisibleEntity
which extends Entity
.
Like this, I have many different hierarchical types for the elements in the game.
My question is this:
What data structure has the best run-time complexity when issuing the following types of queries?
1) get objects of type Entity
2) get objects of type VisibleEntity
3) get objects of type SomeSpecificGameObject
The trivial solution is to store them all in a list, and iterate through them all, and if they are of the type specified, add them to a list that is to be returned.
Obviously, it is not feasible when computation is done at every frame for certain elements in the screen.
What is the best way to keep track of all this?
I appreciate any response!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
另一个简单的解决方案是为每种类型维护一个列表。将每个列表存储在哈希图中,以类型作为键。它几乎是您能得到的最快速度,并且每个项目只花费您一个指针。它还使得将同一对象添加到多个列表成为可能。这将处理你的层次结构。
如果要减少上述方法所需的空间,请让每个实体列表对象还存储指向其子类列表的指针。这样,VisibleEntity 将仅存在于 VisibleEntity 列表中,而不存在于其子类的列表中。要查找所有 VisibleEntities,您可以对主列表进行哈希查找,然后对子类的子类进行递归搜索。这是一个简单的树结构。
根据树的高度和对象的数量,第一种方法可能会更好。这是复杂性与时间与空间的权衡。
The other trivial solution is to maintain one list per type. Store each list in a hashmap, with the type as the key. It's about as instant as you can get, and will only cost you one pointer per item. It also makes it possible to add the same object to more than one list. That will handle your hierarchy.
If you want to reduce the space required by the approach above, have each list-of-entities object also store pointers to the lists of its subclasses. That way, a VisibleEntity would live only in the VisibleEntity list, and not in the lists for its subclasses. To find all VisibleEntities, you do a hash lookup for the the main list, and then do a recursive search through the children for the subclasses. This is a simple tree structure.
Depending on the height of your tree and the number of objects, you might be better off with the first approach. It's a complexity vs time vs space tradeoff.
我真的不认为使用类层次结构来指示对象是否具有某个属性是最好的主意。
您可能希望将可以在游戏引擎中渲染的对象保留在 八叉树 中,当然它们需要有某种绘制方式;因此这可能是类型的一个很好的候选者(从接口是类型的意义上来说)。
至于其他任意属性,您可以通用地表示它们,然后维护索引以便快速检索,或者像您所说的那样,将它们保留在列表中并具有一个简单的过滤函数,可以返回匹配特定条件的对象子集。如果对象不是太多,那么第二种方法应该可以正常工作。 “太多”的阈值是您可能需要通过一些测试找出的值。
I don't really think that using a class hierarchy to indicate whether or not an object has a certain attribute or not is the best idea.
You might want to keep objects that could be rendered in the game engine in an octree, and certainly they will need to have some way of being drawn; so that may be a good candidate for a type (in the sense that an interface is a type).
As to other arbitrary attributes, you can represent them generically and then maintain indices for quick retrieval, or like you said, keep them in lists and have a simple filter function that can return you a sub-set of objects that match specific criteria. If there aren't too many objects then the second approach ought to work fine. The threshold value for 'too many' is a value that you'll probably have to figure out with some testing.
这实际上取决于对象的数量。现代 CPU 每秒循环数十亿次。假设检查并添加到列表需要 10 个周期,并且每秒执行 100 帧,则为每帧迭代 1000 个元素的列表将导致 cpu 利用率为 0.1%。所以相反,天真的解决方案是非常可行的,除非你有数千个游戏对象,或者需要每帧多次按类型查询。与往常一样,建议是实施可能有效的最简单的方法,衡量性能影响,并仅在影响显着时进行优化。
也就是说,下一个最简单的事情是:
您
可以使用该方法来概括为按类以外的事物进行索引,只需为映射使用另一种键类型,并在适当的时间从类别集中插入和删除。
That really depends on the number of objects. A modern cpu cycles several billion times each second. Assuming the check and add to the list takes 10 cycles and you do 100 frames per second, iterating over a list of 1000 elements for each frame will cause a cpu utilization of 0.1%. So on the contrary, the naive solution is very feasible unless you have thousands of game objects, or need to query by type many times per frame. The recommandation, as usual, is to implement the simplest thing that could possibly work, measure the performance impact, and optimize only if that impact is significant.
That said, the next simplest thing is to do:
which you'd use like
The approach can be generalized to index by things other than classes, simply use another key type for the map, and insert and remove from the category sets at appropriate times.