多人游戏教程 1:概念

51次阅读
没有评论

共计 12226 个字符,预计需要花费 31 分钟才能阅读完成。

多人游戏教程 1:概念

介绍

开发多人游戏很困难,尽管 Construct 的 Multiplayer 对象为您解决了许多复杂性。同样,每个游戏的事件都不同,多人游戏消息和数据的处理方式将取决于您正在制作的游戏类型。因此,Multiplayer 对象具有相对抽象的通用功能,因此您可以在特定游戏中充分利用它。为了充分利用这些功能,了解多人在线游戏的基本原理、出现的问题以及如何解决这些问题非常重要。

如果这些功能使用不当,您的游戏最终可能会出现不必要的滞后,出现奇怪且困难的错误,或者使玩家有可能作弊。虽然您可能热衷于尽快开始设计多人游戏,但强烈建议您在开始之前通读完整的多人游戏教程集。此外,这应该被视为一项高级功能:初学者可能会发现它非常困难,中级用户可能会发现自己捉襟见肘。

如果您准备好开始学习多人游戏的运作方式,请继续阅读!

连接

Construct 的多人游戏引擎基于 WebRTC DataChannels。这是一种点对点浏览器网络技术。玩家直接相互连接,而不是通过中央服务器。

尽管玩家可以直接相互连接,但游戏本身仍然基于带有客户端的服务器。第一个加入游戏的对等方成为主机。然后,所有随后加入的玩家仅连接到主机。非主机玩家称为对等方。主机充当游戏的服务器。与中央服务器的主要区别在于,主机可以是加入游戏的任何人,而不是由游戏开发者运行的始终在线的服务器。此外,主机可以是游戏的积极参与者,而中央服务器通常只是盲目地为其他玩家运行游戏。
多人游戏教程 1:概念
多人游戏教程 1:概念

不过,仍然可以使用中央服务器:您可以设计游戏,使主机不是参与者,并让它在专用服务器上运行。但是,这需要为服务器托管付费,因此点对点方法可能更便宜。

要使加入的对等体能够连接到主机,它需要知道它们的位置以及如何连接到它们。这涉及找出他们的 IP 地址,找出他们是否具有限制连接的路由器,并在可能的情况下绕过这些限制。

受限路由器很常见。几年前,互联网的 IPv4 地址就用完了。解决方法是将多个用户隐藏在一个 IP 地址后面。这是通过以下方式完成的网络地址转换(NAT)。例如,在您自己的家中或办公室中,可能有一个路由器,内部网络上的每个人都通过该路由器连接到 Internet。在这种情况下,NAT 的一个变体将使每个人看起来都来自相同的 IP 地址,但使用不同的 IP 地址港口.NAT 还有其他几种变体,包括应用于整个区域、ISP 或移动网络的大规模 NAT,其中一些比其他变体更具限制性。不幸的是,这意味着在某些情况下无法进行连接,特别是如果主机和加入对等体都位于高度限制的 NAT 后面。但是,使用常见的设置,玩家通常可以相互连接。
多人游戏教程 1:概念

连接由 WebRTC 自动处理。它将尝试确定如何通过 NAT 限制连接到主机。这也意味着游戏没有使用特定的端口 – 它使用 WebRTC 发现正在工作的任何端口。例如,在上图中,三个客户端共享一个 IP 地址,因此另一端的对等体必须通过端口 A 连接到该 IP 地址才能到达第一个客户端,或者通过端口 B 连接到第二个客户端,依此类推。

TURN 服务器

在大多数情况下,设备可以通过 Internet 建立直接连接。但是,在某些情况下,由于网络的复杂性和网络沿线的限制,两个特定设备可能无法彼此建立直接连接。

这种情况通常通过使用 TURN 服务器. 这是两个设备都连接到的服务器,然后在两者之间中继流量,因此它们可以间接连接而不是直接连接。但是,这会导致连接质量较差,因为数据可能需要传输更远的距离。

Scirra 托管了一个 TURN 服务器,以帮助确保多人游戏的连接性。但是,这是一项尽最大努力提供的免费服务。它是带宽有限的,无法保证服务质量(QoS),并且在所有 Construct 项目之间共享。

