# 同步

LLMS 索引： [llms.txt](/dvw/llms.txt)

---

信息在客户端和服务器之间传递需要时间。服务器执行命令也需要时间。在这段时间里，客户端得一直把虚拟世界显示下去。因此，屏幕上显示的东西未必是服务器所认定的当前世界状态的真实呈现：两者并没有同步。在真实世界里，太阳也许在 19 秒前就毫无缘由地爆炸了，而你还要再过八分钟才会知道。在虚拟世界里，你朝某人射出一箭，而对方可能四秒前就已经退出了。

因服务器负载而产生的延迟，可以通过购置更快的硬件、优化代码来解决。不过，对于通信造成的延迟，能做的就不多了。即便连接状况完美，光在玻璃中传播的速度 [^33] 也意味着：一个身在悉尼（Sydney）的人，玩着一个服务器设在圣迭戈（San Diego）的虚拟世界 [^34]，就算用直连电缆，每个方向也会有超过 0.06 秒的延迟。而通信还得经过路由器，走的又不是直线，这样一来，延迟就变成差不多三分之一秒了。再把模拟调制解调器算进去，又能多出三分之一秒。延迟总会发生。

设计师必须为此做出应对：设计里不要有任何对时间过于敏感的东西。在普通的电脑游戏里，可以让玩家掐着时间从风车的叶片、巨大的蒸汽活塞或钟摆似的镰刀之间穿过去；但在虚拟世界里，玩家在自己的客户端上看到一个缺口时，服务器上却没法保证真有这个缺口。正因如此，永远不能要求玩家做出反射动作（虽然可以要求他们的角色这么做），也就是说，虚拟世界里的 twitch（瞬时反应）少得可怜，甚至根本没有。

定时动作是可以做的，但成功的判定窗口至少要持续四秒，否则有些玩家会以为自己赶上了，实际上却错过了。不过，互联网可靠性的提高，还是让人尝试把第一人称射击游戏里常见的那种响应时间带进虚拟世界：《星际online》（Planetside）[^35] 就是其中最著名的先驱。

撇开精确计时的问题不谈，虚拟世界面对延迟其实相当稳健。玩家在什么确切时刻发起一个动作，很少要紧；玩家们约好“同时”做一件事的时候，心里清楚那是个模糊的概念。只要设计师不去刻意做任何需要速度的设计，就很少会出问题。

玩家忍受的延迟，虽然大部分在整条连接上相当恒定，但并非全都如此。有时候延迟会是一阵一阵的：一切正常运转，接着突然毫无明显原因地停住。这种延迟其实源于带宽问题，服务提供商因此启用了某种资源分配方案。你的宽带连接有多好都没用：如果 ISP 不把数据包发给你，你就是收不到。这种延迟能持续好几秒，随后所有被缓冲下来的数据包会一次性发出，服务恢复正常。

客户端要靠服务器定期发来的数据包，更新自己的本地状态。大多数时候，这些数据包都到得很及时。可是，只要有个和你用同一台路由器的人开始下载海量色情内容，数据包就免不了被拖慢。那么，遇到这种情况，客户端该怎么办？

最简单的解决办法是什么也不做。就那么坐着等，等数据包到了，再按顺序更新。问题在于：在更新到达之前，对玩家来说虚拟世界实际上已经冻住了。玩家可以试着做点什么，但在数据包重新流动起来之前得不到任何回应。同样的情况在文字世界里未必总是问题，但在图形化世界里，看起来就非常令人不安。

因此，大多数图形客户端使用一种预测模型：让物体沿着它们最后一次得到信息时的方向继续移动。如果一个角色正朝东跑，那么等更新包终于到达时，客户端多半还在让它朝东跑；画面因此是对的，而且从头到尾都没冻结过。预测模型在预测正确时效果很好（幸运的是，大多数时候都是如此）。可一旦预测错了，问题就来了。如果那个朝东跑的角色其实已经停下、转向了北面，那么它的实际位置，就可能和那个被拖延的客户端所显示的位置差出一大截。

要纠正失败的预测，有两种做法。传统的做法是采用新信息，把预测直接忘掉。这会产生一种叫 warping（跃迁）的效果，它最早出现在《空中勇士》（Air Warrior）里。玩家本来正咬着敌机的尾巴，那架飞机却突然从视线里消失，又在不远处瞬间重新出现，仿佛做了一次超空间跳跃。玩家甚至找到了诱发它的办法，这样就能安排好那架飞机重新出现的位置，取得战术上的优势。

更现代的客户端则是给物体显示出来的位置做渐进式平移，让它平滑地移到正确的位置上（虽然会慢一点，而且看上去仍然很可疑）。

对设计师来说，这意味着他们不仅不能用相对时间（“三秒后”），也不能用相对空间（“正前方”）。客户端可能以为某个坐标在玩家稍微偏左一点，而服务器知道它在稍微偏右一点。因此，需要坐标的命令必须使用绝对坐标，而不是相对坐标。还是那句话：只要设计师意识到这个问题，不去要求玩家在迷宫之类的地方执行复杂指令，虚拟世界通常就足够结实，应付得来；绝对坐标上有点小误差没关系。不过，他们首先得意识到这一点。

不过，有一种特殊情况：有时候玩家想对远处的其他玩家做点什么，比如朝他们射一箭。这种情况下，不仅弓箭手的位置可能与服务器的权威版本不一致，目标的位置也可能不一致。客户端知道玩家想朝某个角色射箭，却并不确知那个角色的坐标。设计师必须决定：这条命令究竟是“射击某个目标”，还是“射击某个位置”（但愿那个位置上正好有目标）。如果箭的飞行是定时的（如果它模拟的是真实的箭，那当然应该如此），出错的余地还会更大。

唉！

图形化虚拟世界呈现出来的是连续的空间。角色实际占据的也许是整数坐标，但它们有动画，会在这些坐标之间平滑地移动，于是给人一种印象：它们有时就处在坐标“之间”的空间里。

文字世界也可以是连续的，不过它们通常是毗连的。地点可以代表一个区域，而不是一个点，好几个角色可以同时处在这样一个地点 [^36] 而不引起任何异常。把水平方向的移动限制在八个罗盘方位上，意味着在这类虚拟世界里使用相对方向完全可行。果不其然，有些文字世界就允许玩家在移动时既使用绝对方向（北、东北、东等），也使用相对方向（前方、右前方、右等），房间描述采用哪种格式（绝对还是相对）也由玩家自己决定。图形游戏可以接收客户端发来的相对坐标，但发送出去时必须写成绝对坐标。

经验不足的客户端作者常犯的一个错误，就是把这一切都不当回事。客户端和服务器对什么东西在什么位置、朝哪个方向，看法略有出入，那又怎样？分歧大不到哪儿去。好吧，偶尔你确实会看到有人从实心的风车叶片里穿过去，因为他那边的客户端上有个空隙，可这实在算不上什么拦路虎。就让客户端来决定箭有没有射中吧，别把负担压在服务器身上。也许会有几次本该脱靶的判成了命中、本该命中的判成了脱靶，但时间一长总会扯平。

这就顺理成章地把话题引到了安全问题上。


[^33]: 大约每秒 197,000 公里。
[^34]: 在海平面上距悉尼大约 12,083 公里。
[^35]: http://planetside.station.sony.com/
[^36]: 这种地点叫作房间。
