使用 XNA 创建游戏/网络/网络和点对点
好吧,我会做到的。 - project79
一个非常重要的点是:从一开始就决定是否支持游戏的网络功能。由于带宽、延迟、丢包以及所有这些因素的组合,你不能只通过网络发送你的输入。会有你必须在玩家面前隐藏的错误。为什么、哪些错误以及如何隐藏将在后面提到。首先,我们来了解一下游戏和网络的一些理论。
大多数人听到点对点(简称 P2P)时会想到非法的东西。但它并不非法。它只是一种组织网络的方式。
在这里,每台机器(称为节点)都知道其他所有节点,或者至少知道它想要与其通信的所有其他节点。因此,一个节点可以直接与另一个节点通信,这比客户端/服务器方法更快。此外,你也不需要一台具有大量带宽需求的机器。但要量力而行。带宽最差的节点决定了所有其他节点的速度(对于与它的连接)。(每个人都与每个人连接。因此,B 的下载速度与 A 的上传速度相同)
如果每个节点都是平等的,没有人比其他人拥有更多,包括逻辑。因此每个人都在计算自己世界的一部分,因此作弊很容易 - 没有人(可以)控制你。另一个缺点是寻找其他节点的方式。玩家不能输入 10 个 IP 地址,你不能扫描整个网络。
进一步阅读维基百科
这是网络中最典型的网络架构。在这里,每台机器(客户端)都连接到中间的一台机器(服务器)。通常,信息的流动是客户端将他们的输入发送到服务器,服务器计算结果并将其发送回客户端。因此,逻辑集中在一个中央点,玩家无法操纵它。因此,作弊很难。还有创建游戏会话的优势,因为客户端只需要一台机器的地址。
但也有缺点。由于每个人都通过服务器通信,因此该机器上的带宽负载要高得多。该机器也应该更强大。另一个问题是延迟。每个消息都必须通过服务器传递,这会导致更长的距离和更长的交付时间。
进一步阅读维基百科
就像混合动力车一样,这里既有客户端/服务器也有 P2P。下面提到了两种有趣的类型。
第一个解决了寻找其他节点的问题。某种程度上,你需要一个像服务器一样的中央点。那么为什么不使用一个呢?一个玩家启动多人游戏会话,并在后台启动一个小服务器。其他人只需要加入一个会话。也许他们输入第一个玩家的 IP 地址,或者在局域网中,游戏会查找服务器。找到服务器并设置一个准备就绪的标记后,所有客户端的 IP 地址以及一些初始化信息(地图、此会话的规则)将被共享。现在每个客户端都可以与其他每个客户端通信。因此服务器停止,网络变为 P2P,游戏开始。
第二个解决了作弊问题。由于每个节点都拥有整个逻辑(并使用它),因此没有权威机器可以说 A 的结论是错误的。但如果有一个大型权威机器控制着逻辑,那将是客户端/服务器,这对于带宽原因来说可能是不可行的。所以将逻辑(对于重要的部分)拆分成小的独立部分,并将它们分布到节点上。因此,A 控制团队旗帜,而 B 控制其他东西,等等。
通常有 12 到 250 千字节每秒可用。但建议只使用 8 千字节每秒。这是 99% 用户拥有的带宽(《光环 3》测试版期间的数据收集(2007 年)[1](上行中值 44,下行中值 42))
那么为什么只有这么一点呢?
服务提供商总是想销售他们的产品。即使在最佳状态下,你也无法获得合同中规定的全部功率。带宽受在线人数、你到路由器的距离、其他人的活动等等的影响。也许你的队友没有良好的连接。但他的上传是你的下载,反之亦然。这也是上行速度与下行速度相似的理由。
好的。物理。
我们都知道光速是 299,792,458 米每秒(真空)。我们也知道数据包是通过光或电发送的。但这些线缆中是否有真空?没有,它是光纤或铜线,将我们的数据包速度降低到 194,865,097 m/s(65%)。因此,以下是一些从柏林到其他地点的距离以及每个数据包所花费的时间(理论时间和往返时间;网站主机只在城市附近)
城市 | 距离(公里) | 计算时间(毫秒) | 测量时间(毫秒)(32 字节 ping) |
---|---|---|---|
伦敦 | 910 | 4.67 | 137(www.proteusinvestigations.co.uk) |
比勒陀利亚 | 8,660 | 44.41 | 272(mybroadband.co.za) |
墨西哥城 | 9,710 | 49.79 | 671(mexicocity.gob.mx) |
悉尼 | 15,960 | 81.85 | 432(cityofsydney.nsw.gov.au) |
那么为什么测量时间总是高出那么多呢?因为你没有直接的(物理)连接到这些计算机。数据包必须被路由,每个路由器都需要一些时间才能将你的数据包放到正确的线路(5-50 毫秒)。你的调制解调器也会增加 10 毫秒。
因此,游戏中延迟的一个好数字是 270 毫秒。
这个问题(也称为“高延迟”)归结为您为数据包使用哪种协议的问题。对于游戏,UDP 是主要使用的协议,但它并不总是可靠的。UDP 协议将数据包发送到网络并忘记它们。因此,如果数据包丢失,就无法再找到它。在实时测试中,2% 的数据包丢失是平均延迟,但对于游戏,要做好高达 10% 数据包丢失的准备。每个数据包都可能出现损坏,以及数据流顺序混乱和错误。另一种协议,TCP,解决了大多数这些问题,但速度太慢,无法产生太大影响。TCP 在多人游戏中最好的应用是回合制游戏或延迟不是大问题的其他环境。
无论您在编写什么程序,都应该考虑一个要点:使用正确的(更小的)数据类型。一个字节只是一个 int 的四分之一。矩阵可以用一个四元数和一个向量表示,这样只需要 7 个值而不是 16 个值。由于字符串有开销,应避免使用。您还可以将多个布尔值放在一个位域中(好吧,这实际上并没有更小),但您可以将多个(不是 32 位长的)数字放在一个 32 位整数中(通过位移)。
另一种方法是不每次都发送整个世界(或您的角色的特定状态),只发送变化。
不要过于精确!考虑图像,您不会发送每个像素的真实值。除了对像素进行分组之外,值还会被量化。因此,与其发送弧度(或度数)中的精确角度,不如将其转换为度数并将值四舍五入为自然数。或者,如果 256 个不同的值足够,则将其转换为一个字节。
其他更多 XNA/C# 特定的可能性是:[2]
- 如果一个浮点值不能大于 1,则将其转换为一个 Alpa8(减少 75%)。
- 如果一个浮点值可以大于 1,则将其转换为一个 Halfsingle(减少 50%)。
- Vector2 ⇒ HalfVector2
- Vector4 ⇒ HalfVector4
- 如果一个 Vector3 被归一化 ⇒ Normalized101010
- 如果不是 ⇒ 3 个 Halfsingle
- Quaternion ⇒ NormalizedByte4
- Color.packedValue
举个简单的例子。您有一个小型游戏,有 8 个玩家,以 30 帧/秒的速度运行。每个玩家都有一个位置,一个他所看的方向,以及一个布尔值作为某种状态。每帧您都会将您的数据发送给所有其他玩家。
但是,我们不是通过互联网发送的吗?所以我们至少还需要三样东西。IP 头部是 20 字节,UDP 是 8 字节。那是传输,但不知何故,另一台计算机必须知道如何处理数据包。所以我们的框架的头部仍然缺失。Live 需要 16 个字节,XNA 需要大约 7 个字节。因此,我们有 51 个额外的字节没有存储任何数据。
好的。15.6 kB 是我们 8 kB 限制的两倍。如果您想通过 XNA 发送语音,则需要为每个队友每秒添加 500 个字节。
在这个例子中,我们有 25 个字节的(对于游戏)有用数据和 51 个字节的开销,这意味着我们使用了 67% 的带宽来填充“浪费”。我们不能完全减少这种浪费,但可以相对减少。如果我们将发送次数减少到每三帧一次(每秒 10 次,典型的频率是每秒 10 到 20 次)。假设我们仍然会发送当前帧的数据。因此,我们只会发送 5.2 kB 的数据,但我们仍然有 67% 的开销,并且有用数据更少。所以我们将最后两帧与我们的“发送”帧结合起来。为了简化操作,我们只在每一帧中发送我们的完整位置和方向 - 更好的做法是在第一帧中发送位置,而在第二帧和第三帧中使用更小的数据类型(方向也是如此)。
75 个字节的有用数据与 51 个字节的开销,这意味着只有 40% 的浪费,数据完全相同。听起来很棒,我们仍然将整个世界未压缩地发送给所有人。只是一个往返时间的比较。首先,我用 5250 字节的数据包大小对我的网站进行 ping 测试,然后使用 15960 字节的数据包大小。查看结果
最小值 | 最大值 | 平均值 | |
---|---|---|---|
5250 字节 | 110 | 255 | 140 |
15960 字节 | 217 | 317 | 264 |
我认为我无需解释,更多的数据也意味着更多延迟。
考虑以下问题
- 在游戏中我必须和谁交谈?
- 我必须知道我身后是什么吗?
- 灰尘颗粒向哪个方向反弹?
- 哪些星星在哪里?
- Linus 需要知道我穿的靴子还是我看着哪里吗?
- ...
好的。对于某些事情,您可能已经失去了思考,而对于其他事情,可能只是一个“什么……”。您可以忘记最后一种问题,如果您还记得,不是每个客户端都必须拥有相同的世界,而是彼此足够相似。其他问题应该被优先考虑。
在很多情况下,这并不容易。但其背后的想法是。玩游戏时,您已经拥有队友的一些数据。即使它们来自过去,您也可以将它们结合起来计算他们的移动方式。这就是预测,平滑现在处理的是所犯的错误。因为当有新的数据包时,显示原始位置而不是预测并不那么好(化身会跳跃)。这就是它如此困难的原因。
但是,您可以通过将物体的物理状态与其其余状态分离,并将它(以及物理模拟所需的所有内容)放在嵌套的辅助结构中来使其稍微容易一些。还可以为模拟发送更多数据。更多(和正确)的数据会导致更好的预测。因此,数据必须更少地发送。
由于敌人的位置只是一个预测或它的平滑和“现实”,玩家不能真正依赖于他看到的敌人就在那里 - 记住,我们生活在平行世界中,有些事情被认为是不同的,而另一些事情只是猜测。因此,当您将书扔到特定位置时,其他人可能在他的世界中稍微偏左一点,因此您错过了他。因此,最好是扔向这个人,让您的计算机计算您是否击中了他 - 以及您是如何错过的。
您还必须隐藏服务器(或其他对等体)响应玩家行为的往返时间。这很简单,用动画隐藏它。让角色说点什么,或者让他四处看看,好像在寻找路径。您也可以使用它与其他玩家同步。
- ↑ 一些部分可以在幻灯片 18 和 20 中找到 联网、交通拥堵和薛定谔的猫
- ↑ Chad Carter - Microsoft XNA Game Studio 3.0 Unleashed - 第 561 页