如何编写网络游戏?[关闭]


73

基于为什么开发MMO如此困难?

网络游戏的发展并非易事。不仅要克服延迟,而且还要防止作弊,状态管理和负载平衡,这是一大障碍。如果您没有编写网络游戏的经验,那么这将是一个困难的学习练习。

我知道有关套接字,服务器,客户端,协议,连接之类的理论。

现在,我想知道如何学习编写网络游戏:

  • 如何平衡负载问题?
  • 如何管理游戏状态?
  • 如何保持事物同步?
  • 如何保护通信和客户端免受逆向工程的影响?
  • 如何解决延迟问题?
  • 应该在本地计算哪些内容,在服务器上计算哪些内容?
  • ...

是否有关于此的好书,教程,网站,有趣的文章或其他问题?

我正在寻找广泛的答案,但是也可以使用特定的答案来学习区别。


4
是的,有书籍,教程,网站,有趣的文章以及与此有关的其他问题。
莉吉特

2
我添加了赏金来推动该问题而不修改它,并给用户一个回答的理由,因为该问题值得回答,因此,最佳回答者在其工作中享有声誉,但没有一个答案可以回答问题。
塔玛拉·维斯曼

Answers:


61

除了其他答案中链接的文章之外,我还可以介绍Arianne项目的经验。

如何保持事物同步?

我们围绕动作和感知的概念构建了框架“ Marauroa ”:动作从客户端发送到服务器,并携带用户输入,例如(向左走,攻击怪物47,说“你好”)。感知从服务器发送到客户端,告诉客户端周围的世界状况。那些感想无处不在。根据游戏的不同,我们使用30毫秒至300毫秒的翻转时间。

我们有两种类型的感知:在登录时和玩家进入新区域(区域)时发送完整感知。之后,发送差异感知,仅包括经修改对象的经修改属性(例如位置),当然还包括新对象和已删除对象。

如何解决延迟问题?

我们坚信“服务器永远是正确的”。客户端会进行一些预测,例如平稳步行,碰撞检查等。但是,如果客户端和服务器不同意某件事,则服务器获胜。子项目Stendhal(一个2D RPG)默认情况下使用300ms的转换时间(在客户端进行了大量的平滑操作)。这使得Stendhal非常耐滞后。

注意:其他一些游戏会在一定程度上信任客户端,以最大程度地减少网络延迟的影响。在《魔兽世界》中,它经常被用于战场之一,称为“战歌峡谷”。带有旗帜的玩家可以选择两种方式:通过隧道的中间位置和沿着山坡的右眼位置之一。因此,作弊玩家朝着隧道奔跑,然后为自己造成了滞后。服务器和其他客户端将继续看到他向服务器运行。但是过了一会儿,该客户端可以告诉服务器它已驶向山丘。WoW将检查最后传输的坐标与当前坐标之间的距离是否在该时间段内,并接受。

使用UDP与TCP

在早期版本中,我们使用UDP来减少TCP的开销。我们自己处理丢失的数据包。在项目的早期阶段,这非常完美。但是,几年前,当服务器从某个家庭DSL连接移到一个真实的数据中心时,我们遇到了很多问题。UDP对防火墙硬件的CPU功能(或至少在5年前是非常苛刻的):必须将规则集应用于每个单个UDP数据包。但是,对于TCP,规则集仅适用于前3个数据包。之后,建立连接。随后的所有数据包都将绕过常规规则集,因为它们在连接跟踪表中或没有SYN标志。

如何保护通信和客户端免受逆向工程的影响?

Arianne是完全开源的,其中包括客户端,服务器,图形,音乐。当然,其中包括我们的协议文档,甚至包括用于调试的分析器。

可以很容易地防止通信受到第三方使用SSL的未经授权的嗅探。

但是,要保护它免受逆向工程是不可能的。当然,您可以对其进行混淆并使用反调试技术。但是最后,您不能阻止您对用户赠送的软件进行反向工程。尽管开发人员在反调试技术上投入了大量精力,但有关如何进行Skype反向工程的演讲非常有趣:http : //recon.cx/en/f/vskype-part1.pdf

