RTS游戏协议


18

我一直在考虑多人RTS游戏。我似乎无法解决的部分是保持单元运动同步。如果我将单元A移动到XY位置,则必须将其传达回中继到另一个客户端的服务器。

我很好奇通讯的样子。您是否只想与服务器将A单元从JZ移到XY进行通信?也许您需要逐个协调沟通运动?将单位从一个客户转移到另一个客户的最有效方法是什么?

编辑

这是stackoverflow重新发布的问题。我发现这个网站可能是个更好的地方。

该帖子的更好答案之一:

我假设您打算使用客户端-服务器网络范例?在这种情况下,您不能信任客户端来处理单元的实际位置,则必须将该任务委托给服务器。然后,您按时从每个客户端获取命令列表,并计算每个单元的移动,一旦完成,下一步就传递与每个客户端相关的每个单元的位置(以全图为基础,或者每个观看次数),然后重新开始该过程。


2
答案实际上取决于您要使用哪种方法。客户端-客户端或客户端-服务器。客户端到服务器更容易,但是它需要可信任的服务器
Cem Kalyoncu

Answers:


25

您不想将所有单元的位置从服务器同步到每个客户端;这会占用方式比你需要更多的带宽。您还必须处理插值/插值单元位置等问题。 几乎没有专业的RTS使用客户端/服务器!

相反,您只想发送玩家的命令。而不是在玩家单击时立即移动单位,而是将移动命令排队在将来的某个时候完成-通常只有几帧。每个人都将命令发送给每个人。几帧之后,每个人都执行所有命令,并且由于游戏是确定性的,因此他们都看到相同的结果。

缺点是每个玩家都和最慢的玩家一样慢-如果有人落后于发出命令,每个人都必须放慢速度并等待他追赶(在《星际争霸2》中,这是“ XXX正在减慢游戏速度“对话框)。


实际上,通常还有另外一件事要做: 完全淘汰服务器。让每个客户端将其命令发送给其他每个客户端。这样可以减少延迟(而不是从您那里发出命令->服务器->对手,而只是从您那里发出->对手) 并使编码更加容易,因为您不再需要编写单独的服务器了。这种架构称为对等(P2P)。

缺点是现在您需要一种解决冲突的方法,但是由于在大多数RTS中玩家的命令彼此独立,所以通常这不是什么大问题。此外,它的伸缩性也不佳-每次添加新玩家时,每个玩家都需要向他发送命令。您不会使用P2P制作MMO RTS。


这种设置(仅使用P2P发送命令)是大多数RTS(包括Starcraft,C&C和AoE)的工作方式,并且是AoE可能在28.8kbps连接上支持1500个单元的唯一方法。

(AoE中的网络图像)

这里有一些编写P2P RTS的技巧:

  • 出于显而易见的原因,此设置仅在您的游戏使用固定步长时间时才有效-您不希望计算结果取决于帧率!固定步骤在大多数情况下都更易于使用,因此这不是问题。
  • 为了使它起作用,每个命令的结果必须完全确定
    • 如果将自己限制在一个系统(例如32位Windows)上,并强制所有客户端使用相同的可执行文件,通常这很容易:确保任何随机数生成器具有相同的种子,并且始终以相同的顺序调用;遍历无序集合时要特别小心; 等等
    • 如果您打算使游戏可以在不同平台上玩,或者(例如,在Linux中通常如此)允许客户端自己编译代码,则这将非常困难。不仅可以保证不同的系统库可以使用的不同实现rand()cos()等等,而且几乎所有浮点数学运算都是不可能的(请参见此处此处此处!在这种情况下,使用客户端服务器可能会更好。
  • 您将希望每隔一段时间(至少在调试时)发出所有单元位置,以检测不同步的错误(相信我,您拥有)。是否将其保留在最终游戏中取决于您-我将至少同步一些单位(或使用某种校验和),以检测企图黑客入侵。

好帖子。要添加的小东西,即使是相同的编译器进行优化,调试/发布以及其他标志也可能会改变结果。小心!
彼得Ølsted,2011年

14

我制作了一个TCP网络RTS,在其中我自己传递了命令,而不是命令的结果。例如,玩家发​​出移动指令。如果移动订单根据该客户端有效,则将其发送到服务器。然后,服务器将其发送回所有客户端,由它们进行验证和执行。

因此,所有客户端计算机自己运行游戏,服务器代码接受消息并将其发送回所有客户端。如果客户给出了移动指令,则直到从服务器收到回单后,它才会开始执行。

服务器还会发送一个“ tick”号来执行该命令,该编号比“当前” tick提前几个tick。这样,所有命令都可以在所有计算机上以相同的“刻度”执行。

这种方法的一个好处是它不依赖任何单个客户端计算机来验证命令。如果我通过了移动的结果,我也许可以破解它以更快地移动我的单位。所有客户端都必须执行同一命令,并且如果一台计算机以不同的方式执行该命令,这将是显而易见的。

在将命令发送到服务器之前不需要在客户端进行验证,但是从理论上讲,它可以节省网络流量。我使用了相同的验证代码来告诉UI可以进行此操作,因此不需要编写额外的代码。

至于消息可能是什么样子。我并不担心超高效率,因为这是我的第一款网络游戏。我将命令作为字符串传递。命令的格式如下:"<player_id>:<command>:<parameters>"

对于一个人为的示例,移动命令可能如下所示: "3:move:522:100:200"。这意味着玩家3move单位522给(100200)。

服务器将命令传递给所有客户端(包括发送该命令的客户端),并带有以下标记号:"153238:3:move:522:100:200"

然后,在执行订单号153238时,客户端将全部执行此命令。


我向问题添加了更多信息。SO的答案似乎与您所说的相反,我很想讨论更详细的信息。
Darthg8r 2011年

是的,这是另一种实现方式,但在我看来,要传递这么多游戏状态而不是仅命令来进行更多的工作。我的游戏非常简单,整个事情可以在每台客户端计算机上运行。对于MMO或Minecraft之类的产品,您无法在客户端上运行整个模拟,因此您只传递与每个客户端相关的信息。
菲利普(Philip)
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.