7

我正在用 C# 编写一个 2D 空间 RTS 游戏。单人游戏有效。现在我想添加一些多人游戏功能。我搜索了一下,似乎只有一种方法可以让数千个单位在没有强大网络连接的情况下连续移动:只通过网络发送命令,同时在每个玩家身上运行相同的模拟。

现在有一个问题,整个引擎到处都使用双精度。浮点计算在很大程度上取决于编译器优化和 cpu 架构,因此很难保持同步。而且它根本不是基于网格的,并且有一个简单的物理引擎来移动太空船(太空船有冲量和角动量......)。因此,将整个内容重新编码以使用定点将非常麻烦(但可能是唯一的解决方案)。

所以到目前为止我有两个选择:

  • 告别当前代码并使用整数从头开始
  • 仅在有足够带宽的情况下制作游戏 LAN,以容纳 8 名拥有数千个单位的玩家,并在(几乎)每一帧中发送位置和方向等......

所以我在寻找更好的意见,(甚至是关于将代码迁移到定点而不搞乱一切的技巧......)

4

4 回答 4

2

当然,您的所有客户端都将使用相同的二进制文件,因此编译器优化对同步问题没有影响。

此外,如果您只计划针对一种架构(或者至少只允许人们在同一架构上进行对抗),那么这也无关紧要。

我在为 iPhone 和台式机开发游戏的 C# 中使用浮点数做了完全相同的事情,即使 iPhone 是 ARM 而台式机是 x86,它们都给出了相同的结果。

只要确保游戏进行完全相同的计算,你就会没事的。

如果一切都失败了,只需将float游戏中的所有实例替换为标准定点算术类即可。这样,您可以 100% 确定您的计算在架构中是确定性的,尽管定点算术的性质可能会对您的游戏产生不利影响。

于 2009-12-22T20:36:38.163 回答
1

我对此的回应有点晚了,但从游戏安全的角度来看,模拟应该只在服务器/主机上运行(即:不要信任客户端,他们可能在作弊):

  1. 客户端应该只将他们的动作/命令发送到服务器(它会丢弃错误的输入或将它们限制在游戏限制内,因此客户端说“我正在以 10,000m/s 的速度运行”被服务器限制为 10m/s )。

  2. 服务器/主机只告诉客户端他们视野内发生的事情(即:坐标为 0,0 的玩家不会被告知两个 AI 在 200,0 处相互战斗,如果他只能看到半径为他/她自己周围 50 个单位)。

这是节省带宽的第二部分——服务器/主机上的模拟可能有数千个对象需要管理,但客户端只需要知道他们自己视野内的大约 100 或 200 件事情。

这种情况下唯一的问题是动态火力(子弹、导弹等),其射程可能大于客户的视野半径。服务器/主机告诉客户端他们的起源和初始轨迹/目标对象,然后客户端根据相同的规则模拟他们的路径,但是杀戮只在服务器/主机上的模拟中有效。

序列化客户端特定的世界状态并在传输之前对其进行压缩也可能是一个巨大的胜利,特别是如果您的类属性仅在需要的地方是公共的。(我通常避免使用 XML,但我们通过序列化为 XML 并对其进行压缩,而不是序列化为二进制格式并对其进行压缩,从而显着提高了一个应用程序的压缩率。我怀疑使用的 ASCII 字符的有限范围在其中起到了作用,YMMV。)

于 2010-09-01T06:02:43.360 回答
0

一种常见的技术是让所有客户端定期向其他客户端描述它们的当前状态。

当两台计算机对一个对象的状态存在分歧时,可能是由于浮点错误,游戏有一些规则来确定哪个是正确的,所有客户端都会调整以匹配它。

于 2009-12-22T20:37:55.307 回答
0

你专门用双打做什么?你能用十进制代替吗?

一般来说,服务器会存储所有玩家单位的状态(位置/方向/类型)。

当 player1 移动一个单位时......移动指令被发送到服务器或......更新的状态被发送到服务器

当玩家客户端需要渲染场景时,服务器会发回请求范围内所有单元位置的状态信息。

于 2009-12-23T10:06:11.560 回答