游戏数据库设计帮助 / 用户等级 / 进度

4

抱歉这篇文章有点长而且很啰嗦。我正在创建我的第一个真正的游戏化Web应用程序,需要一些帮助来思考如何构建数据结构。

背景

用户需要在每个类别中完成任务才能升级。我有UsersTasksCategories表,以及一个UserTasks表,它连接了这三个表。(“用户3已经在类别8中添加了任务42。现在他们已经完成了它。”)这一切都很好,而且工作得非常好。

挑战

我不确定如何最好地跟踪每个类别中朝向每个等级的进度。业务规则如下:

  1. 您必须在每个类别中获得一定数量的积分才能升级。
  2. 如果您在Cat 8中获得所需的积分,但仍然有其他工作要完成该级别,则任何新的Cat 8积分都计入您的总分,但不会“滚动”到下一个级别。
  3. 类别的数量很少(目前为五个),但绝对不是固定的。
  4. 升级所需的积分将会因级别而异,可能是一个公式或查找表。

因此,挑战在于跟踪每个用户在每个类别中朝向下一个级别的进度。我想到了几种潜在的方法:

可能的解决方案

  1. 为每个类别添加一列到用户表中,并在每次用户升级时将它们全部重置为零。
  2. 使用单独的UserProgress表,每个用户每个类别都有一行,记录他们拥有的积分数。(基本上是#1的多对多版本。)
  3. UserTasks表中添加userLevel列,并使用某种SUM语句来推导他们的进度。

他们当前的等级将是User表中的一个简单整数。

优缺点

(1)似乎是最简单直接的方法,但也是最不灵活的。也许我可以使用基于类别ID的命名约定来帮助克服其中的一些问题。(例如使用像“select cats; for each cat, get the value from Users.progress_{cat.id}”这样的代码。)这也是我失去最多数据的方法——我将不知道哪些积分计入了升级。我没有为此设想任何需求,所以也许我不在乎这个。

(2)看起来很复杂:每次添加或删除用户或类别时,都必须维护另一个表。我预见到同步方面的挑战。

(3)介于前两者之间——比#2更干净,但比#1不那么直观。为了找出用户的进度,我需要使用稍微复杂的SQL语句,例如:

SELECT categoryId, SUM(points) from UserTasks WHERE userId={user.id} & countsTowardLevel={user.level} groupBy categoryId

嗯...这似乎并不那么糟糕。我想我正在说服自己选择#3,但我很希望得到任何意见、建议或其他想法。


跨帖 http://gamedev.stackexchange.com/questions/7861/database-design-help-for-game-user-levels-progress - chaos
1
是的,就像我在那里说的一样:我在发布这里之后才想起它的存在。但是坦率地说,我宁愿在那里关闭它而不是在这里。那个社区只有这个社区的1/100大小,而且问题肯定足够普遍。我不会感到惊讶,如果我没有得到任何答案:问题太长了,而且我基本上在最后回答了它。我们会看到的... - sprugman
祝你的游戏好运!计划这些事情总是很有趣。 - ClosureCowboy
2个回答

1

我会投票给第三个选项。

每当我可以聚合现有数据而不是单独存储“运行总数”时,我都会抓住机会。对于像StackOverflow这样的大型网站,由于性能原因,这可能不可行,但对于中小型网络游戏来说,它应该完美地工作。

通过避免保留“运行总数”,您通常可以避免在多个位置执行相同(或类似)的操作。举个非常简单的例子,在论坛中,如果手动更新post_count而不是计算为COUNT,那么删除帖子也将需要更新post_count。您拥有的此类情况越多,您就越有可能出现错误或者玩家注意到两个或更多数字不完全相加的“WTF?”时刻。

除了性能之外,使用简单聚合的主要缺点是,有时您不希望现有总数受到您正在进行的更改的影响。我从未遇到过这种情况,但我确信它们存在。


0

我绝对不会选择第一种方法,而我想提供第四种方法。

如果我理解你的意思正确,用户需要在给定的类别/级别中获得5分才能访问下一个类别,但可以在那里获得总共10分,其中额外的5分不计入下一个类别。最简单的方法是制作这样的表格:

| user_id | category_id | score |   (primary key = user_id, category_id)

不要害怕存储总分,您可以在查找表/公式中检查“从表中选择得分,其中用户ID =?且类别ID =?”是否足够高。

这样,您就可以拥有非常简单的查询、非常简单和可扩展的数据库设计(添加新类别或更改评分没有问题)。

如果以后您想要转移分数,只需使用SQL的sum函数获取用户的总分,然后将其减去所需的给定类别的总分即可。


这听起来有点像我的第二个问题,但我不明白的是,如果他们有六个点,每个级别需要五个点,除非我每次升级时重置所有值,否则我将不知道第六个点是否超出了一级,或者计入了二级。 - sprugman
啊,原来你们有超出点数的情况。那么,不要按阶段存储,而是为每个等级存储点数,这样就可以得到:第1阶段有1级、2级、3级和4级。要完成第1阶段,玩家至少需要15个点数。因此,如果查询数据库中第1、2、3、4阶段的总点数大于15,则解锁第2阶段。 - Roy T.
我没有阶段。我有级别和类别。我不确定您是否建议我也添加阶段,还是仅使用不同的术语。无论如何,我选择了我的#3。它似乎运作得相当不错,但还是感谢您的帮助。 - sprugman
嘿,我的解决方案实际上与第三个很接近,我认为你走这条路会没问题的!祝你的网络游戏好运! - Roy T.
哇,你的意思是在用户表中会有类别ID、名称、分数,并将其与用户表进行关联,并添加每个用户的总分数,所以表中会有许多类别ID。你是如何保存这些数据的?是以JSON格式还是其他方式?那么,你将如何根据积分或分数来对用户进行分级呢? - ujwal dhakal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接