现在的位置: 首页 > 综合 > 正文

游戏中移动讨论

2018年05月04日 ⁄ 综合 ⁄ 共 3449字 ⁄ 字号 评论关闭

       前一阵子策划提出一个需求,需要在游戏内部做一个副本,副本中分成2个队,在一个圆形的台子上进行游戏,每个队6个人,每个人相互碰撞,目的是把对方碰下去,把对方一个人碰下去得1分,自己掉下去对方得1分,这个游戏想法很直接,逻辑很简单,但是要在网络游戏中实现难度却相当大

      网络游戏中玩家移动是游戏中一个很重要的部分,由于是一个“活动”的游戏,每个玩家希望跟现实中一样,周围环境有任何变化,包括其它玩家的移动都希望能够看到,起码延时不能太大(rpg游戏中通常延迟500ms是可以容忍的),那么这个是怎么实现的呢。

      通常大型mmorpg中客户端都连接到服务器,所有逻辑判断以及数据都以服务器为准,移动相关逻辑也是如此。玩家的运动信息需要发给服务器,服务器收到信息以后广播给需要了解这个玩家位置的其它玩家,包括他周围玩家,他的组队队友,以及其它需要这个信息的人。这里面主要包括两块逻辑,玩家自己的移动与自己看到的别人的移动。

     对于玩家自己的移动,有3种状态需要通知服务器:开始移动、移动进行、停止移动,这些信息发给服务器以后服务器以后会进行校验,如果不合理则对客户端进行校正并通知,通常是把玩家拉回到一个合理的位置,如果合理则服务器会根据需要转发给其它玩家,其它玩家收到信息以后做相应处理,下面会讲,这里主要先考虑玩家自己的移动,首先是玩家开始移动,玩家会通知服务器,我要动,其次是每隔一段时间,玩家通知服务器移动情况,包括当前位置,移动原因(走?跑?跳?飞?),与上一次发送消息使用的时间,速度,时间戳,在玩家停止的时候,发送的协议中需要增加一个朝向,别的玩家需要这个信息。

     比较重要的是玩家看的其它玩家的情况,mmorpg以及各种游戏包括fps游戏设计基本都坚持一个原则:让玩家动作能即时相应,其它玩家的操作时必然会有些延时的,虽然可以通过一些手段来弥补。就好像apple产品iphone、ipad对用户操作相应是第一位的,所以他们操作起来感觉特别“滑”。玩家看别的玩家主要通过两条协议来同步,首先是玩家移动协议,这条协议包含玩家移动的目标位置,移动原因,当前移动的速度。然后是停止,停止的时候客户端也会收到这个玩家停止的目标点,朝向,移动模式,停止之前移动速度。值得注意的是,如果这两个协议中目标位置与当前位置距离过大,则会直接拉过去,否则客户端自动调节这个玩家速度,让他“平滑”朝目标点移动。这些协议发的越快,两个客户端就越能实时看到对方移动信息,服务器处理数据包也会变大,mmorpg这个间隔通常100ms-500ms,cs中这个值可以随意设置。

     如果要实现开头提到的碰撞游戏,我们需要做哪些工作?由于要碰撞,延时100ms都是不能接受的,因为我不希望我看到碰到了别人,别人实际不在这个位置,或者别人明明离我很远,却将我碰开了,因此必须通过一些手段,让两个客户端看起来好像是实时同步的,最起码,两个玩家碰撞的时候必须能够达成一致,即碰撞以后双方移动方向、速度等信息必须一致。

     目前我们做了一些工作,但很不完善。我们目前的系统中,服务器校验很少,跟上面提到的普通移动一样,由每个玩家发起移动,不同的是开始移动信息会即时转给其它玩家进行模拟,根据这个玩家当前的位置和移动速度、加速度,这样,两个玩家位置的偏差就只跟网络数据传输需要的时间,我们加入了一些预测,使得两个玩家实际位置差值更小。玩家停止移动的时候,服务器会向周围所有玩家广播这个玩家最终位置,并做同步。总结一下目前所有同步都是在某个玩家停止的时候发生的, 包括玩家停止时候的广播、客户端看到别的玩家停止向服务器请求这个玩家位置。

      目前的这些工作在原始移动逻辑基础上做了改进,也加入了补偿,但是还有些很重要问题,1.没有反外挂措施,如果不对逻辑进行较大改变,很难添加较强的反外挂措施。2.两个玩家碰撞的时候没有统一碰撞点,虽然我们采用了一些补偿手段减小两个玩家实际位置、实际速度的偏差,但是只要有偏差,碰撞结果对细微的位置、速度偏差比较敏感,3.延迟补偿做的不够,只做了很简单的经验补偿。

      事实上要作出一个这样的系统是比较困难的,虽然不是不可能。目前我们还没有发现市面上有类似这样的游戏,目前的rpg、fps、rts游戏与这个需求都有很大的不同,而且这个需求中玩家移动加入了加速度,使得模拟变得困难。rpg、rts游戏事实上对位置不是特别敏感,fps游戏相对来说就要敏感的多,因此我们可以借鉴fps游戏射击中的一些经验。fps游戏中一般是怎么处理这种同步问题的呢?

      其它游戏是怎么做的呢,主要有两种方法,代表类型是星际争霸(sc)和反恐精英(cs)

      星际争霸每个客户端按固定时间间隔同步,比如100ms,每个同步间隔中间缓冲玩家输入(而不是直接执行逻辑),到达同步时间点后等待其他客户端发送过来的同步消息,所有消息都到达后执行逻辑以及下一轮同步,由于每个玩家执行的所有操作都是一致的,就保证了严格同步,缺点是如果某轮某个玩家网络数据没发出去,所有玩家就进入等待。

      经典的fps游戏当然是id-software的quake系列,valve的half-life、军团要塞。这些游戏同步过程主要采用两种思想:预测、补偿。首先保证客户端和服务器采用相同的逻辑来处理玩家移动、导弹移动等信息。首先是预测:客户端通常有2种预测方法,一种是外推,假设玩家移动速度5m/s,两个玩家延迟分别是100ms和50ms,我们假设收到协议的时候,玩家已经朝当前速度方向移动了5*0.15m,当然这个预测可能是错误地,因为可能玩家这时候已经刹车,或者朝别的方向移动,另一种方法是采用插值法,这种方法就比较精确了,通过引进固定的延时,比如100ms,保证本地显示延时这么长的时间,显然这样显示的位置是精确的过去某个时间玩家所在位置。那么引入的延时怎么处理呢,方法是采用延时补偿,服务器会收到每个玩家客户端显示的延时,在服务器进行逻辑处理的时候会考虑到这个值,比如玩家开枪,玩家延时100ms,那么是否击中通过计算100ms之前服务器状态来进行判断。就像我们上面提到,游戏设计的时候最重要的是让玩家玩的流畅,并且实际逻辑与玩家看到的接近。

      像tf中火箭手发射的火箭跟火箭被喷火兵反射后的效果可能稍微复杂些,但是由于在这个过程中最重要的是两点:第一,火箭兵需要感觉我的火箭是即时发射的,第二,喷火兵需要感觉火箭被我即时反弹并且反弹轨迹正确。事实上两步是分开的,在延时补偿基础上加以改动可以满足要求

      与fps游戏对比一下我们发现这个需求比fps游戏要难,首先,fps游戏中是否击中目标是最重要的,对我们来说在哪里碰撞是最重要的,但是fps中射击是单向的,我射击你或你射击我,而碰撞则我碰你的同时你也会碰我,这就对关键事件同步有更高的要求;其次,fps游戏视野有限,这个非常重要,因为fps游戏中如果双方面向移动,延时对是否击中影响不大,如果一方垂直于另一方的视线方向移动,延时对击中虽然影响比较大,但是这个时候另一方因为视线并没有朝向射击他的那个人,所以视觉效果不是很差,而我们的游戏则是一个3d视图;另外,我们游戏有加速度,增加了同步和逻辑处理难度。

      所以,要完成这样一个产品,6v6可以按正常的逻辑游戏,每个玩家看起来没有明显的逻辑问题,不会频繁出现拉人,碰撞错误等影响体验的情况。可能是一个非常困难的探索过程。但是有几点是确定需要注意的:

1. 碰撞需要仲裁。其实这个设计难点就在这儿,碰撞对延时是0容忍的,而实际游戏中延时又是不可避免,怎么处理比较难以权衡。如果类似fps游戏,服务器采用类似客户端的逻辑在跑,则服务器把计算到的碰撞结果发给客户端即可,如果服务器因为效率原因没法做运动逻辑,则需要一些别的方式进行仲裁,一种方法是增加一个“即将碰撞状态”,将可能的碰撞提前计算并由服务器锁定,这样客户端只需要模拟,两个碰撞的客户端将发生完全同样的碰撞。在这个碰撞为核心玩法的游戏中,碰撞必须统一。

2. 位置同步问题,由于碰撞必须在不同客户端呢同时发生,所以我们只能采用外推这种可能产生误差的方法,好在由于有加速度,速度不会急剧变化(不碰撞的情况),因此外推法产生的误差应该可以接受。

3. 由于这个需求对同步要求很强烈,可以采用根据距离远近,采用不同的发包频率,50-500ms?

实际开发过程中可能会有更多没有考虑到的问题。

抱歉!评论已关闭.