我对这些类型的游戏的协议(和游戏循环)如何工作很感兴趣;任何指示或见解表示赞赏。
我猜主循环会有一个世界状态,每秒会提前几个“滴答”,但是玩家的命令是如何执行的?需要来回传输什么样的数据?
我对这些类型的游戏的协议(和游戏循环)如何工作很感兴趣;任何指示或见解表示赞赏。
我猜主循环会有一个世界状态,每秒会提前几个“滴答”,但是玩家的命令是如何执行的?需要来回传输什么样的数据?
我可以对此进行详细介绍,但首先,请阅读“1500 名弓箭手” http://www.gamasutra.com/view/feature/3094/1500_archers_on_a_288_network_.php,这将回答您的许多问题。这里有一个总结:首先,由于游戏的实时性,大多数游戏都使用 UDP。游戏循环看起来像这样:
这已经大大简化了,“搞砸物理”本身很容易成为一本 200 页的书,但它涉及预测客户端可能在哪里,从旧的服务器获取数据,但准确地告诉对象在哪里/应该在哪里是,然后以某种方式对这些值进行插值,以使对象看起来“足够接近”它实际上应该是没有人注意到的位置。这在第一人称射击游戏中是非常关键的,但对于实时战略来说却不是那么重要。
对于实时策略,通常发生的是基于回合的系统,其中时间被划分为称为“回合”的离散块,这些块按顺序发生,每个回合都有一个由单调函数生成的数字,该函数保证以特定顺序不断增加值,而无需重复。在任何给定的第 n 回合,每个客户端都会向所有其他客户端发送一条消息,其中包含他们在第 n + m 回合的预期动作,其中 m 是一个任意数字,通常相当小,可以通过反复试验以及游戏测试来最好地确定。一旦所有客户端都发送了他们想要的动作,每个客户端都会执行在第 n + m 轮发送的所有动作。这会在用户订购操作和执行操作时引入微小的延迟,但这通常不会引起注意。
有几种技术也可以用来捏造时间。例如,如果你高亮一个单位然后让它移动,它会在它开始移动时发出声音并有动画,但实际上不会立即移动。但是,移动该单位的意图的网络消息会立即发送,因此当屏幕响应玩家的输入时,网络消息已经发送并确认。您可以通过在鼠标点击和游戏对象的响应之间引入一个小的延迟(100 毫秒左右)来进一步捏造它。玩家通常不会注意到这一点,但 100 毫秒在 LAN 游戏中是永恒的,即使在家用计算机上使用宽带连接,平均 ping 也可能在 15-60 毫秒左右,这让您有足够的时间在之前发送数据包移动。
至于要发送的数据,游戏中有两种类型的数据:确定性和非确定性。确定性动作以游戏物理为基础,因此当动作开始时,可以 100% 保证我可以预测该动作的结果。这些数据永远不需要通过网络发送,因为我可以根据初始状态确定客户端上的数据。请注意,在每个客户端上使用具有相同种子的随机数生成器会将“随机”事件转变为确定性行为。非确定性数据通常是用户输入,但在许多情况下可以预测用户的输入可能是什么。这些在实时战略游戏中配对的方式是,非确定性事件是我的一个游戏对象的某种顺序。一旦游戏对象被命令移动,它移动的方式是 100% 确定的。因此,您需要在网络上发送的只是对象的 ID、给定的命令(将其设为枚举以节省带宽)和命令的目标(如果有的话,因此如果咒语是影响区域,但移动命令有终点)。如果用户点击 100 次来进行单位移动,则无需为每次点击发送单独的移动命令,因为它们都在同一个通用区域,因此请务必将其过滤掉,因为它会杀死你带宽。
处理命令与其执行之间可能的延迟的最后一个技巧是称为局部感知过滤器的东西。如果我在下达命令后的某个时间 t 收到移动命令,我知道该单元应该何时开始移动并且我知道它的最终目的地。与其将单位传送到它应该在的位置,我可以晚点开始它的运动,然后用物理方法稍微加快它的速度,这样它就可以赶上它应该在的位置,然后再放慢速度把它放在正确的地方。加速它所需的确切值也是相对的,游戏测试是确定正确值的唯一方法,因为它只需要“感觉正确”才能使其正确。你也可以用发射子弹和导弹来做同样的事情,这非常有效。
接下来要考虑的是减少带宽。不要将消息发送给无法看到或与正在移动的单元交互的客户端。不要因为用户点击而一遍又一遍地发送相同的消息。不要立即为没有立即影响的事件发送消息。最后,如果事件无法被接收,则不需要确认将过时的事件。如果我没有收到移动更新,当我重新传输该更新时,它的值将太旧以至于不再相关,因此最好只发送另一个移动并使用本地感知过滤器来赶上或使用三次样条插值运动,使其看起来更正确或类似性质的东西。但是,重要的事件,例如“你死了”或“
此处讨论帝国时代网络架构
恕我直言,这种基于点对点重复回放的架构风格令人印象深刻,但对于超过 8 个左右的玩家来说,这有点死胡同。