贪吃蛇大作战你个混蛋-别小看了异步消息

国庆期间我无意中下载了一个叫“贪吃蛇大作战”的“网络游戏”。当我玩的正嗨的时候有朋友告诉我这是个单机游戏。我瞬间感到我的智商被侮辱了。于是我开始回忆游戏中不对劲的地方,一想问题还不少。

  • 为什么我总是能拿到第一呢?
  • 为什么所有的蛇都只在吃球球的时候才加速呢?
  • 为什么我从来碰不到1000米以上的大蛇呢?

就算这些都是巧合,那作为一个网络游戏它是如何做到毫秒级的相应速度的?

不甘心的我在网上搜了一圈,果然应证了这个想法。不过应用商店里也有一些真实的多人贪吃蛇游戏,这些游戏的流畅性明显不如单机版的。

那么网络游戏为什么会出现如此严重的体验下降呢?我能想到的原因有三个:

  1. 多线程:多线程引发关键资源的竞争条件(Racing Condition),造成线程进入等待状态
  2. 不同玩家的网络延时不同
  3. 异步:网络请求以异步的方式完成。

1. 多线程

现在的网络游戏基本上都是多线程的,我们可以简单的把每个玩家看成服务器上的一个线程(真实情况肯定不止一个),当两个玩家同时访问一个资源的时候,其中一个玩家必须等待。如果多个玩家都在等待同一个资源这就会造成卡顿。

为了把问题简单化我们先不考虑游戏中的异步请求机制,那么如果每个请求都是通过同步的方式完成的,游戏体验会是则么样呢?要回答这个问题我们首先要分析这个游戏有哪些竞争资源,我就游戏中最常见的一种场景进行分析。

蛇吞食小球

在这个场景中小球对所有的玩家都是共享的,所以小球一定是需要同步机制的资源。对于小球的访问属于典型的read-modify-write类型的访问,如果不加以同步保护会出现一个同小球被多个玩家吞食的情况。

那个小球这个竞争资源会如何影响游戏的体验呢?让我们想象一下如果小球在任何一个时刻只能被一个线程访问,那么游戏的客户端在发出“吞食小球”这个请求的时候,蛇就不能继续移动,因为蛇并不知道这个小球资源是否已经被其他玩家上锁。于是蛇就会卡在原地不动,直到“吞食小球”的请求得到返回蛇才能继续移动。注意在这段等待服务器响应的时间里,玩家的任何操作都是没有响应的,当然游戏的开发者不会让这种卡顿发生,因为有异步消息机制。 游戏玩家真实感受到的是,在吃到小球后蛇的身体没有立即变成,而是过了几秒后才变长,在这之间玩家可以自由移动。

在“贪吃蛇大作战”中玩家吞食小球没有任何延迟现象,所以客户端并没有向服务端发起“我要吞食这个小球,请尝试锁住小球状态”的请求,当然不会有网络延迟。

2. 不同玩家的网络延时不同

不同的网络连接方式的延迟大不相同,有时甚至可能出现玩家掉线的情况。所以每一个客户端都需要和服务端进行同步,以确保每个玩家都处于一个统一的状态。下面我通过蛇与蛇撞击的例子说明网络延时对玩家的影响。

为了简化这个问题,我假设游戏中只有两个玩家A和B,A没有延时而B处于掉线状态。那么对于A来说他会看到B在屏幕上处于静止状态,而自己可以自由移动。这个时候如果A操作失误装上了B,那么直觉上A应该立即死亡变成小球。而实际情况是A不能立即判断自己是否真的装上了B,因为B此时可能已经掉线,所以A的屏幕上的B的位置可能是不真实的。这个时候A的客户端向服务器发出“A撞击B”的请求,由服务器来确认撞击是否是真实有效的。注意在等待响应的这段时间里A必须处于静止状态,也就是所谓的卡顿,当然游戏厂商也不会让这个发生,同样是借助了异步请求,真实的情况是A始终可以移动,它穿过B的身体就像什么也发生一样。

在“贪吃蛇大作战”中蛇的死亡是立即发生的,求好像屏幕上每一条小蛇的状态都是没有延迟的。这在真实的网络环境中是不可能实现的。

3. 异步请求

异步可以为玩家带来流畅的游戏体验,在这个游戏中这种意义上的流畅体现为玩家在任何时刻都可以移动小蛇。但是作为代价游戏中所有的请求都不会得到及时的反馈,而是等待服务器主动向客户端推送返回的结果。我们可以从两个事实中应证这个推测。

1. 小蛇身体加长的时机

首先小蛇在吞食了小球后身体并没有立即加长,而是过了半秒后才加长的,在此期间小蛇的移动没有任何卡顿。这个可以说明游戏客户发出“吞食小球”的请求后并没有加长蛇的身体,而是等待服务器处理完这个请求后主动发送消息给客户端,客户端接收到异步消息后更新小蛇的长度。实际中可能服务器每个一秒向客户端更新一次蛇的长度。

这种做法虽然使得吞食小球和身体加长之间隔了一秒,但是比起小蛇移动的卡顿显然是可以接受的。
在“贪吃蛇大作战”中,小蛇的身体是及时加长的,说明没有发生网络异步请求。

2. 其他蛇吞食小球后,小球消失的时机

我观察到在我的屏幕中其他小蛇吞食小球后,小球并没有立即消失,而是隔了一秒后才开始消失。这也能说明小球消失的消息是服务器异步发送给我的客户端的,因为如果如果在我的屏幕上看到其他蛇吞食小球,小球本可以立即消失,但是由于这个小球是一个竞争资源小球的状态还需要服务器来同步。这样的异步消息机制造成了屏幕上小球状态的延迟。

在“贪吃蛇大作战”中,其他小蛇吞食小球小球立即消失,由此可以推断不存在服务器发来的异步消息。

总结

我们可以得出两个结论:

  1. 网络版的贪吃蛇游戏需要在关键资源上上锁,这回导致卡顿。
  2. 我们可以用异步消息机制改善游戏的体验,这使得屏幕上事件的响应发生延迟。

在贪吃蛇游戏中这些延迟均不存在,所以基本断定这款游戏不需要联网。

当然真实的游戏设计要比这个复杂很多。例如每个玩家发送的请求都因该保存在一个队列中,队列按照先进先出的顺序处理,这可以避免逻辑上的错误(例如由于资源竞争导致小蛇撞击的请求比吞食小球请求先处理)等等。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值