游戏引擎基础(七)(网络和连线游戏环境)
第
7
部份
:
网络和连线游戏环境
网络游戏
我记得一些年前坐在 GDC (游戏开发者大会)听负责开发 X-Wing Vs TIE Fighter 的家伙们题为 “ 淹没在 Internet” 的演讲,全是关于让网络游戏实时地在 Internet 上工作的东西。他们选择那个题目是多么的正确啊。当它开始处理数据包的丢失,乱序,潜伏(一个数据包发送到它的目的地所花的时间)等等时,它确实淹没了。然而它是可能的。对于 Internet 需要一些聪明和经验,但它是肯定可能的。看看今天大量的连线游戏,从 Quake III , Unreal Tournament , Counter Strike 一直到 EverQuest 和 Ultima Online 。
如今大多数真正有长久生命力的游戏都至少有一些连线成分。最纯粹的单人游戏容易玩一次,也许两次,或者甚至三次如果它是非常好的游戏,但一旦游戏结束,就被束之高阁了。如果你想要有任何长久生命力,那么多人连线游戏就是形势的核心所在,并且那意味着和 Internet 打交道,为编码者打开了那个潘多拉的盒子。
那么跟 Internet 打交道包括些什么呢?首先是要理解 Internet 是怎么工作的,和点对点与客户机 / 服务器体系结构的快速讨论。点对点就是你在两台机器上运行游戏,并简单地在它们之间共享输入。每个单独的游戏假定它是正确的,并仅仅在它一幀接一幀的刷新中合并来自另外一台机器的输入。客户机 / 服务器是一台机器有效地运行游戏,别的机器仅仅是一个终端,接受来自玩家的输入,并渲染服务器让它渲染的任何东西。
客户机 / 服务器的优点是每台机器都将会展现相同的游戏,因为所有的处理都在一个地方完成,没有跨越多台机器,你可以不用考虑每台机器相互之间的同步问题。不足之处是,服务器本身需要有一些重要的 CPU 可用时间来处理每一个连接的客户机,和一个合适的网络连接来确保每一个客户机及时地接收到它的更新。
了解 IP
我们都已经听说过 TCP/IP (传输控制协议 / 网间协议)和 UDP (用户数据包协议), 在 Web 网络上有大量关于这些协议的深奥的技术资讯。实际上,在 Cisco 网站上有一些极好的 TCP/IP 指导。我们将在较高层面上介绍一些 TCP/IP 的基本知识,目的是让你更好地了解使用这些标准协议的网络游戏设计者面临的挑战。
TCP/IP 和 UDP/IP 是两层的通信协议系统。 IP 层负责网际数据包的传输。 UDP 或者 TCP 层将大的数据包传给 IP , IP 将数据包分割为小的子数据包,为每个数据包加上一个信封,计算出目的地的 IP 地址,应该如何到达那里,然后将数据包发送到你的 ISP ,或者不管怎样你连接到网络。 这实在象是在一张明信片上写下你要发送的,贴上邮票,写上地址,塞进一个邮箱,它就送走了。
UDP 和 TCP 是从你编码者或者游戏接收数据包的高层协议,并决定该如何处理这些数据包。 UDP 和 TCP 的区别在于 TCP 保证数据包的传送和有序,而 UDP 不保证。 UDP 是一条直接和 IP 对话的小路,而 TCP 是在你和 IP 之间的一个接口。它像是在你和你的邮件之间有一个管理员助手。使用 UDP 你会自己为你的信打字,把它们放进一个信封等等。使用 TCP 你会仅仅向你的管理员口授信稿,管理员会做全部的工作并追踪确认信件送到了。
然而,所有这些令人惊奇的为你完成的工作伴随着代价。为了确定数据包通过 Internet 完好无损地送到了目的方, TCP 期待从目的方为它发送的每个数据包发回一个应答包(网络用语是 ACK )。如果它在一定时间内没有收到 ACK ,它就停止发送任何新的数据包,重新发送丢失的数据包,并且将继续这样做直到收到目的方的回应。当你访问一个网页时,我们都已经看到了这种情形,在半途中下载停止了一会然后又重新开始了。可能是一个数据包在什么地方丢失了(假定不时 ISP 的问题),在任何更多的数据包被发送以前 TCP 要求重新发送它。
这一切的问题是,在认识到出了差错的发送者和实际上正在送达的数据包之间出现了延迟。有时这能花上数秒钟,如果你仅仅只是下载一个文件或一个网页,这不是什么大碍,但如果这是一个游戏数据包而且每秒至少有十次,那么你真的是遇到麻烦了,尤其是因为它停止了其他一切事情。实际上就是这个问题所以几乎没有游戏选择使用 TCP 作为它们主要的 Internet 协议,除非它不是一个实时动作游戏。大多数游戏使用 UDP-- 他们不能保证有序或可靠送达,但它确实很快 — 或者结果是至少通常比 TCP/IP 更快。现在我们了解这些了,接下来呢?
客户端预测
因为 UDP 明显的是快速响应游戏的方式,我们将必须自己处理数据包的丢失和乱序。边而且这是技巧所在。不用说出太多的代码秘密,我就能说有方法。作为开始,有客户端预言,一个被谈论得相当多的词语。当你作为一个客户端连接到一个大的服务器,但是不能连贯地看见来自服务器的更新,客户端预言开始起作用了。正在你的电脑上运行的游戏部分看着你正给它的输入,并在缺乏来自服务器的任何弃绝信息的情况下,对它认为将继续进行的事情作出 ‘ 最好的猜测 ’ 。它将会显示被猜测的数据,然后当它得到来自服务器的世界的最新状态时,改正它自己,如果需要。你可能会对这个方法的效力感到惊讶。大体而言,大部分时间数据包不容易丢失 — 大多数时候是一秒的几十分之一,这种情况下游戏没有太多的时间偏离服务器实际上认为正在发生的事情。偏离确实会随着时间变的比较大,大多数游戏里面有一个超时功能,当出现很长时间没有来自服务器的联络时就停止游戏。
你正在创造的游戏类型在这里有关系 -- 第一人称射击游戏不需要这样有效的客户端预言,因为它多数情况下仅仅处理 “ 我在哪儿,我是否要射击? ” 。在第三人称游戏中,你必须更加精确,因此你能够正确地预测你的角色正在播放的动画,并且动作流畅。在这种情形中流畅的动画是完全必要的。 Heretic II 在这方面有很大的问题,并且是当它开始网络编码时 Raven 一直不得不处理的最困难的事情之一。
当然如果你有一个很不错的网络连接,比如宽带连接,那么这个问题就远没有那么重要。对比较大的数据包有一个更宽的管道,对你的网络连通时间更快速。事实上,宽带对于游戏的主要优点不比较胖的管道多,但大大减少了延迟,特别是你到 ISP 的第一跳上。对于 56K 调制解调器,第一跳典型的延迟是 100ms ,这已经严重地增加了你到网络上任意一台游戏服务器的潜在连通时间。对于宽带连接比如像 DSL ,第一跳的延迟时间多半是 20ms 。使用 Windows 中一个叫做 TraceRoute ( TRACERT.EXE )的命令行程序并指定一个目标 IP 地址或者域名,你能够找出你的第一跳的连通时间。仔细观察第一跳,因为这几乎总是你到你的 ISP 的网络连通时间。并且观察你在你的 ISP 的网络内部用了多少跳直到你看见在一个给定跳上列出的一个不同的域名。
请注意,宽带并不总是能解决延迟问题。你仍然受最慢的路由器 / 服务器和数据包从服务器穿越网络到达你的跳数(反之亦然)的支配。有一个宽带连接确实容易缓和这些,但不可能它们最后就消失了。当然,如果你打算要运行某种服务器,你将会需要一个具有足够快速的向上游的数据速率的带宽,因为仅仅一个调制解调器不能够处理一个服务器产生的负荷。
值得一提的是,如果你想要在 PS2 或者 Xbox 上面玩网络游戏,你将需要一个宽带连接,因为它们两者都不支持调制解调器。
包大小,智能数据传输,和反作弊
别的必须被处理的事情是数据包的大小。如果你在一个游戏里面 64 个人都在跑来跑去相互攻击,从一台机器发送到另外一台机器的数据包能变得相当大,达到了一些调制解调器没有带宽处理这些数据的程度。这正在变得特别和那些有着很大的地表系统的游戏有关。这里增加的问题是,因为你有这个很好的地表系统,你能够看得很远,因此能够看见许多其他游戏玩家,使得你为了精确渲染所需要的来自服务器的数据数量以很快的速率增长。我们能做什么呢?
好吧,首先必要的是只发送绝对必须的东西给任何给定的客户端,因此他仅仅得到从他的角度观察游戏所需要的东西。发送在他视野以外的人们的数据没有一点意义 — 他将看不见这些。同时,你最好确保只发送那些每幀之间实际上发生改变的数据。如果一个家伙仍然在播放相同的动画,重新发送数据没有意义。当然,如果数据包丢失时这确实带来一些问题,但这就是为什么好的网络程序员被支付很多金钱,来处理类似这样的东西。
还有一些其他的事情也要处理。最近已经有大量的令人苦恼的连线作弊正在发生。这是某些人修改游戏以给他们不正当利益的地方。尽管严格意义上这不是网络的一部分,但它确实发生了。有时人们会创作一些模块,允许他们立即瞄准进入视野的任何人,或者简单地允许他们看穿墙壁,或者让其他游戏玩家看不见他们自己。大部份时间这些事情可以在网络层内部或者在服务器上被处理。任何有 100% 命中率的人被简单地踢出游戏,因为在人力所及的范围内那是不可能的。
游戏开发者必须尽一切可能制止作弊行为,但很不幸,人做的东西可以被人突破。所有你能做的就是让作弊变得困难,当确实发生时去尝试发现它。
好吧,现在就到这里了。在第 8 部分中,我们将会看看游戏脚本系统的趣味世界,根据游戏过程中出现的事件来渲染或使能预先定义的场景和行为,协助故事叙述。
网络游戏
我记得一些年前坐在 GDC (游戏开发者大会)听负责开发 X-Wing Vs TIE Fighter 的家伙们题为 “ 淹没在 Internet” 的演讲,全是关于让网络游戏实时地在 Internet 上工作的东西。他们选择那个题目是多么的正确啊。当它开始处理数据包的丢失,乱序,潜伏(一个数据包发送到它的目的地所花的时间)等等时,它确实淹没了。然而它是可能的。对于 Internet 需要一些聪明和经验,但它是肯定可能的。看看今天大量的连线游戏,从 Quake III , Unreal Tournament , Counter Strike 一直到 EverQuest 和 Ultima Online 。
如今大多数真正有长久生命力的游戏都至少有一些连线成分。最纯粹的单人游戏容易玩一次,也许两次,或者甚至三次如果它是非常好的游戏,但一旦游戏结束,就被束之高阁了。如果你想要有任何长久生命力,那么多人连线游戏就是形势的核心所在,并且那意味着和 Internet 打交道,为编码者打开了那个潘多拉的盒子。
那么跟 Internet 打交道包括些什么呢?首先是要理解 Internet 是怎么工作的,和点对点与客户机 / 服务器体系结构的快速讨论。点对点就是你在两台机器上运行游戏,并简单地在它们之间共享输入。每个单独的游戏假定它是正确的,并仅仅在它一幀接一幀的刷新中合并来自另外一台机器的输入。客户机 / 服务器是一台机器有效地运行游戏,别的机器仅仅是一个终端,接受来自玩家的输入,并渲染服务器让它渲染的任何东西。
客户机 / 服务器的优点是每台机器都将会展现相同的游戏,因为所有的处理都在一个地方完成,没有跨越多台机器,你可以不用考虑每台机器相互之间的同步问题。不足之处是,服务器本身需要有一些重要的 CPU 可用时间来处理每一个连接的客户机,和一个合适的网络连接来确保每一个客户机及时地接收到它的更新。
了解 IP
我们都已经听说过 TCP/IP (传输控制协议 / 网间协议)和 UDP (用户数据包协议), 在 Web 网络上有大量关于这些协议的深奥的技术资讯。实际上,在 Cisco 网站上有一些极好的 TCP/IP 指导。我们将在较高层面上介绍一些 TCP/IP 的基本知识,目的是让你更好地了解使用这些标准协议的网络游戏设计者面临的挑战。
TCP/IP 和 UDP/IP 是两层的通信协议系统。 IP 层负责网际数据包的传输。 UDP 或者 TCP 层将大的数据包传给 IP , IP 将数据包分割为小的子数据包,为每个数据包加上一个信封,计算出目的地的 IP 地址,应该如何到达那里,然后将数据包发送到你的 ISP ,或者不管怎样你连接到网络。 这实在象是在一张明信片上写下你要发送的,贴上邮票,写上地址,塞进一个邮箱,它就送走了。
UDP 和 TCP 是从你编码者或者游戏接收数据包的高层协议,并决定该如何处理这些数据包。 UDP 和 TCP 的区别在于 TCP 保证数据包的传送和有序,而 UDP 不保证。 UDP 是一条直接和 IP 对话的小路,而 TCP 是在你和 IP 之间的一个接口。它像是在你和你的邮件之间有一个管理员助手。使用 UDP 你会自己为你的信打字,把它们放进一个信封等等。使用 TCP 你会仅仅向你的管理员口授信稿,管理员会做全部的工作并追踪确认信件送到了。
然而,所有这些令人惊奇的为你完成的工作伴随着代价。为了确定数据包通过 Internet 完好无损地送到了目的方, TCP 期待从目的方为它发送的每个数据包发回一个应答包(网络用语是 ACK )。如果它在一定时间内没有收到 ACK ,它就停止发送任何新的数据包,重新发送丢失的数据包,并且将继续这样做直到收到目的方的回应。当你访问一个网页时,我们都已经看到了这种情形,在半途中下载停止了一会然后又重新开始了。可能是一个数据包在什么地方丢失了(假定不时 ISP 的问题),在任何更多的数据包被发送以前 TCP 要求重新发送它。
这一切的问题是,在认识到出了差错的发送者和实际上正在送达的数据包之间出现了延迟。有时这能花上数秒钟,如果你仅仅只是下载一个文件或一个网页,这不是什么大碍,但如果这是一个游戏数据包而且每秒至少有十次,那么你真的是遇到麻烦了,尤其是因为它停止了其他一切事情。实际上就是这个问题所以几乎没有游戏选择使用 TCP 作为它们主要的 Internet 协议,除非它不是一个实时动作游戏。大多数游戏使用 UDP-- 他们不能保证有序或可靠送达,但它确实很快 — 或者结果是至少通常比 TCP/IP 更快。现在我们了解这些了,接下来呢?
客户端预测
因为 UDP 明显的是快速响应游戏的方式,我们将必须自己处理数据包的丢失和乱序。边而且这是技巧所在。不用说出太多的代码秘密,我就能说有方法。作为开始,有客户端预言,一个被谈论得相当多的词语。当你作为一个客户端连接到一个大的服务器,但是不能连贯地看见来自服务器的更新,客户端预言开始起作用了。正在你的电脑上运行的游戏部分看着你正给它的输入,并在缺乏来自服务器的任何弃绝信息的情况下,对它认为将继续进行的事情作出 ‘ 最好的猜测 ’ 。它将会显示被猜测的数据,然后当它得到来自服务器的世界的最新状态时,改正它自己,如果需要。你可能会对这个方法的效力感到惊讶。大体而言,大部分时间数据包不容易丢失 — 大多数时候是一秒的几十分之一,这种情况下游戏没有太多的时间偏离服务器实际上认为正在发生的事情。偏离确实会随着时间变的比较大,大多数游戏里面有一个超时功能,当出现很长时间没有来自服务器的联络时就停止游戏。
你正在创造的游戏类型在这里有关系 -- 第一人称射击游戏不需要这样有效的客户端预言,因为它多数情况下仅仅处理 “ 我在哪儿,我是否要射击? ” 。在第三人称游戏中,你必须更加精确,因此你能够正确地预测你的角色正在播放的动画,并且动作流畅。在这种情形中流畅的动画是完全必要的。 Heretic II 在这方面有很大的问题,并且是当它开始网络编码时 Raven 一直不得不处理的最困难的事情之一。
当然如果你有一个很不错的网络连接,比如宽带连接,那么这个问题就远没有那么重要。对比较大的数据包有一个更宽的管道,对你的网络连通时间更快速。事实上,宽带对于游戏的主要优点不比较胖的管道多,但大大减少了延迟,特别是你到 ISP 的第一跳上。对于 56K 调制解调器,第一跳典型的延迟是 100ms ,这已经严重地增加了你到网络上任意一台游戏服务器的潜在连通时间。对于宽带连接比如像 DSL ,第一跳的延迟时间多半是 20ms 。使用 Windows 中一个叫做 TraceRoute ( TRACERT.EXE )的命令行程序并指定一个目标 IP 地址或者域名,你能够找出你的第一跳的连通时间。仔细观察第一跳,因为这几乎总是你到你的 ISP 的网络连通时间。并且观察你在你的 ISP 的网络内部用了多少跳直到你看见在一个给定跳上列出的一个不同的域名。
请注意,宽带并不总是能解决延迟问题。你仍然受最慢的路由器 / 服务器和数据包从服务器穿越网络到达你的跳数(反之亦然)的支配。有一个宽带连接确实容易缓和这些,但不可能它们最后就消失了。当然,如果你打算要运行某种服务器,你将会需要一个具有足够快速的向上游的数据速率的带宽,因为仅仅一个调制解调器不能够处理一个服务器产生的负荷。
值得一提的是,如果你想要在 PS2 或者 Xbox 上面玩网络游戏,你将需要一个宽带连接,因为它们两者都不支持调制解调器。
包大小,智能数据传输,和反作弊
别的必须被处理的事情是数据包的大小。如果你在一个游戏里面 64 个人都在跑来跑去相互攻击,从一台机器发送到另外一台机器的数据包能变得相当大,达到了一些调制解调器没有带宽处理这些数据的程度。这正在变得特别和那些有着很大的地表系统的游戏有关。这里增加的问题是,因为你有这个很好的地表系统,你能够看得很远,因此能够看见许多其他游戏玩家,使得你为了精确渲染所需要的来自服务器的数据数量以很快的速率增长。我们能做什么呢?
好吧,首先必要的是只发送绝对必须的东西给任何给定的客户端,因此他仅仅得到从他的角度观察游戏所需要的东西。发送在他视野以外的人们的数据没有一点意义 — 他将看不见这些。同时,你最好确保只发送那些每幀之间实际上发生改变的数据。如果一个家伙仍然在播放相同的动画,重新发送数据没有意义。当然,如果数据包丢失时这确实带来一些问题,但这就是为什么好的网络程序员被支付很多金钱,来处理类似这样的东西。
还有一些其他的事情也要处理。最近已经有大量的令人苦恼的连线作弊正在发生。这是某些人修改游戏以给他们不正当利益的地方。尽管严格意义上这不是网络的一部分,但它确实发生了。有时人们会创作一些模块,允许他们立即瞄准进入视野的任何人,或者简单地允许他们看穿墙壁,或者让其他游戏玩家看不见他们自己。大部份时间这些事情可以在网络层内部或者在服务器上被处理。任何有 100% 命中率的人被简单地踢出游戏,因为在人力所及的范围内那是不可能的。
游戏开发者必须尽一切可能制止作弊行为,但很不幸,人做的东西可以被人突破。所有你能做的就是让作弊变得困难,当确实发生时去尝试发现它。
好吧,现在就到这里了。在第 8 部分中,我们将会看看游戏脚本系统的趣味世界,根据游戏过程中出现的事件来渲染或使能预先定义的场景和行为,协助故事叙述。