如果您想要更好地保证 QoS,您也可以托管自己的 TURN 服务器。您可以在启动时使用 Multiplayer 对象的 Add ICE 服务器操作来添加自定义 TURN 服务器。

有一些商业服务可以为您托管 TURN 服务器。截至 2022 年,这些包括 Xirsys 的和特维里奥,其他人可能可以通过在网上搜索找到。这些通常按传输带宽的千兆字节(GB)收费,但请记住,它仅在无法直接连接时使用,因此它只会用于一部分用户。

您也可以尝试 Open Relay 项目的免费的 TURN 服务器。这可能可行,但由于它是一项免费的托管服务,因此无法保证其可靠性或寿命。

有经验的服务器管理员也可以设置自定义 TURN 服务器。这可以使用免费的 TURN 服务器软件,例如科特.

IPv6 的正逐渐通过具有更大地址空间的 Internet 获得采用。这将使每个连接到互联网的设备再次拥有唯一的 IP 地址,从而有望提高在互联网上建立直接连接的能力。在此之前,点对点连接问题是一个不幸的后果。谷歌也发布采用 IPv6 的统计数字.

信号

如上一节所述,对于节点要连接到主机,它需要找出其 IP 地址并确定如何连接到它们。主机可以是世界上任何地方的任何人,因此不可能事先知道要连接到谁。因此,为了让玩家找到彼此,有一个单独的中央服务器,称为信号服务器。

信令服务器不托管实际的游戏:第一个进入房间的玩家主持游戏并将游戏数据传输给其他对等方。信号只是玩家寻找彼此的中心位置。当对等体想要加入主机时,信令服务器会在两者之间中继 IP 地址和连接详细信息等信息。一旦对等体成功连接到主机,信令服务器就不再参与,玩家之间直接进行通信。
多人游戏教程 1:概念

Scirra 在 wss://multiplayer.construct.net 托管一个公共专用信令服务器。(wss:表示安全的 WebSocket 连接,因为信令数据恰好通过 WebSockets 中继。游戏本身仍然使用 WebRTC 运行。

信令术语

信令服务器需要避免混淆不相关游戏的玩家,并允许不同的玩家组同时安排单独的游戏。为此,玩家需要在游戏实例中加入一个房间。

