【问题标题】:Storing and saving player backpack(inventory) in database在数据库中存储和保存玩家背包(库存)
【发布时间】:2017-05-14 16:19:05
【问题描述】:

有没有最好的方法将玩家背包等数据存储在关系数据库中?

假设我想将玩家背包存储在数据库中。

表“eq”的数据库模型如下:

playerId | slot | itemId | amount

现在假设我在数据库中有这一行:

1 | 10 | 20 | 99

这意味着,ID 为 1 的玩家在第 10 个位置有 99 个 id 为 20 的物品。将这些数据读取到游戏中很容易(如果槽 Y 的行不存在,则表示它是空的),但保存这些数据有点棘手。为什么?因为如果玩家使用 99 个 id 为 20 的物品,他的背包在 RAM 中将是空的,但在数据库中仍然会有一行。玩家将物品移动到另一个插槽时也是如此,如何知道何时删除数据库中的插槽?

这是我的两个想法,看起来很糟糕:

  1. 当玩家注册新账户时,我可以在“eq”表中添加 X 个空行,带有他的 id 和以下插槽(1、2、3、4...),然后保存就迭代player eq 并更新 每一 属于 player 的行

  2. 当保存过程开始时,删除所有属于玩家的“eq”行,然后将这些行插入到数据库中,这些行在哪里(保留空槽)

【问题讨论】:

    标签: mysql database database-design relational-database inventory


    【解决方案1】:

    如果您的背包是固定尺寸或很少更改且不太大,则在注册期间为所有插槽创建行可能会有好处。我认为这意味着索引只有在添加或删除玩家时才会更新,优化器使用的统计信息应该保持稳定和有效。对这样的表使用INSERT ... ON DUPLICATE KEY UPDATE ... 查询可能是个好主意,以确保它在意外删除行的情况下能够自我修复。它不应该比只做一个UPDATE 效率低。

    您还应该能够进行单独的插槽更新。每当玩家使用背包中的物品时,UPDATE 该插槽的内容。如果添加了新项目,请发送INSERT 命令。如果使用了插槽中的最后一项,则改为发送DELETE 命令。当物品被移动时,您只需UPDATE该行即可更改插槽号。您应该在内存中有足够的上下文来确定要做什么,并且任何时候都只能有一个玩家登录帐户,对吗?如果您预先创建插槽,您只需执行合适的 UPDATE 命令而不是 INSERT / DELETE 命令。

    如果由于某种原因您无法更新单个插槽,您可以在两个查询中保存整个背包。我会发送一个INSERT ... ON DUPLICATE KEY UPDATE ... 命令,其中包含每个包含项目的插槽的值。然后我会发送一个DELETE FROM eq WHERE playerId = ... 查询,如果背包不是空的,则将AND slot NOT IN (...) 附加到已填充插槽的列表中。这样,您就不会删除和创建不必要的行,这应该会更有效率。使用预先创建的插槽,您可以在一个查询中完成。

    【讨论】:

    • 我考虑过实时更新数据库(如果玩家得到新项目使用 INSERT,如果他把它扔掉使用 DELETE 等)但我担心性能,而且主键会增长非常快。目前我正在保存玩家退出时的玩家位置、等级和金币等数据,所以我不知道这是否是个好主意。
    • 您的 eq 表使用复合键 (playerId, slot),因此自动递增键大小不是问题。即时但异步的更新可以为成千上万同时在线的用户工作。如果没有,保存整个背包应该没问题,但我建议定期保存,而不是仅在注销时保存,以防止由于客户端崩溃或断电而造成重大损失。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2014-06-29
    • 1970-01-01
    • 2017-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多