• 网络游戏的同步


    近期完成一个稍稍涉及网络同步的游戏,结合网络上查到的一点资料和自己的心得做个小结。

          游戏描述:略形象的归纳为地图中5个玩家在5个不同位置消息,地图中有20个道具,玩家选择出发时间,出发角度和出发速度去奔向某道具。现在玩家1向server发消息,准备从当前currposition出发,对应的currtime,currangle,currspeed都确定,假定前方有prop1,现在服务器收到消息currservertime,然后广播玩家1的出发,那么玩家2,玩家3,玩家4,玩家5可能又由于网络原因接收到消息的时间是time2,time3,time4,time5。如果玩家1发出消息时开始绘图,玩家2,3,4,5接收到消息时绘图,这里就会产生一个不同步问题,玩家1和玩家2,3,4,5对应有一个time2,3,4,5-currtime的时间误差。而且中间还可能有5个玩家的本地时间并不相同的情况。

          首先可以通过服务器验证群发方式解决:玩家1发出消息的时候并不进行绘图,而是挂起等待服务器接收玩家1消息,广播给5位玩家之后大家一起绘图。考虑5个玩家本地时间不同的情况和网络延时时间,我们可以在玩家开始游戏的前进行一个玩家本地时间和服务器时间的误差比较,在服务器和5个客户端记录每个玩家和服务器的时间误差motifytime1,2,3,4,5。在服务器收到出发消息时,根据motifytime1,2,3,4,5确定玩家1,2,3,4,5每个人收到玩家1出发消息的绘图时间。这个方案在网络延迟很大发出消息的玩家会感觉极其不顺。很多并不是很需要及时通信的游戏会采用这种方式。

          如果玩家1在发出消息时就绘图,也可以通过motifytime方式进行同步,在服务器收到玩家1消息时,通过motifytime1计算出服务器中的玩家1出发时间,进行广播后玩家2,3,4,5根据自己的motifytime2,3,4,5判断接收到消息的时间和服务器发来的时间是否满足motifytime2,3,4,5范围,超出范围则计算出超出的时间,*speed后可以得到实际玩家1已经走到的位置positon1,当然我们可以用一个稍微快一点的speed到达position1后面的一点位置。

          还有一种好像是目前主流的解决方案,笔者没有实践拷贝网络资料:

          首先客户端需要在登陆世界的时候建立很多张广播列表,这些列表在客户端后台和服务器要进行不及时同步,之所以要建立多张列表,是因为要广播的类型是不止一种的,比如说有local message,有remote message,还有global message 等等,这些列表都需要在客户端登陆的时候根据服务器发过来的消息建立好。在建立列表的同时,还需要获得每个列表中广播对象的TimeModified,并且要维护一张完整的用户状态列表在后台,也是不及时的和服务器进行同步,根据本地的用户状态表,可以做到一部分决策由客户端自己来决定,当客户端发送这部分决策的时候,则直接将最终决策发送到各个广播列表里面的客户端,并对其时间进行校对,保证每个客户端在收到的消息的时间是和根据本地时间进行校对过的。那么再采用预测拉扯中提到过的计算提前量,提高速度行走过去的方法,将会使同步变得非常的smooth。该方案的优点是不通过服务器,客户端自己之间进行同步,大大的降低了由于网络延迟而带来的误差,并且由于大部分决策都可以由客户端来做,也大大的降低了服务器的资源。由此带来的弊端就是由于消息和决策权都放在客户端本地,所以给外挂提供了很大的可乘之机。
          基于这种方案的导航Dead Reckoning算法:

          大家都知道,在网络传输的时候,延迟现象是很普遍的,而在基于Server/Client结构下的网络游戏的同步也就成了很头疼的问题,在保证客户端响应用户本地指令流畅的情况下,没法有效的保证的同步的及时性。首先,这套同步方案是基于客户端之间的同步的。下面我们先来说一些本文中将用到的名词概念:
    网状网络:客户端之间构成的网络
    节点:网状网络中的每个客户端
    极限误差:进行同步的时候可能产生的误差的极值
    恩,在探讨其原理的之前,我们先来看看我们需要一个什么样的环境。首先,需要一个网状网络,网状网络如何构成呢?当有新节点进入的时候,通知该网络里面的所有节点,各节点为该客户端在本地创建一个副本,登出的时候,则通知所有节点销毁本地关于该节点的副本。然后每个节点该保存一些什么数据呢?首先有一个很重要的包需要保存,叫做协议数据包(PDU Protocol Data Unit),PDU包含节点的一些相关的运动信息,比如当前位置,速度,运动方向,或者还有加速度等一些信息。除PDU之外,还有其他信息需要保存,比如说节点客户端人物的HP,MP之类的。然后,保证每个节点在最少8秒之内要向其它节点广播一次PDU信息。最后,设置一个极限误差值。到此,其环境就算搭建完成了。下面,我们就来看看相关的具体算法:
    假设在节点A有一个小人(路人甲),开始跑路了,这个时候,就像所有的节点广播一次他的PDU信息,包括:速度(S),方向(O),加速度(A)。那么所有的节点就开始模拟路人甲的运动轨迹和路线,包括节点A本身(这点很重要),同时,路人甲在某某玩家的控制下,会不时的改变一下方向,让其跑路的路线变得不是那么正规。在跑路的过程中,节点A有一个值在不停的记录着其真实坐标和在后台模拟运动的坐标的差值,当差值大于极限误差的时候,则计算出当前的速度S,方向O和速度A(算法将在后面介绍),并广播给网络中其他所有节点。其他节点在收到这条消息之后呢,就可以用一些很平滑的移动把路人甲拉扯过去,然后重新调整模拟跑路的数据,让其继续在后台模拟跑路。
    很显然,如果极限误差定义得大了,其他节点看到的偏差就会过大,如果极限偏差定义得小了,网络带宽就会增大。如果定义这个极限误差,就该根据各种数据的重要性来设计了。如果是回合制的网络游戏,那么在走路上把极限误差定义得大些无所谓,可以减少带宽。但是如果是及时打斗的网络游戏,那么就得把极限误差定义得小一些,否则会出现某人看到某人老远把自己给砍死的情况。

          同步是网络游戏很重要的问题,如何同步也牵扯到各个方面的问题,比如说游戏的规模,游戏的类型以及各种各样的方面,对于规模比较大的游戏,在同步方面可以下很多的工夫,把消息分得十分的细腻,对于不同的消息采用不同的同步机制,而对于规模比较小的游戏,则可以采用大体上一样的同步机制,究竟怎么样同步,没有个定式,是需要根据自己的不同情况来做出不同的同步决策的。

          笔者完成的是一个休闲游戏,采用了第二种方式做预测拉扯方式完成,对玩家操作采用先绘图,其他玩家接收消息后预测拉扯。同时服务器端也建立一幅地图资源和玩家操作场景,类似服务器和客户端都是一幅地图下同样的位置更新,由服务器做定期更细玩家坐标,并在关键的获得道具等消息处理有服务器决定。

         最后摘抄以为网络大虾的的一点总结:

          以下六点,将助你分清楚哪些我们可以努力,哪些我们不值得努力,弄明白实时游戏中同步问题关键之所在,巧妙的化解与规避游戏,最终在适合普遍用户网络环境中(200ms),实现实时快速互动游戏:

    1. 基本情况:
       (A) 网络性能指标一:带宽,限制了实时游戏的人数容量
       (B) 网络性能指标二:延时,决定了实时游戏的最低反应时间

    2. 两个基本原则:
       (A) 让所有的用户屏幕上面表现出完全不同的表象是完全没有问题的。
       (B) 把这些完全不同表象完全柔和在一个统一的逻辑中也是完全没有问题的。

    3. 同步的十二条基本对应策略:
       (A) 最大可能减少游戏中的数据传输
       (B) 将阻塞通信放到线程池中实现
       (C) 永远不要为了等待某个数据而不让游戏进行下去
       (D) 利用预测和插值改进游戏的效果
       (E) 当使用预测插值的时候传送的数据不仅包括坐标,还需要速度和加速度
       (F) 将输入数据枷锁或者队列化(例如键盘消息队列),直到下次发送数据的时刻,传统的方法是在固定的时间(发送数据前)检测键盘,在游戏的原理上隐藏延时
       (G) 使用事件调度表,将需要在所有用户客户端同时发生的事件,提前广播到所有用户
       (H) 使用多次攻击来杀死一个精灵,尽量减少一次性的、确定性的、延时敏感的事件
       (I) 延长子弹或者火箭在空中飞行的时间(在其飞行的同时,在所有客户端进行预测插值)
       (J) 所有物体从一个地方移动到另外一个地方都需要时间,避免诸如“瞬间移动”的设计
       (K) 尽量使游戏中所有精灵,飞船或者其他物体,都按照可预测的轨迹运行,比如在移动中增加惯性
       (L) 充分发挥创造力,尽最大可能的合并游戏中前后相关的事件,合并游戏中存在的延时此问题,需要在技术上改进的同时也需要策划有所重视,规避一些影响较大的设计,巧妙的隐藏"延时"

    4. 同步问题现状:
       (A) 重视程度不够:很多人尚未意识到此问题的存在,曾有公司花半年时间打算做一款“松鼠大战”的网络版。
       (B) 技术上无彻底解决方案:对于多数程序员,单机游戏技术善未成熟就匆匆步入网络时代。
       (C) 研究这个技术需要条件:需要有实力的公司才能提供,无此条件,即便有能力的程序员也无法成功。

    5. 目前网游的三大技术难题:
       (A) 服务器的响应问题:如何使服务器在支持越来越多的人数的情况下提供最高的响应
       (B) 同步问题:如上在有限的网络响应情况下,实现快速实时类游戏,提供最完美的交互
       (C) 服务器分布式问题:如何在统一用户数据的情况下,利用分部式将各个分散的“世界”统一到一个“世界”中。
       谁能真正解决好以上三个问题,配合策划在设计上的突破,将使其他人在至少两年内无法超越。
       
    6. 相关补充:
       (A) 网格技术现在还是抄作,真正用到游戏中,还有很多技术难点需要突破(比如:目前网格的单位计算时间是以秒计算).
       (B) 其实与很多人想法相反的是现在3D技术早已不是主要的矛盾。而现在国内外对于以上三个问题可以说处于同一个起跑线上,完全有机会取得先机。
       (C) 现在解决同步问题已经很紧迫,而同时所需要的环境也已经成熟,只要有所关注,半年之内可以得出较成熟的结论

  • 相关阅读:
    时间序列数据
    python--模块
    聚类模型
    数模写作
    分类问题
    图论的基本概念
    706. Design HashMap
    第七讲异方差、多重共线性、逐步回归
    187.Repeated DNA Sequences
    C语言堆内存的分配和使用
  • 原文地址:https://www.cnblogs.com/wangbin/p/3935603.html
Copyright © 2020-2023  润新知