玩家需要流畅的移动

来源:互联网 发布:软件开发单价 编辑:程序博客网 时间:2024/04/30 00:43

        游戏虽然完成了,但是玩家体验很差,特别是走路的时候,总是很卡,这肯定是我们设计上的缺陷。

        最开始用的办法是玩家每移动一步,都向服务器提出申请,服务器检查玩家是否可以移动,如果移动速度和服务器这边的数据不匹配,或者正处于某些不能移动的状态下,则忽略客户端的移动请求,反之,同意玩家的移动,在服务器端设置新的坐标,并通知玩家自己和同屏内其他对象将其坐标更新到玩家移动后的位置。

        这样处理的优点是能避免玩家使用外挂,移动超过本身的速度,而影响游戏的公平性;缺点是当服务器忙于处理其它的事务操作来不及响应,或者玩家的网络状况比较糟糕时,玩家会卡的受不了。我们来计算一下这种情况下移动的时间差,假设玩家C1从客户端发起请求到服务器收到请求的时间需要t1,服务器处理移动的时间忽略不计,处理完成后将新坐标返回客户端C1需要的时间是t2,同时还返回给同屏的玩家C3,需要时间t3,那么,对玩家C1,看到自己移动一步的时间延迟=t1+t2;对玩家C2,看到C1移动一步的延时=t1+t3。

        难怪乎玩家会受不了了,修改设计是迫不及待的。优化时首先考虑玩家的体验,由客户端自己来控制移动速度,首先响应玩家的移动请求,把玩家坐标更新到目标位置,然后再告诉服务器,由服务器通知同屏内的其他玩家。这样玩家体验当然好了,但是外挂的怎么办呢?这个还是要靠服务器来把关。也就是说,服务器校验玩家移动速度这一步不能省掉,校验合格的坐标,才通知同屏内的玩家,并在服务器端将坐标设置到新的位置去,否则,仍然忽略客户端的移动消息。

        改了以后,再来计算一下移动延时,对C1,看到自身的移动时间延迟=0;对C2,看到C1的移动延时=t1+t3,就是同屏内的玩家看到C1的移动延时仍然存在,这在对pk的实时要求不是超级严格的游戏来说,已经够用了。最坏的情况就是,玩家使用外挂,自己跑了八丈远,但是同屏内的其他人看到他却还是在原地的,并且,虽然玩家从A坐标移动到了F坐标,却看不到F坐标附近的对象,包括玩家和npc等等,因为在服务器端,该玩家的坐标仍然是A坐标,并没有将F坐标同屏内的数据推送下来。

        还有一种情况,移动不是玩家主动发起的,而是由其它玩家或者事件造成的,比如冲撞等等,所以客户端不能只响应主动发起的移动,还需要响应服务器强制进行的移动,流程修改一点点。客户端保存了一个移动队列,玩家从A坐标移动到B坐标时,先在客户端修改玩家位置,然后将B坐标点保存到移动队列中,然后发送坐标到服务器端校验,校验成功后,服务器将新的坐标点B返回,客户端在移动队列里查找B坐标,如果找到了,就将B坐标从队列里删除;如果不在移动队列里,说明这个移动动作时服务器强制进行的,就把玩家重新设置到新的坐标去。

        改了这么多,是否就满意了吗,能不能让C2玩家看到C1的这个延时(t1+t3)缩短一点呢,再思考一下,其实是可以的。客户端C1获取服务器的时钟,粗略计算出消息包从本地到服务器的延时time_delay(实际就是前面定义的t1),然后把玩家的移动速度改成v-time_delay(仅仅是客户端单方面修改)。在服务器端呢,因为time_delay是客户端粗略计算的,并不十分精确可信。半夜网速好的时候可能误差很小,而晚上8点到10点可能又卡的想死,所以服务器端也为每个玩家建立一个移动队列,收到C1的移动请求后,不是直接进行移动操作,而是push到C1的移动队列中去,每经过一个移动间隔从队列里面取出一个坐标来执行。

        好了,再来计算一下移动延迟吧,对C1,看到自身的移动延迟=0;对C2,因为把t1省去了,看到C1的移动延迟=t3。