我目前正在做一个小型地牢模拟游戏。游戏非常详细,随着时间的推移,我计划有一个代表“怪物”的类的+200 k实例。它们包含了那个怪物的特权、技能和历史。比如他用了多少药剂,他住在哪里,他的巡逻路线是什么等等。
我开始用SQLite来实现这个功能,并使用一个简单的表“怪物”,它包含了所有的数据。这允许我使用SQL查询来查找每个帧上的模拟计算所需的怪物。例如:找到所有在A点巡逻的怪物,或者找到所有使用药剂X的怪物等等。不幸的是,在每一帧上查询SQLite几次很快就减慢了游戏的速度。尽管这是一个2D游戏,我需要宝贵的毫秒来进行模拟计算。
另外,我需要JOIN在未来做图表:我需要知道一个怪物是否攻击了另一个怪物,或者一个怪物是否是另一个怪物团队的成员。这将进一步减缓事态的发展。
有没有人对如何处理这件事有任何建议?
我的数据类似于这样的东西:
发布于 2017-09-03 12:44:43
基于前面的答案/注释以及您对它们的回答,我假设您决定继续使用SQL,但是您希望有一种更好的方法来读取/处理它。因此,我的回答只关注这个方面,并且只与设计相关,而不是其他建议(比如使用不同的SQL引擎)。
您的DB中的主要问题,正如它在您最初的问题中所反映的,是给定的怪物的所有方面都在一个单一的记录中,都在同一个表中。这使得这张桌子随着时间的推移而变得巨大。此外,此设计还使您的DB和代码难以维护和发展。
虽然将怪物的所有细节保存在一条记录中听起来可能是“正确的”(也许,在代码本身中包含一个单独的对象),但这并不是一个好的决定。在您的“世界”中建模的对象属性与在软件中建模的对象属性之间应该有明确的分离。例如,怪物的位置可能经常被更改,而它的名字却不是。由于您将所有数据保存在一个表中,所以对位置的任何更改都是在保存所有其他属性的同一表上完成的,这使其成为一个非常繁重的操作。
相反,你应该做的是:
这样,任何读取和更改都只在相关的上下文中进行;例如,更改怪兽的位置只会更改locations表,而不会影响具有更持久详细信息的表。只要您有好的索引,并且只过滤那些您感兴趣的数据,联接就不应该花很多时间。除了加快查询速度之外,这种设计更加灵活。例如,如果您想向怪物添加一种新类型的属性,您只需添加一个新表,或者使用一个具有类似数据的现有表(例如,怪物的设备)来保存它。
如果查询很大程度上依赖于“地理”位置,并且仍然希望使用关系数据库来处理它,则可以考虑在空间查询中更好地支持其他类型的DB。
哈哈!
发布于 2016-06-01 14:51:40
如果您没有使用实体组件系统,请考虑将游戏迁移到使用实体组件系统。每一位相关数据都可以存储在一个自包含的组件中,并且实体本身是标识该组件的某种不透明标识符。当使用ECS,而不是有一个游戏实体与一堆数据挂起,你扭转了关系。特定类型的所有组件一起存在于一个大池中,而您的实体只是一个标识符,它指定了它们所关心的这个池中的哪个组件。这允许您进行批处理组件更新。如果在每个带有库存的怪物上都有一个库存组件,那么您的所有库存组件都可以或多或少地连续存储在内存中。这意味着在处理它们时,您具有很高的缓存一致性,这将大大提高性能。
这也可能是,你只是试图做太多的每一帧。对于实体组件系统,您可以将特定的子系统节流到每个X帧或每X秒(如果需要的话)。也许AI组件只需要运行一秒钟来思考下一步该做什么,但是它们需要不断地移动,这样您就可以更新每个帧的位置。或者,把一个图表和图表组合在一起需要花费太长的时间才能在一个框架中完成,因此每隔一帧就计算一次,或者将处理分割成两个框架,这样就可以在框架上迭代一半以上的实体,在第二个框架上迭代剩下的部分。你有很多方法可以把它分开。
如果您以前没有见过组件系统,这里有更多关于组件系统的读物
发布于 2016-05-29 07:00:18
据我所知,你的主要问题是找到最优的方式来存储你的怪物。例如,您可以使用一些树数据结构来查找飞机上有效需要的怪物。这些数据结构之一是BSP (二进制搜索分区)树。本文简要介绍了分区。Qt的图形视图框架使用了这种方法。有关它的更多信息,您可以在http://doc.qt.io/qt-4.8/graphicsview.html上看到
https://stackoverflow.com/questions/37506155
复制相似问题