多人在线游戏编程中最常见的新手错误是什么?

4
你看到过哪些新手错误,以及如何解决?
其中一个经常出现的问题是没有对客户端进行任何检查。
例如:
- 用户反编译Flash游戏源代码或监听网络流量,看到高分数据的去向并将虚假的高分发送到那里,而不是真正玩游戏。 - 用户使用修改器获得物品,即使该物品在当前关卡中可能不会出现。这样就像“客户端X获得物品Y”一样发送到服务器,并且服务器只接受它。
简单的解决方法当然是将游戏客户端视为与服务器交互的API。然后用户可以尽情使用训练器和其他内存操作,但服务器只会告诉您不能这样做。将服务器视为具有游戏规则的数据库,可以在其上查询内容。
例如:
- 客户端:启动游戏 - 客户端:连接到服务器 - 客户端:从服务器查询可用资金的金额 - 用户:启用将资金设置为无限的修改器 - 客户端:server.buyItem('非常昂贵') - 服务器:检查游戏状态(用户现在可以购买物品)。检查player[0].money ->没有奖励。 - 客户端:server.buyItem('可以得到这个') - 服务器:检查游戏状态(用户现在可以购买物品)。检查player[0].money,ok。player[0].items.add('可以得到这个')将从player[0].money中减少其成本。然后通知客户端send(player[0],'items','可以得到这个'); send(player[0],'money',player[0].money)。
另一种方法是记录客户端的动作并将其发送到高分服务器,服务器会播放它。当然,这可能会导致记录非常大。

+1 - 或许将你问题的第二部分移至回答中会更好? - Andy Mikula
有没有什么我没注意到的含义,为什么这是一个无效的问题?请关闭和投票的人给我指点一下... - Erik Forbes
这是一个开放性问题,没有单一正确答案。即它是主观的。 - Pyrolistical
没有问题。这就是为什么我投票关闭的原因。 - Robert S.
问题在帖子开头和主题中。在我看来,这是一个完全有效的问题。 - strager
这篇文章读起来像是围绕一个问题构建的博客文章。 - Robert S.
3个回答

6
毫无疑问,对客户端的盲目信任是不可取的。在我正在开发的游戏中,我们现在将所有的“业务逻辑”都放在服务器端处理,只让客户端向我们发送他们要执行的指令,比如“玩家B想向右移动”,但是服务器会计算出实际应该向右移动多远。这样做会增加性能开销(当然还有延迟问题可能需要更好地处理),因此一个可能的折中方案是将重度计算放在客户端上,同时仍在服务器端进行检查;例如检查客户端玩家在更新之间是否移动了超过规定时间内所能允许的最大距离,比如如果最大玩家速度是200单位/秒,则如果在0.5秒后收到更新信息称其移动了150个单位,则将其踢出。

当然,这并不能完全防止有人编写机器人来发送这些按键命令,因此还有其他方法来防范此类行为。但是,完全没有验证是一个非常新手错误(我承认在我采取捷径时也曾犯过这种错误)。


+1 - 比我的回答更好说。 =)处理服务器端玩家移动的一种方法是通过客户端预测代码,尽管这很难完美实现。 - Erik Forbes
客户端预测代码?嘿?我还从未听说过。你有一个解释的链接吗?我很感兴趣 =) - Smashery
它被称为插值,几乎所有现代FPS引擎都在使用它。(例如,在Source引擎中可以通过cl_interp进行调整。) - strager

6
Valve采用的方法(至少曾经)是让客户端和服务器独立模拟游戏。然后,服务器进行权威模拟并向所有客户端发送状态更新以纠正其错误/黑客攻击尝试。
例如,如果您按左箭头,您的角色将立即向左移动;不需要等待服务器说“好”。但是,如果您穿过了墙壁,下一个服务器更新将使您出现在墙壁旁边,因为服务器认为它是实心的。
同样,如果客户端看到一个角色向前移动,它会假设它将继续向前移动,直到服务器返回授权响应。
这种方法打败了黑客攻击,因为服务器做出主要决策(并在模拟过程中执行合理性检查),并且处理延迟,因为客户端进行预测,直到他们收到服务器消息。
与“信任客户端”相关的另一个重大错误是认为您的网络协议无法被伪造。人们往往认为,如果他们向服务器发送二进制块,这些二进制块永远不会被逆向工程,并且没有人会尝试干扰数据以查看发生了什么。这导致了各种各样的问题。

1

你们已经涵盖了服务器信任客户端可能出现的所有问题。我想不到还有其他实际问题。

因此,我不想告诉你会出现什么问题,而是看看会出现什么好处。

Valve在他们的netcode上投入了大量的工作。可以去研究一下。


实际上,Valve 是“信任客户端”的主要罪魁祸首之一。如果一个玩家在服务器和观察者的视野范围内处于掩护中,但在另一个玩家的客户端上可见,那么他仍然可以被另一个玩家射击。Valve 偏爱这种方式来设计他们的游戏,但这并不是普遍适用的好解决方案。 - Kylotan
不好意思,服务器在所有情况下都有最终决定权。如果你所说的是真的,那么就有可能创建一个黑客程序,在不接触受害者的情况下杀死他们。 - Pyrolistical
服务器有最终决定权,但它依赖于对延迟的估计来“倒回时间”,而这个估计最终可以被客户端操纵。这样做可以让射手感觉更好,但代价是不一致性。 - Kylotan
时间倒流仍然在服务器上进行,因此尽管您可能会从拐角处受到伤害,但这是因为服务器已经计算出客户端在过去击中了您。这不能由客户端操纵,这是为了减少延迟,而不是信任客户端。 - Pyrolistical
1
虽然客户端可能会增加延迟,以使子弹绕过角落的效果更加明显,但这并不给他们带来任何优势。他们本可以提前发送相同的信息,并更快地击败玩家。 - Pyrolistical

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