注意:在某些国家/地区反向工程是非法的,或者允许在许可或ToS中添加一段以禁止反向工程。但是还有其他一些国家(例如我所居住的国家)明确允许在开发兼容的数据存储格式或传输协议,许可证中的条款或ToS禁止这样做的情况下进行逆向工程。(据我所知,本节内容全都不是律师)

应该在本地计算哪些内容,在服务器上计算哪些内容?

我们计算与服务器上的游戏逻辑相关的所有内容。客户将预测某些事件,以使游戏顺利进行。但是最后服务器总是正确的。

预测的事件例如是发生碰撞时停止运动。Stendhal使用网格定位元素。从服务器的角度来看,每个实体的左上角正好在一个正方形上。但是客户将在瓷砖之间平稳地移动它们。它还将绘制伪3d效果。因此,客户端中以1x1为基数的实体可能会更高。

如何平衡负载问题?

尽量保持简单,以简化维护。

静态内容的负载平衡在http服务器群集和内容分发网络领域是众所周知的。

游戏服务负载平衡的一个相当简单的概念是将服务器划分为多个区域/区域。因此,区域AC位于一台服务器上,区域DF在另一台服务器上。如果您无法从一组中的区域查看到另一组中的区域,则这特别容易。您需要在其中进行一些检查,以便客户端只能连接到负责播放器所在区域的区域服务器。

将播放器从一台服务器转移到另一台服务器的最简单方法是将其写入数据库,告诉客户端连接到另一台区域服务器,并将它们与当前服务器断开连接。然后,客户端将连接到新的区域服务器,该服务器将从数据库中加载它。(由于仍然需要从/存储到数据库代码的负载,因此稍后可在服务器之间进行直接通信以进行切换)。

通过以下方式需要一些其他全局服务:登录时,必须告知客户端连接到正确的区域服务器。您可能需要一个全球聊天系统。

我在“ 如何在MMO中​​实现负载平衡”上详细介绍了此主题


1
您提到UDP需要更多的CPU,但是您没有提到TCP在处理数据包之前至少需要在客户端和服务器之间进行三趟行程,并且将数据包缓冲直到收到所有先前的数据包,这意味着您可能会感到荒谬等待不再相关的数据包的延迟量。似乎要提一个重要的事情。
BlueRaja-Danny Pflughoeft

2
@Danny,启动一个新的TCP连接需要三个数据包:客户端到服务器:SYN,服务器到客户端:SYN ACK,客户端到服务器:ACK +数据。这比UDP多了一次往返,但是仅在客户端第一次与服务器联系时才发生。在已建立的连接中,将立即处理每个数据包,而无需进行任何其他往返操作。将会有一个ACK-answer,但是在ACK数据包回传的同时,已经处理了接收到的数据。
Hendrik Brummermann 2011年

1
@ Danny,TCP自动以一种非常有效的方式处理数据包丢失。重新使用自己的UDP很难实现。除非您的协议适合随机未送达的封包。下一个问题是TCP确保数据包的顺序,而UDP数据包可能以错误的顺序接收。同样,很难重新实现自己的功能,除非您只能基于数据包计数器忽略旧数据包。如果TCP需要非常短的响应时间,则需要禁用Nagle的算法
Hendrik Brummermann 2011年

似乎您在没有解决真正的TCP延迟问题的情况下就为自己的立场进行了激烈的捍卫。也许真正的问题是您选择了硬件防火墙而不是DDoS抵抗协议
MickLH 2016年

27

http://gafferongames.com/networking-for-game-programmers/

大量有关游戏网络的各种问题和解决方案的文章。


1
+1,但请不要盲目相信他们。例如,根据我的经验,使用UDP并重塑TCP功能不是一个好主意。仅当丢失的软件包完全没有影响时,即每个UDP软件包都包含完整的相关状态时,UPD才有用。WoW使用TCP,SL正在从UDP迁移到TCP(对于静态内容甚至是HTTP),并且通过这些更改已显着提高了性能。
亨德里克·布鲁默曼