信号服务器将玩家首先分开进入每场比赛。您的特定游戏在服务器上应具有全局唯一的名称。然后,您游戏中的每个人都在信令服务器上加入同一游戏。这样可以避免您的游戏玩家与来自不相关游戏的玩家混淆,这些游戏的工作方式完全不同!对于您创建的每个游戏,您只应在信令服务器上使用一个游戏。为确保您的游戏名称在服务器上是唯一的,并且不会被其他人的游戏意外选择,请包含您或您公司的名称,例如“MyStudio-Asteroids”或“JohnSmith-Asteroids”,而不仅仅是“Asteroids”。(此名称永远不会在任何地方显示,并且仅在信令服务器内部使用,因此请随意添加其他详细信息以确保唯一性。

接下来,信令服务器将玩家分隔到一个游戏实例中。这使您可以运行游戏的不同隔离实例。例如,您可能希望有一个大多数玩家加入的“稳定”实例,但对于使用您游戏的下一个(略有不同)版本的测试人员来说,则希望有一个“测试”实例。这将阻止 Beta 测试人员连接到可能具有不同游戏机制或功能的普通玩家。出于同样的原因,实例可以是“v1.0”、“v1.1”、“v1.2”等版本,始终确保玩家只能看到与自己具有相同游戏版本的其他玩家。或者,另一个很好的用途是拥有基于位置的实例,例如“欧洲”、“北美”和“亚洲”。假设玩家以他们的实际位置加入实例,他们只会在同一位置看到其他玩家,从而提高了与他们建立高质量连接的机会。这些目的甚至可以合并,例如“Europe-v1.1”、“Europe-v1.2”等。

最后,玩家可以加入一个房间。房间代表一组相互玩耍的玩家。除了同一房间的玩家之外,玩家无法看到任何其他玩家。第一个进入房间的玩家被分配为主持人。然后,信令服务器通知主机加入同一房间的任何其他玩家。然后他们相互连接并可以开始玩游戏,实时查看彼此的动作!

在 Construct 的 Multiplayer 对象中,与信令服务器相关的所有动作、条件和表达式都属于信令类别。所有其他功能都与游戏本身有关。

互联网的混乱

假设现在一些对等方已加入同一房间,成功连接到主机,并且多人游戏已经开始。我们现在可以忽略信令服务器:从此时起,它不再参与其中。(此时,您的游戏可以断开所有人与信号服务器的连接,但请注意,这可以防止任何人延迟加入游戏。

如前所述,多人游戏本身运行时,主机充当服务器。对等方只向主机发送数据,而主机可以向任何人发送数据。这意味着如果两个对等体想要通信,则必须通过主机进行中继。

如果互联网上的所有传输都几乎是即时的,那么多人游戏会简单得多。在局域网(LAN)上通常出现这种情况,例如您的家庭或办公室网络。然而,互联网非常复杂。在互联网上的任何两个播放器之间,可能有 10-20 个网络设备(例如路由器)。这条路线上的设备对于每对玩家来说都是不同的。对于发送的每一条消息,沿途的每个设备都必须接收一个传入的信息包,读取并理解其目的地,确定将其转发到何处,然后重新传输它。最重要的是,如果您连接到海外播放器,您的数据很可能会通过海底电缆传输,这些电缆可以处理长距离的大量流量。
多人游戏教程 1:概念

令人惊讶的是,路由上的每个设备通常都可以在几毫秒内转发传入的数据包。但是,由于沿途有很多设备,这就会加起来。如果沿途的任何设备遇到高负载,它可能会减慢速度,从而导致更长的传输延迟。与任何计算机一样,这些设备也可能会崩溃、内存不足、因维护而关闭、断电、遇到影响服务的错误等。由于令人印象深刻的工程设计,路由器通常可以在已脱机的设备周围重新路由数据,甚至可以将数据重新路由到更快的替代路径。所有这些都可以对消息从 A 传输到 B 所需的时间进行临时或永久性更改。

物理定律也必须被考虑在内。如果来自英国伦敦的玩家连接到澳大利亚的悉尼,则数据必须传输大约 17,000 公里。以光速沿直线行进,这大约需要 57 毫秒。从物理上讲,要比这更快地获取数据是不可能的。然后,沿途的电缆可能不是完全笔直的,并且在如此长的距离内,可能会有更多的布线设备。

连接质量

可以进行许多测量来确定 Internet 上的连接质量,并且是可能产生的游戏质量的良好指南。这些包括延迟、数据包延迟差异(PDV)、数据包丢失和带宽。

延迟

由于路由设备和物理定律,通过 Internet 发送的每条消息都需要一些时间才能到达目的地。传输时间称为延迟,有时也称为 ping 时间。对于世界上任何地方的任何给定两名玩家来说,它通常在 20 毫秒到 200 毫秒左右,尽管正如任何经验丰富的游戏玩家都可以告诉您的那样,它有时可能超出该范围。游戏通常以 60 FPS 的速度运行,这意味着每帧大约需要 16 毫秒。100 毫秒的延迟意味着游戏在发送的消息到达目的地之前前进了大约 6 帧。如果它随后需要回复,它会加倍:响应将在另外六帧后到达。
多人游戏教程 1:概念

在动作游戏中,响应时间非常重要。优秀的玩家通常可以在几十毫秒内对游戏事件做出反应,他们对这些延迟变得非常敏感。考虑一颗子弹以每秒 500 像素的速度移动。在 200 毫秒内,它覆盖了 100 个像素,这很容易成为直接命中和宽床位丢失之间的区别。

互联网上数据传输的这种延迟会产生一些难题。为了使游戏公平,所有玩家都需要看到相同的事物,并有相同的机会对事件做出反应。在实践中,每个玩家都在不同的时间延迟下行动,主持人必须决定到底发生了什么。虽然使用了各种技术来补偿时间延迟并试图保持游戏的公平性,但任何经验丰富的游戏玩家也可以告诉您,低延迟是一种游戏优势:您会在其他玩家之前看到事情稍微发生。

数据包延迟差异(PDV)

延迟的另一个问题是,每条消息的延迟可能会有所不同。如果通过 Internet 发送两条消息,一条可能需要 50 毫秒才能到达,但第二条可能需要 70 毫秒。这称为数据包延迟差异或 PDV。在 Construct 中,它被测量为最后几次测量的最高延迟减去最低延迟,因此在给定的示例中为 20 毫秒。高 PDV 往往比高延迟更糟糕。多人游戏引擎预测消息何时到达,并尝试补偿延迟。高延迟和低 PDV 意味着关于到达时间的预测效果很好,补偿准确,从而产生稳定的游戏玩法。低延迟和高 PDV 意味着消息到达不可预测,并且补偿有时不准确,导致游戏玩法不稳定,因为多人游戏引擎必须进行更正,并抵消了低延迟的优势。

数据包丢失

消息也可能完全丢失。虽然路由设备会“尽最大努力”尝试传递消息,但如果它们被太多消息淹没、内存不足、崩溃、断电等,它们可以简单地丢弃它们。丢失的消息百分比称为数据包丢失。多人游戏引擎可以很容易地补偿偶尔丢失的数据包,但如果数据包丢失率很高,游戏质量就会开始下降。

数据包丢失的一个常见原因是高流量,导致路由设备接收发送的消息的速度快于它们接收或处理消息的速度。如果超过容量,将处理和重新传输某些消息,而其他消息将被丢弃,以保持一定程度的服务。如果它必须处理每一条消息,积压将不断增加,重新传输的速度会越来越慢,直到完全失败。为了避免造成这种情况,明智的做法是尝试以可接受的最低速率传输较小的消息 – 这也使它们更有可能快速到达。

带宽

最后,带宽是指可以发送数据的总速率。所有 Internet 连接都有最大下载和上传速率,通常以兆比特 / 秒为单位。由于一个字节中有 8 位,因此将其除以 8 可以得到以兆字节 / 秒为单位的速率(因为大多数软件系统(包括 Construct)以字节而不是比特为单位测量数据)。例如,理论上 40 兆比特 / 秒的连接每秒可以传输 5 兆字节。但是,请注意,上传速率可能会有所不同,并且在消费者 Internet 连接中通常较低。

带宽可能是大型游戏的瓶颈。加入游戏的对等方越多,主机必须上传的数据就越多,以使所有对等方保持最新状态。最终,主机将达到其上传速率的限制,并且会发生数据包丢失。这是以可接受的最低速率发送小消息的另一个原因,因为它最大限度地减少了必要的带宽。

补偿网络状况

为了最大程度地减少带宽和数据包丢失,默认情况下,多人游戏引擎每秒最多传输 30 次数据。游戏通常以每秒 60 帧的速度渲染,因此这意味着数据大约每隔一帧发送一次。

对同伴的补偿

对等方将从主机接收数据,指示对象数据,例如它们的位置。如果它们只是直接显示接收到的内容,则对象的运动将显得不稳定,因为它们每隔一帧才会更新一次。它们还会不规则地移动,更新会受到 PDV 和数据包丢失的影响。

为了提升游戏体验,多人游戏引擎插值在 X 和 Y 坐标等值的更新之间。在仓位的情况下,它将在更新之间线性插值。例如,如果数据每隔一帧就传入一次,则未接收更新的帧将在任一侧的两个更新之间使用一个值。这使得运动再次顺畅,而不需要任何更多的数据。

但是,在渲染插值帧时,它还不知道下一个值是什么,因为这将在未来到达!多人游戏引擎不是使用时间机器,而是通过为对等方增加 80 毫秒的人为额外延迟来解决这个问题。这意味着多人游戏引擎可以在当前呈现的内容之前了解接下来的几次更新。即使由于数据包丢失而丢失了下一个更新,它也可能能够使用之后的下一个更新进行插值。即使网络条件不佳意味着 80 毫秒内没有更新,引擎也可以继续从前两次更新的方向进行推断。然而,这只是猜测,如果下一次更新显示对象实际上已经去了其他地方,则对象可能会跳跃。

多人游戏引擎允许您对值使用三种可能的插值模式:线性(例如对象位置)、角度(例如对象角度)和无(用于不应插值的数据,例如指示激光器是否打开的布尔值)。

延迟变化

应该注意的是,延迟可能会发生变化。例如,某处的路由设备可能会过载,两个播放器之间的数据突然沿着不同的路径重新路由,该路径速度较慢; 或者,也许有一条新的更快的路径可用。延迟有时也会在连接后的第一分钟左右逐渐改善,因为连接路线上的设备会逐渐优化连接并找出可能的最快路径。延迟会不断重新测量,以检测此类变化。

如果延迟减少,多人游戏引擎会暂时以非常轻微的快进方式运行游戏,从而减少您看到游戏的落后距离。另一方面,如果延迟增加,它会以慢动作略微运行游戏,并增加您看到游戏的落后距离。这是必要的,以避免当 80 毫秒延迟不再涵盖任何更新时发生的不稳定、不规则的运动。这些调整应该发生得足够慢,以至于难以察觉,但即使连接质量在游戏过程中发生变化,它也有助于确保最佳体验。

对主机进行补偿

主机拥有游戏的权威版本。它们具有零延迟,因为无需向自己传输数据。换言之,主机正在参与“真实”游戏,而对等方正在尽最大努力呈现同一游戏,但主机的更新延迟且可能不规则。因此,主机具有轻微的游戏性优势。

您可能会认为主机需要在从对等方接收的对象位置的更新之间进行插值。这实际上不会发生,因为对等方不应该告诉主机他们在哪里。事实上,主持人应该告诉对等方他们在哪里。其原因将在下一节中介绍。

防止作弊

如果同伴告诉主持人他们在哪里以及他们在游戏中做什么,并且主持人信任他们,那么同伴就可以作弊。他们只需要突然发送数据,说他们是墙的另一边,或者他们攻击了一个他们无法接触到的玩家,等等。为了缓解这种情况,对等方只告诉主机他们的输入,例如他们当前按住的箭头键。主机接收到这个信息并开始移动该播放器,并发送回数据,告诉该播放器它认为他们在哪里。

这样做的直接问题是它增加了所有播放器输入的延迟。如果播放器以 100 毫秒的延迟按下“左”,则主机将在按下该输入 100 毫秒后接收该输入。然后,主机对新玩家位置的更新将需要另外 100 毫秒才能返回。这意味着所有对等方的控件都感觉非常滞后,仅在一秒的显着分数后才会生效。为了解决这个问题,对等方的本地博弈使用本地输入预测。

本地输入预测

相反,按左键将向主机发送一条消息,说输入已被按下,然后该玩家的本地游戏无论如何都会开始移动它们,而无需等待主机的确认!由于主机和对等方运行同一游戏,因此它们通常非常匹配。然后,玩家会得到感觉响应迅速的控件,他们仍然不能作弊:他们只是发送他们的输入,不能假装在其他地方。即使他们入侵了他们的本地游戏,也只会让自己处于不利地位,因为他们所能做的就是表明自己与主机相比处于错误的位置。

然而,同伴的玩家将不可避免地偏离主机看到他们的位置。在网络计时、帧率同步、增量时间测量等过程中可能会积累很多小错误。对等方仍在接收来自主机的消息,说明他们的位置,但消息被延迟了。在前面的示例中,对等体从主机接收其位置,总延迟为 200 毫秒。为了纠正偏差,多人游戏引擎会查看对象历史记录,并比较 200 毫秒前的位置。换言之,校正是查看对象过去的位置,同时考虑到主机的延迟。如果物体位于错误的位置,多人游戏引擎将逐渐移动它以进行补偿。这种情况会随着时间的推移而发生,以试图使其不那么引人注目。在极端情况下,需要进行大而明显的修正,但在良好的网络条件下,运动会紧密匹配,并且以难以发现的方式进行小的调整。

值得注意的是,这不仅限于职位。多人游戏引擎能够与任何实例变量进行所有这些同步,而不仅仅是 X 和 Y 坐标。

滞后

在较差的网络条件下,可能会对游戏玩法产生明显的影响。游戏玩家通常将这些问题称为“滞后”。它可能包括粗暴的运动(当 80 毫秒的更新缓冲区为空时)、游戏过程中的跳跃或不连续性(当发生数据包丢失并且下一次更新显着改变游戏状态时)、玩家突然改变位置(当本地输入预测遇到大错误时)或看起来不公平的后果(通常是每个玩家以不同的延迟观看游戏的结果,以及主持人做出有利于某个特定对等方的权威性决定)。

不幸的是,除了找到质量更好的互联网连接之外,没有好的解决方案可以永久避免这些问题。这些问题通常只在严重的情况下发生,例如几秒钟的完全数据包丢失,或者延迟或 PDV 的突然和极端的临时变化。在这种情况下,各种补偿技术几乎不可能掩盖它。这有时只是通过互联网进行通信的现实。

滞后补偿

考虑以下问题:玩家 A 站着不动并瞄准向右跑的玩家 B。玩家 A 将鼠标正好悬停在玩家 B 上方并射击。(假设射击是瞬间命中的,就像激光或无限速射弹一样。向主机发送指示他们正在拍摄的消息需要 100 毫秒才能到达那里。在此期间,玩家 B 不断向右移动。主机晚了 100 毫秒收到消息,并测试了玩家 A 瞄准的碰撞 – 但他们错过了,因为玩家 B 已经继续前进了!玩家 A 看到自己被直接击中,但他们从未造成任何伤害。

一般来说,由于延迟,主持人会看到每个玩家做所有事情都晚一点,玩家最终会错过移动的目标。这种问题会激怒玩家,他们最终会了解到他们实际上需要瞄准玩家移动位置之前的空白空间。这不是很现实或公平。滞后补偿是一种避免这种结果的技术。

倒带时间

主持人知道每个玩家观看比赛的落后程度,因为它正在测量每个人的延迟。因此,当主机收到指示玩家 A 正在射击的消息时,它知道他们实际上在 100 毫秒前就这样做了。

主机正在记住每个对象历史记录的过去几秒钟。然后,它可以回头看看玩家 B 在 100 毫秒前的位置。然后,它可以测试玩家 A 在玩家 B 最初开火时是否击中了他们。这就是主机补偿玩家 A 的延迟的方式,这意味着当玩家 A 看到自己在自己的屏幕上得分时,他们可能会在主机上得分。
多人游戏教程 1:概念

不过,这带来了另一个问题。玩家 B 也处于延迟状态。如果它们的延迟为 100 毫秒,则主机会将它们移动到它们看到自己的位置后约 100 毫秒(请记住,它们的本地输入预测会立即将它们移动)。最重要的是,当玩家 A 开火时,主机在测试碰撞时将他们进一步向后移动。

这意味着玩家 B 看到玩家 A 瞄准他们身后可能错过的地方,开火,然后他们还是被击中了!在极端情况下,玩家 B 实际上可能已经到达了玩家 A 的庇护所,因此他们无法直接被击中,然后他们突然受到伤害。这对玩家 B 来说很烦人,但通常不会像没有补偿那么糟糕——至少玩家实际上必须直接瞄准对方才能命中。一种常见的解决方案是不清楚地指示玩家瞄准的位置,因此玩家 B 无法轻易看到玩家 A 似乎在瞄准他们身后,从而在他们被击中时看起来更容易接受。

有多少玩家可以加入同一个游戏?

可以加入游戏的玩家数量限制可能是主机上的上传带宽。发动机本身没有限制,但会遇到一定的实际限制。

问题是主机必须向 N 个玩家中的每一个发送一条包含 N 个玩家数据的消息。例如,如果主机需要为每个播放器发送 16 个字节的数据,则每条消息的大小约为 N * 16,然后该消息必须发送 N 次。这将产生 N 平方带宽要求。例如:

10 个玩家 = 16 x 10 x 10 = 每次更新 1600 字节

20 个玩家 = 16 x 20 x 20 = 每次更新 6400 字节

30 个玩家 = 16 x 30 x 30 = 每次更新 14400 字节

100 个玩家 = 16 x 100 x 100 = 每次更新 160000 字节

尽管玩家数量呈线性增加,但带宽要求与平方成正比。这意味着即使服务器功能更强大或每个玩家需要的数据更少,它也不会为您带来很多额外的玩家。

默认情况下,更新每秒发送 30 次,因此最后一个有 100 个播放器的示例实际上需要大约 5 兆字节 / 秒(或 40 兆比特 / 秒)的上传速率。对于家庭连接来说,这是相当高的,但不一定是专用服务器。

最重要的是,主机还需要能够为大量玩家运行游戏,执行延迟补偿碰撞测试等任务,这可能会占用 CPU 大量资源。然后,如果主机也是参与者,则可能需要为主机呈现游戏。通常,总工作量会随着玩家数量的增加而迅速增加,尽管这取决于具体的游戏和连接,但很少在一场比赛中接近 100 名玩家。

控制更新格式

可以选择多人游戏引擎触发的值的确切数据格式。如果使用得当,这可以显着减少所需的带宽量,而不会对游戏精度产生任何显着影响。这有助于使游戏更有效地利用网络,并可能提高可以加入的最大玩家数量。

如果您不熟悉比特、字节和二进制文件,那么它在其他地方已经被广泛介绍过。考虑从以下维基百科文章开始二进制数和字节. 简而言之,计算中的所有数字都以二进制形式存储:每个数字只能是 0 或 1。一个字节是 8 位,因此可以存储 2^8(256)个不同的值,或从 0 到 255。字节数越多,可以存储的值范围越大。浮点类型还可以存储小数值(如 0.3),通常至少需要四个字节。

您可以在 Construct 中使用的类型包括:

高(双精度,8 字节):a 双精度浮点数可以存储数字而不会影响其精度。它有大约 15-17 位有效数字的精度。但是,存储单个数字需要 8 个字节,这最终可能会显着增加带宽需求。在实践中,这不太可能是一个必要的选择。

正常(浮点数,4 个字节):a 单精度浮点数可以存储精度约为 6-9 位有效数字的小数。这意味着某些数字将四舍五入为较少的有效数字。然而,它通常比双精度值更实用,因为它只需要一半的字节,而前 6 个字节之外的数字通常并不重要(例如,0.333333 对于实际目的来说,它足够接近 0.333333333333333)。

低(int16,2 字节):一个有符号的 16 位整数,只能存储 -32768 到 32767 范围内的整数。

非常低(uint8,1 字节):一个无符号的 8 位整数,只能存储 0 到 255 范围内的整数。

为了最小化带宽,选择尽可能低的精度非常重要,因为这种精度不会严重影响游戏玩法。例如,X 和 Y 位置通常可以使用低(int16)精度。只要布局小于 32767×32767(非常大),并且子像素位置对游戏玩法不重要(因为这会四舍五入任何小数值),它就完全足够了,并且使用的带宽比两倍少四倍。

低(int16)和非常低(uint8)精度对于玩家输入非常有用,以便对等方发送到主机。使用 Construct 中的 setbit、getbit 和 togglebit 表达式,可以在这些数字中设置各个位。如果游戏使用四个箭头键来移动和空格键进行射击,那么这些只是五个控件,并且可以以 8 位存储,0 表示“未按下”,1 表示“正在按下”。然后,主机可以查看每个位并模拟适当的控件。这一切都可以通过单个字节来完成,或者如果您有八个以上的控件,则可以使用 int16,从而非常有效地利用带宽。同样,主机可以在单个值中向对等方发送多个开 / 关状态。

CONSTRUCT MULTIPLAYER 插件

Construct 中多人游戏的总体设计如下所示。

多人游戏的流程

多人游戏的生命周期将如下所示:

  1. 连接到信令服务器并登录
  2. 加入聊天室
  3. 其他同伴可以在游戏运行时加入和退出游戏
  4. 对象数据和其他消息(如聊天)与其他连接的对等体交换
  5. 最终游戏结束,每个人都离开了房间,也许可以寻找新的房间(回到第 2 步)。
    请注意,如果主机断开连接,游戏将结束。他们充当游戏的服务器,因此如果他们断开连接,则游戏将不再运行。这就是考虑在中央服务器上运行专用主机的原因,特别是对于拥有更多玩家的大型游戏。然而,对于双人游戏来说,这没有区别 – 如果另一个玩家离开,游戏无论如何都会结束。

多人游戏插件具有涵盖信号阶段(步骤 1-2)的功能,以及涵盖游戏玩法本身的“房间”功能,例如对等方加入和离开、接收消息等的触发器。

设计概述

旨在使游戏设计为一个对象类型既代表玩家的受控对象,也代表游戏中的所有其他玩家。然后,游戏中的每个人都平等地使用相同的对象,包括您自己(甚至当主持人)。将此对象命名为 Peer 是明智的,因为这就是它所代表的。如果您的玩家由多个对象组成,例如单独的枪和身体,请有一个基本的 Peer 对象并将其放入容器与其他对象一起使用。这确保了玩家是作为一个整体创建和销毁的,并且他们的相关对象在具有基本对象的事件中被自动选择,因此您可以在很大程度上将基本对象视为代表整个玩家。

主机和对等方都在运行同一个项目。这意味着您的一个项目必须能够处理主机(拥有游戏权威版本)和对等方的事件,后者看到延迟版本并仅发送其输入。处理此问题的最便捷方法是将两个事件组专用于主持人和对等方,并在加入房间并确定您是否成为主持人后仅激活适当的事件组。

Multiplayer 对象的 Sync 对象操作是指示您希望通过网络发送有关对象的数据的基本方式。这告诉主机将有关这些对象的信息发送给对等方,并告诉对等方等待接收有关这些对象的信息。多人游戏引擎会自动创建和销毁代表对等方的对象,因为它们会加入和离开。(“同步对象”操作也可用于不表示对等方的其他对象,但最常用于对等方。

每个对等体都有一个由信令服务器分配的对等体 ID。这是一个字符串,其中包含一小段随机字符,用于唯一标识它们。对等 ID 通常用于能够一致地引用同一玩家,即使其别名发生变化也是如此。Peer ID 需要存储在实例变量中,以便您知道给定对象代表哪个 Peer 节点。当多人游戏引擎为对等方创建对象时,Multiplayer.PeerID 表达式将设置为其对等方 ID,因此可以将其存储在其实例变量中。由于您可以控制自己的对等对象,因此您可以通过测试其实例变量是否等于 Multiplayer.MyID 来轻松选择它,然后仅修改该实例。

可靠性模式

最后要提到的是有 3 种数据传输模式。这些交易在可靠性与性能之间进行了权衡。

最可靠的模式是 Reliable ordered。这将发送一条被跟踪的消息:如果它被网络丢弃,它将重新发送它,直到它验证它到达目的地。它还对消息进行排序,因此可以保证消息以与发送相同的顺序到达。这很有用,但不是最快的:如果一条消息被丢弃并暂停,它将阻止所有后续消息,直到该消息通过。这也意味着单个消息可能需要数倍的延迟才能到达,因为它必须至少等待往返时间才能知道消息是否到达。这通常仅适用于重要的低频消息,例如聊天消息。

其次是 Reliable unordered。这将发送一条被跟踪的消息,并且还会重新发送它,直到它验证它到达目的地。但是,消息可以按任何顺序到达。这样可以防止单个被保留的消息阻碍所有后续消息 – 它可能只是在最初发送的其他消息之后延迟到达。但是,单个消息仍可能需要数倍的延迟才能到达。这适用于必须到达但彼此无关的游戏事件,例如开门或发生爆炸。

最快的模式是不可靠。这会发送一条消息并忘记它。如果它被丢弃,消息将永远不会到达目的地。它也可能以与最初发送的序列不同的顺序到达,甚至可能是一式两份。通常,这适用于常规消息,在常规消息中,消息尽快到达比消息是否到达更重要。如果它被丢弃,它可能会很快被下一条包含较新数据的消息跟进,所以没关系。请注意,引擎在内部将此模式用于具有内置插值和补偿功能的同步对象,因此请勿尝试使用此模式复制该功能。

整装待发!

虽然 Construct 的多人游戏插件可以为您处理许多技术细节,例如输入预测和连接性,但了解理论仍然非常重要,以便能够就发送哪些数据、发送到何处、以何种精度和可靠性模式做出适当的选择。希望本教程已经为您提供了足够的概述,以便您开始设计您的第一个多人游戏,同时充分理解幕后发生的事情,以及您需要从 Construct 中执行的操作以充分利用这些功能。虽然本教程重点介绍理论,但后续教程将介绍如何在实践中使用多人游戏插件的特定功能解决输入预测和滞后补偿等问题。

如果您已准备好开始了解更多信息,请前往多人游戏教程 2:聊天室!

正文完
 0
评论(没有评论)