7
但是,您并不是在重新发明TCP功能,至少不是全部。对于需要低延迟连接的游戏,TCP流量控制和数据包丢失的语义非常糟糕。仅当您不关心延迟或最小化所需带宽时,TCP才有用。
jsimmons 2010年

2
:第二人生极大的改进通过UDP要基于TCP的HTTP性能blogs.secondlife.com/community/technology/blog/2010/08/13/...
亨德里克Brummermann

5
并非如此,他们通过更改资产的工作方式来提高资产流的性能。在那种情况下使用HTTP / TCP使他们更容易实现,而不是更快。我可能还会注意到zeromq是一个有趣的项目,它可以很好地扩展到游戏网络。 zeromq.org
jsimmons 2010年

8

根据您正在编写的游戏类型,您可能可以避免一些底层网络编程。某些类型的游戏不需要客户端与服务器之间进行大量来回通信。在这种情况下,可以选择使用更高级别的框架。例如,我正在C#/。NET中开发基于回合的策略游戏。基于回合的策略游戏在某种程度上是独特的,因为绝大多数客户/服务器通信发生在回合的开始和结束,而在回合之间很少。因此,我选择使用Windows Communication Foundation(WCF),这是一个主要为Web服务设计的高级通信框架。我可以直接使用标准方法调用,而不是直接使用套接字和所有这些底层的网络技巧,让WCF为我处理协议和传输层。我唯一需要处理低级网络问题的时间是在配置端点时,这几乎是一次性处理配置文件。仍然可能需要实现一些自定义序列化逻辑,但是无论如何,您都需要做这种事情。


8

这个问题太广泛了。答案可以自己填满一个网站。但是,有一些涉及这方面的书,主要是这两本书:

请注意,即使这些书也不是完整的指南,而是可以使用的思想和方法的集合,其中有些思想和方法无法协同工作,甚至是矛盾的。通常,它假定您具有开发游戏,网络应用程序或两者的理想经验。

(请注意,我在最初的问题中谈论的更多是MMO,“网络游戏”可能意味着从基于PHP的文字游戏到MMO的各种事物,而上述子问题并非全部适用于每种类型。)


7

如何平衡负载问题?

固定的地理位置大小+多个实例是最简单的解决方案。从事SWG工作的人们尝试了动态尺寸,对此感到遗憾。

如何管理游戏状态?

服务器是权威的。

如何保持事物同步?

来自服务器的定期同步更新。(不太确定这里有什么问题)

如何保护通信和客户端免受逆向工程的影响?

不可能。只需确保您不信任从客户端收到的任何信息,并且服务器是权威的。

如何解决延迟问题?

这已经深入了很多,但是从表面上看,您在客户端上与服务器运行了相同的模拟,并且当同步发生时,修复了问题。在客户端上做出的所有决策也都在服务器上进行了模拟,因此可能存在错误的决策,但总的来说是可行的。

应该在本地计算哪些内容,在服务器上计算哪些内容?

将客户端视为运行服务器上正在发生的事情的非权威模拟。响应能力是玩家体验的关键,因此您必须做一些事情即使玩家只是在开始一个杆每次做出决定时。

实话实说,这些问题中有很多是正交的,以后可以应用解决方案。刚开始做游戏,不要太担心这些事情。


4

这个问题广泛。这也是一个非常棘手的领域,网络程序员在行业中以相当的薪水受到追捧,这有点表明这是一个“未解决”的领域。有书吗,是的,很多。毫无疑问,那里有好书吗?有没有可以回答您问题的书籍?...我不这么认为。他们可能有在某些情况下可以使用的解决方案,或者在寻找所需内容的指针,但是几乎您所有的问题都取决于游戏。...在这个领域中,您实际上必须自己做很多工作,看起来如此琐碎的事情会以很多(不受控制的)方式出错。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.