4lqedz 发表于 2024-8-31 04:38:37

对抗网络延迟 手游服务器实时同步办法分享


    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz/uicUKliaDticRYeHTVMxwgkHEVfsXaORlmocUXYcgTAwvtsU6RJ3a597nDSFu9mqe1fbNIjO77TBsibAyxOxiaaojBQ/640?wx_fmt=jpeg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">网络延迟是所有实时同步的游戏都会遇到的问题,下面是关于实时同步问题的<span style="color: black;">有些</span>思考和处理<span style="color: black;">办法</span>。<span style="color: black;">详细</span>的<span style="color: black;">处理</span><span style="color: black;">办法</span>可能比较特殊,<span style="color: black;">首要</span><span style="color: black;">这儿</span>的服务器并不跑<span style="color: black;">按时</span>器(除了一个游戏结束倒计时的<span style="color: black;">按时</span>器),由前端驱动,延迟的<span style="color: black;">状况</span>下<span style="color: black;">重点</span><span style="color: black;">是由于</span>前端来预测或纠正,服务器辅助,处理和转发,据我的<span style="color: black;">认识</span><span style="color: black;">好似</span>没什么人<span style="color: black;">这般</span>子搞吧。<span style="color: black;">因此</span>看完<span style="color: black;">倘若</span>觉得我这边有<span style="color: black;">思虑</span>不周的,<span style="color: black;">或</span>有更好的思路,欢迎拍砖 / 交流。</span><span style="color: black;"><span style="color: black;">首要</span>这是一个两边出兵对攻的游戏,<span style="color: black;">仅有</span>2个玩家,而战场上士兵/英雄的数量<span style="color: black;">亦</span>不会太多,最多不会超过50个吧,士兵都是有AI的,不被玩家<span style="color: black;">掌控</span>。玩家能做的操作<span style="color: black;">特别有</span>限,<span style="color: black;">这儿</span>只以出兵这个操<span style="color: black;">做为</span>例。在游戏<span style="color: black;">起始</span>的时候,会有一次校时操作,这个后面会说到。</span><span style="color: black;">玩家A在Tick1点出兵,播放<span style="color: black;">各样</span>出兵特效之后,Tick1 + Delay = Tick2,在Tick2这个时间才会真正出兵,Delay等于抬手时间,<span style="color: black;">亦</span><span style="color: black;">便是</span>一个<span style="color: black;">准许</span>的延迟时间,并不等于网络延迟,应该理解为一个前摇动画的播放时间,这个时间越长越好,在不影响玩家体验的前提下(例如弄一个士兵生产队列,从出兵指令发出到士兵生产完毕,这可需要不少时间)。</span><span style="color: black;"><span style="color: black;">此时</span>候玩家请求服务器,请求的内容<span style="color: black;">包括</span>Tick1 + 出兵指令,服务器收到指令,对服务器而言,<span style="color: black;">此时</span>可能有两种<span style="color: black;">状况</span>,<span style="color: black;">第1</span>种是在Tick2之前收到,第二种是在Tick2之后收到</span><span style="color: black;">在Tick2之前收到,服务器<span style="color: black;">能够</span>转发操作,告诉所有的客户端,<span style="color: black;">咱们</span>在Tick2出兵(包的内容<span style="color: black;">包括</span>Tick2和出兵指令),<span style="color: black;">此时</span>候对<span style="color: black;">另一</span>一个玩家,他可能看不到出兵的特效,而是直接看到出兵,这<span style="color: black;">无</span>问题,<span style="color: black;">或</span>他看到的特效在时间上晚了<span style="color: black;">有些</span>,这都是<span style="color: black;">能够</span>接受的,不影响游戏<span style="color: black;">规律</span>的。</span><span style="color: black;">这是前后端网络正常时的<span style="color: black;">状况</span>:</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz/uicUKliaDticRYeHTVMxwgkHEVfsXaORlmoCyO0e1M17qRBRX3MRIUtsGe39N8ibvAP6Gf4aovFEicxliag10ucGV3Cg/640?wx_fmt=jpeg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">在Tick2之后收到,服务器<span style="color: black;">能够</span>丢弃这个操作,<span style="color: black;">或</span>立刻执行这个操作,<span style="color: black;">此时</span>候<span style="color: black;">已然</span>是Tick3了,广播给所有玩家,在Tick3出一个兵,<span style="color: black;">由于</span><span style="color: black;">此时</span>服务器<span style="color: black;">已然</span>是Tick3,<span style="color: black;">那样</span>客户端收到出兵指令的时间是<span style="color: black;">已然</span>过了的,<span style="color: black;">此时</span>候会<span style="color: black;">引起</span>客户端<span style="color: black;">必定</span>会进行一次纠正,<span style="color: black;">那样</span><span style="color: black;">咱们</span><span style="color: black;">能够</span>再延一延,让这个指令在Tick4再执行,Tick3 + Delay2 = Tick4。丢弃,Tick3,Tick4执行的结果分别是,玩家的操作无效,战斗需要经过一次纠正(纠正会<span style="color: black;">引起</span>玩家看到奇怪的东西),以及玩家的操作延迟了,<span style="color: black;">然则</span>看到的东西是正常的,只是我的操作晚了一段时间<span style="color: black;">罢了</span>。</span><span style="color: black;">服务器延迟执行这个指令,客户端在生效时间之前收到,大概是<span style="color: black;">这般</span>子的:</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz/uicUKliaDticRYeHTVMxwgkHEVfsXaORlmoHWzvZfrAD9B3JmtEJzXntDN0CXOyVlicGI71Tl4iaIWFARpXh3giaME2w/640?wx_fmt=jpeg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">所有的指令从触发到生效都不是立即的,都是经过延迟的,哪怕我的网络延迟在1ms之内,我这个指令都要在delay时间之后才执行,而前后端都会有一个指令Queue,来记录在哪一帧应该执行哪一个指令。</span><span style="color: black;">所有的指令,只要做到在第几帧执行的统一,就<span style="color: black;">能够</span><span style="color: black;">保准</span>结果的统一。</span><span style="color: black;">客户端接收到指令的时候,<span style="color: black;">此时</span>候又有2种可能,分别是在Tick2之前,以及Tick2之后。</span><span style="color: black;">在Tick2之前收到,<span style="color: black;">那样</span>皆大<span style="color: black;">高兴</span>。在Tick2之后收到,<span style="color: black;">那样</span><span style="color: black;">咱们</span>这个操作就延迟了,可能要进行纠正,<span style="color: black;">这儿</span>说可能,<span style="color: black;">由于</span>还有一线生机。<span style="color: black;">便是</span>玩家点出兵之后,并不等服务器返回,而是在Tick2时自动出兵,<span style="color: black;">这般</span>子的一个好处是,客户端在网络比较差的<span style="color: black;">状况</span>下,所有的东西都<span style="color: black;">能够</span>得到反馈。虽然这些反馈可能是错误的,<span style="color: black;">然则</span><span style="color: black;">不碍事</span>,关键是玩家体验的流畅,错了最后肯定会被纠正,只要处理好纠正时候的表现就<span style="color: black;">能够</span>了。</span><span style="color: black;"><span style="color: black;">倘若</span>自动客户端<span style="color: black;">自动</span>预测:</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz/uicUKliaDticRYeHTVMxwgkHEVfsXaORlmoUmRIWTUToSRtFhtZe3ATF5cs4nMibza30hUm9fTGpdDhgbqAdO2ibhjA/640?wx_fmt=jpeg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">况且</span><span style="color: black;">这般</span>子做不<span style="color: black;">必定</span>是错的,<span style="color: black;">倘若</span>服务器在Tick2之前收到我的请求,<span style="color: black;">那样</span>服务器会在Tick2执行出兵的<span style="color: black;">规律</span>,而我在Tick2之后收到服务器的响应,但我<span style="color: black;">亦</span>在Tick2执行了出兵的<span style="color: black;">规律</span>,这是同一帧,这种<span style="color: black;">状况</span>下是不需要纠正的,<span style="color: black;">由于</span>虽然延迟了,<span style="color: black;">然则</span><span style="color: black;">咱们</span>正确预测到了结果。需要纠正的有两种<span style="color: black;">状况</span>,<span style="color: black;">第1</span>种是B玩家在Tick2之后收到,<span style="color: black;">由于</span>B玩家是<span style="color: black;">没法</span>预测到A玩家在Tick1点击了出兵,在Tick2出了一个兵。第二种是服务器在Tick2之后才收到,<span style="color: black;">那样</span>两个端可能都需要纠正,<span style="color: black;">这儿</span>说可能,<span style="color: black;">由于</span>还有<span style="color: black;">另一</span>的一线生机。</span><span style="color: black;"><span style="color: black;">倘若</span><span style="color: black;">咱们</span>不做预测,而是等服务器的结果,<span style="color: black;">按照</span>服务器的结果来执行,这种<span style="color: black;">状况</span>下,客户端的表现是流畅的,战斗是流畅的,只是我的点击<span style="color: black;">无</span>立即反应<span style="color: black;">罢了</span>。服务器在Tick3下发(内容<span style="color: black;">包括</span>Tick4 + 出兵指令),在Tick4执行,客户端只要在Tick4之前能收到,就<span style="color: black;">能够</span>在Tick4执行出兵,<span style="color: black;">那样</span>结果<span style="color: black;">亦</span>是正确的。这种<span style="color: black;">乃至</span><span style="color: black;">咱们</span><span style="color: black;">能够</span>以服务器收到的时间为准,服务器每次收到都在当前时间的<span style="color: black;">基本</span>上延迟一段时间来执行,完全无视玩家点击的时间,只要客户端在这段延迟时间内收到结果,<span style="color: black;">亦</span>是不需要纠正的。</span><span style="color: black;">这两种一线生机的区别在于,一个是忽略了包从服务器回来的延迟,一个是忽略了包到服务器的延迟,一个是<span style="color: black;">保准</span>客户端流畅,一个是<span style="color: black;">尽可能</span>避免纠正。<span style="color: black;">详细</span>要在<span style="color: black;">实质</span>环境中测试<span style="color: black;">才可</span><span style="color: black;">晓得</span>,哪种更适合我们游戏。<span style="color: black;">因为</span>所有指令的执行会放在一个队列中,<span style="color: black;">因此</span>这几种方式的切换只需要改动少量的代码。当<span style="color: black;">咱们</span>拿捏不准的时候,尽可能让这部分<span style="color: black;">能够</span>被灵活地<span style="color: black;">调节</span>。<span style="color: black;">全部</span>服务器这边的Tick机制<span style="color: black;">便是</span><span style="color: black;">能够</span>被灵活<span style="color: black;">调节</span>的(<span style="color: black;">由于</span>我不跑<span style="color: black;">按时</span>器)。</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz/uicUKliaDticRYeHTVMxwgkHEVfsXaORlmoXiaoZqr8CRNbGAcFtP2X5ibjNiaAibV2RolkS0fok31UeN0Pny6Necbb7g/640?wx_fmt=jpeg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">最后<span style="color: black;">便是</span>纠正了,<span style="color: black;">首要</span>纠正<span style="color: black;">是由于</span>前端发起的,当<span style="color: black;">而后</span>端<span style="color: black;">亦</span><span style="color: black;">晓得</span>前端延了,后端的处理其实比较随意,无关紧要,前面说的,丢弃,立即执行,<span style="color: black;">或</span>延迟执行,都是<span style="color: black;">能够</span>的,但看上去延迟执行是个更好的主意,这个<span style="color: black;">亦</span>看<span style="color: black;">详细</span>游戏吧。前端<span style="color: black;">怎样</span><span style="color: black;">晓得</span>自己延了,这个问题其实很简单,在战斗<span style="color: black;">起始</span>的时候进行一次校时,<span style="color: black;">而后</span>双方都以一致的频率,例如每秒10帧,从第0帧<span style="color: black;">起始</span>前进(<span style="color: black;">实质</span>上服务器只是记录一个时间,并不跑<span style="color: black;">按时</span>器)。</span><span style="color: black;">其实前后端只要记录了第0帧的这个<span style="color: black;">起始</span>时间,是很容易算出当前是在第几帧的,前后端的这个<span style="color: black;">起始</span>时间并不相等,只是<span style="color: black;">规律</span>上相对<span style="color: black;">罢了</span>。当然,这个时间<span style="color: black;">亦</span>会存在误差,误差的结果<span style="color: black;">便是</span>,一边快一点<span style="color: black;">或</span>慢一点。<span style="color: black;">然则</span><span style="color: black;">不碍事</span>,<span style="color: black;">咱们</span>不是<span style="color: black;">根据</span>时间来算,<span style="color: black;">咱们</span>是<span style="color: black;">根据</span>帧来算,咱不<span style="color: black;">需求</span>同一个时间两个端的内容是完完全全的<span style="color: black;">同样</span>,咱只<span style="color: black;">需求</span>结果<span style="color: black;">同样</span>。例如一台设备性能很差,每秒5帧,<span style="color: black;">然则</span>他的结果不会错误,游戏10秒后结束,他这边就20秒后结束,但结束时的结果是<span style="color: black;">同样</span>的就行,至于操作,<span style="color: black;">倘若</span>存在<span style="color: black;">这般</span>的可能性,那服务器就把操作延迟执行,对前端<span style="color: black;">罢了</span>可能按下去要等好几秒<span style="color: black;">才可</span>响应,但<span style="color: black;">此时</span>候都<span style="color: black;">已然</span>不是网络延迟的问题,是设备卡顿的问题。前端<span style="color: black;">始终</span>在跑,<span style="color: black;">然则</span>跑<span style="color: black;">不外</span>来,要<span style="color: black;">处理</span>这个问题,只能是换手机,当然<span style="color: black;">咱们</span>自己要<span style="color: black;">保准</span>在性能很差的手机上能跑起来才行,例如两三年前的<span style="color: black;">设备</span>,但<span style="color: black;">实质</span>上咱<span style="color: black;">亦</span>不需要花太多心思在这上面,这个玩家这么烂的手机都不舍得换,怎么舍得往游戏里面充钱呢?直接放弃他了。</span><span style="color: black;">服务器并不跑计时器,这是什么<span style="color: black;">原由</span>呢?有一部分是性能的<span style="color: black;">原由</span>,<span style="color: black;">每一个</span>子弹,怪物,BUFF这些可能都需要挂计时器,我不<span style="color: black;">期盼</span>服务器挂太多的计时器。比<span style="color: black;">很强</span>的一部分是让拿捏不准的这部分更加的可控。例如这个游戏不做实时同步了,让事情变得不是<span style="color: black;">那样</span>糟糕。只需要少许的改动,就<span style="color: black;">能够</span>实现服务器的校验。</span><span style="color: black;">不跑计时器怎么做呢?很简单,<span style="color: black;">首要</span>你还是需要有一个计时管理的,类似Schedule,游戏<span style="color: black;">规律</span>中添加的计时器全放到<span style="color: black;">这儿</span>面,当客户端请求的时候,<span style="color: black;">咱们</span>先从上一次计算的时间模拟到当前时间,将当前时间减去上次的时间,算出有N帧,<span style="color: black;">而后</span>直接 loop N次计时器,这个loop和客户端的loop相比,<span style="color: black;">便是</span>少了<span style="color: black;">有些</span>判断逝去时间<span style="color: black;">是不是</span><span style="color: black;">少于</span>最小间隔时间,<span style="color: black;">倘若</span>是则sleep一下<span style="color: black;">这般</span>的代码,而改<span style="color: black;">成为了</span>一个for循环,循环N次。当然,loop的不<span style="color: black;">必定</span>只是计时器,<span style="color: black;">然则</span><span style="color: black;">必定</span><span style="color: black;">包括</span>计时器,<span style="color: black;">况且</span>最<span style="color: black;">重点</span>的<span style="color: black;">便是</span>计时器。</span><span style="color: black;">loop完之后,将上次的时间记录为当前时间,<span style="color: black;">而后</span>进行校验,转发指令。<span style="color: black;">此时</span>并不执行指令,而是把<span style="color: black;">经过</span>校验的指令放入指令队列中,等待下次执行。指令执行的结果是什么,服务器<span style="color: black;">此刻</span>是不<span style="color: black;">晓得</span>的。<span style="color: black;">能够</span>看到是客户端的请求来驱动服务器,而不是计时器来驱动服务器运行<span style="color: black;">规律</span>。这就有点类似回合制了。<span style="color: black;">那样</span>还有一个问题,假设客户端都不发请求,那服务器不就动不了了?服务器会跑一个计时器,这个计时器只做一件事,<span style="color: black;">便是</span>游戏结束,模拟玩家发一个空的指令到服务器这边,服务器loop到游戏结束,<span style="color: black;">而后</span>下发战斗结果。</span><span style="color: black;">不跑计时器,<span style="color: black;">怎样</span>让当这个游戏从实时同步变成非实时同步变得简单呢?<span style="color: black;">能够</span><span style="color: black;">这般</span>子,客户端所有发送的指令,<span style="color: black;">所有</span>都在客户端直接运行,<span style="color: black;">然则</span>记录下来,<span style="color: black;">而后</span>在游戏结束时,请求一次服务器,将指令队列发给服务器,服务器只需要设置指令队列,<span style="color: black;">而后</span>执行一次loop到游戏结束的调用,自然<span style="color: black;">能够</span>校验到战斗结果。这个非实时同步的<span style="color: black;">需要</span>,本身<span style="color: black;">便是</span>存在的,例如单刷副本,这个<span style="color: black;">咱们</span>是需要校验的。<span style="color: black;">因此</span>只需要在外面进行一层包装,就<span style="color: black;">能够</span>替换<span style="color: black;">她们</span>。<span style="color: black;">况且</span>改动的代码量并不多。</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz/uicUKliaDticRYeHTVMxwgkHEVfsXaORlmonwtwv5yVqstmWKmBfOnmRNR4VPAia9ibPIterTYrqlVWkuIjnfeAdBnQ/640?wx_fmt=jpeg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">接下来还是说纠正的问题,当客户端<span style="color: black;">发掘</span>服务器下来的包延迟了,超过可接收的时间了,客户端需要向服务器请求最新的数据来刷新,这个过程中,客户端是正常运行的,<span style="color: black;">而后</span>当数据下来之后,大概花0.5-1秒的时候来刷新数据。将本地有服务器<span style="color: black;">无</span>的对象干掉,本地<span style="color: black;">无</span>服务器有的对象创建,两边都有的数据进行一个平滑的插值计算,让他在这段时间过渡到最新的数据。<span style="color: black;">这儿</span><span style="color: black;">必定</span>会产生<span style="color: black;">有些</span>玩家看起来很奇怪的画面,在上面加一个正在重新连接...,玩家应该会比较能接受这小段看上去奇怪的画面。</span><span style="color: black;">过渡的时间内,本地的实时<span style="color: black;">规律</span>帧是<span style="color: black;">始终</span>在正常运行的,它记录服务器当前运行到第几帧了,本地还有<span style="color: black;">另一</span>一个帧变量,这个变量<span style="color: black;">暗示</span>当前<span style="color: black;">规律</span>帧,这两个帧都是<span style="color: black;">规律</span>帧,正常而言,这两个帧是相等的,但当纠正<span style="color: black;">出现</span>时,当前帧会<span style="color: black;">少于</span>实时帧,例如第200帧<span style="color: black;">发掘</span>我本地需要纠正,<span style="color: black;">而后</span>请求服务器,服务器下发了最新,<span style="color: black;">亦</span><span style="color: black;">便是</span>201帧的结果下来,到客户端这边,<span style="color: black;">已然</span>是207帧了,但重置到最新的数据,<span style="color: black;">亦</span><span style="color: black;">便是</span>201帧,<span style="color: black;">而后</span><span style="color: black;">起始</span>加速执行。执行到两个<span style="color: black;">规律</span>帧相等,即恢复正常速度执行。</span><span style="color: black;"><span style="color: black;">首要</span>加速是可行的,<span style="color: black;">由于</span>服务器<span style="color: black;">能够</span>瞬间执行完,<span style="color: black;">那样</span>客户端<span style="color: black;">为何</span><span style="color: black;">不可</span>加速执行完呢?最关键的是,每一帧的结果都是<span style="color: black;">同样</span>的,前面从200帧之前,客户端有一部分的结果就<span style="color: black;">已然</span>错误了,纠正的本质是把错误的结果丢弃,<span style="color: black;">而后</span>重新设置正确的结果。再继续运行。</span><span style="color: black;"><span style="color: black;">另一</span>假设是客户端跑得太慢,跟不上服务器的话,那<span style="color: black;">实质</span>上服务器<span style="color: black;">运用</span>延迟执行的方式,基本上是不会有纠正的<span style="color: black;">需要</span>的,<span style="color: black;">由于</span>所有指令<span style="color: black;">针对</span>这台设备而言,都是未<span style="color: black;">出现</span>的,客户端只能慢慢跑,慢慢演示战斗结果。<span style="color: black;">这般</span>的设备上,动画都是一卡一卡的,问题<span style="color: black;">已然</span>从网络延迟的问题转变为设备的性能问题了,这是<span style="color: black;">另一</span>一个优化的<span style="color: black;">专题</span>了。</span><span style="color: black;"><span style="color: black;">规律</span>帧和<span style="color: black;">表示</span>帧的分离,有这么几个目的,<span style="color: black;">规律</span>帧用来<span style="color: black;">保准</span><span style="color: black;">规律</span>的准确性,<span style="color: black;">亦</span><span style="color: black;">便是</span>这场游戏一共跑2000帧,执行2000次<span style="color: black;">规律</span>处理。这部分是前后端共用的。至于前端的<span style="color: black;">表示</span>刷新了8000帧,还是6000帧,影响的只是动画的平滑度<span style="color: black;">罢了</span>,不影响结果,前端花100秒还是200秒来跑完游戏,<span style="color: black;">亦</span>是不影响结果的。第二是方便纠错和加速,<span style="color: black;">规律</span>帧和<span style="color: black;">表示</span>帧的交互流程是<span style="color: black;">这般</span>的,每次<span style="color: black;">规律</span>帧执行的时候,会修改类似位置<span style="color: black;">这般</span>的属性,<span style="color: black;">或</span>改变<span style="color: black;">有些</span>状态。<span style="color: black;">表示</span>帧负责平滑地从当前位置,状态改变到<span style="color: black;">规律</span>帧修改的位置和状态,并播放相应的动画。<span style="color: black;">规律</span>帧并不直接改变这些属性,而是将这些修改放到一个<span style="color: black;">每一个</span>对象特有的数据组件中,<span style="color: black;">规律</span>判断时,是取这些里面的数据来判断,而不是<span style="color: black;">表示</span>层的数据。每次更新,<span style="color: black;">表示</span>帧都会做一个从当前过渡到该数据的<span style="color: black;">规律</span>。<span style="color: black;">规律</span>帧的频率加快了,对<span style="color: black;">表示</span>帧<span style="color: black;">罢了</span><span style="color: black;">亦</span>是<span style="color: black;">无</span>影响的,两者互相独立,<span style="color: black;">规律</span>帧只管<span style="color: black;">规律</span>处理还有写数据,<span style="color: black;">表示</span>帧只管取出数据来进行<span style="color: black;">表示</span>。</span><span style="color: black;">客户端这边,<span style="color: black;">规律</span>帧和<span style="color: black;">表示</span>帧都<span style="color: black;">是由于</span>同一个Schedule来驱动运行的,但频率<span style="color: black;">区别</span>,<span style="color: black;">她们</span>比<span style="color: black;">很强</span>的一点区别是,<span style="color: black;">规律</span>帧每一帧的dt是一个固定的值,例如每秒10次<span style="color: black;">规律</span>帧,<span style="color: black;">那样</span>这个dt就固定是0.1,而<span style="color: black;">表示</span>帧是<span style="color: black;">按照</span><span style="color: black;">实质</span>的逝去时间来<span style="color: black;">做为</span>dt的。<span style="color: black;">这儿</span>的dt指的是每次update传入的逝去时间。每次<span style="color: black;">规律</span>帧写入的数据除了位置状态等数据,还会<span style="color: black;">包括</span>一个需要<span style="color: black;">表示</span>帧在多<span style="color: black;">长期</span>内模拟完成的数据,这个<span style="color: black;">亦</span>是一个定值0.1。<span style="color: black;">表示</span>帧拿到位置数据,我要移动去哪,再拿到时间数据,多<span style="color: black;">长期</span>内移动到,<span style="color: black;">那样</span>就<span style="color: black;">能够</span>执行平滑<span style="color: black;">表示</span>的<span style="color: black;">规律</span>了。</span><span style="color: black;">至于2G 3G的网络延迟,这个和PC的延迟有什么区别呢?一个是延迟会更大,<span style="color: black;">另一</span>一个<span style="color: black;">便是</span>不稳定。延迟的数据是多少,这个数据<span style="color: black;">道理</span>不是太大,<span style="color: black;">由于</span>这个数据<span style="color: black;">仅有</span><span style="color: black;">有些</span>参考<span style="color: black;">道理</span>,<span style="color: black;">实质</span>的延迟并不是<span style="color: black;">根据</span>这个数据来,而是很不稳定的。可能你蹲个厕所,把厕所门一关,信号一下子就差了<span style="color: black;">非常多</span>,这是很<span style="color: black;">平常</span>的。<span style="color: black;">由于</span>移动设备是可移动的,移动到<span style="color: black;">区别</span>的<span style="color: black;">地区</span>都可能有<span style="color: black;">区别</span>的延迟,<span style="color: black;">此时</span>候可能有两个数据会比较有用,一个是2G 3G比较快的速度是<span style="color: black;">怎么样</span>,另一个是2G 3G比较慢的速度是<span style="color: black;">怎么样</span>。在<span style="color: black;">这般</span>差的网络下,必定会<span style="color: black;">显现</span><span style="color: black;">非常多</span>次的延迟纠正,但只要<span style="color: black;">咱们</span>能收到<span style="color: black;">信息</span>,游戏就<span style="color: black;">能够</span>运行。客户端模拟是可以<span style="color: black;">得到</span>高延迟下好<span style="color: black;">非常多</span>的体验,<span style="color: black;">由于</span>每次点击都有反应,虽然真正生效的时间延迟了,但你的操作还是生效了。2G 3G的<span style="color: black;">另一</span>一个问题<span style="color: black;">便是</span>断线,断线重连其实又是<span style="color: black;">另一</span>一个略有蛋疼的<span style="color: black;">专题</span>了。</span><span style="color: black;">在2G 3G下,在高延迟下给用户带来不差的体验,这个是实时同步比较难做到的,关键看游戏指令的可延迟性,实时<span style="color: black;">需求</span>的高低,玩家操作的频繁度,以及错误纠正时的体验,能否让玩家接受。<span style="color: black;">倘若</span>不行,<span style="color: black;">那样</span>就需要弱化它,例如在进入游戏之前,检测一下ping值,<span style="color: black;">倘若</span>太高,则提醒玩家,你当前的网络延迟较高,让玩家自己决定在不在高延迟的环境下游戏。<span style="color: black;">实质</span>上<span style="color: black;">针对</span>网络延迟,绝大<span style="color: black;">都数</span>的玩家都不陌生,打了一剂预防针之后,对后面的反应不<span style="color: black;">即时</span>的体验<span style="color: black;">包涵</span>性会高一点。在延迟高的<span style="color: black;">状况</span>下,<span style="color: black;">意见</span>玩家去刷单机副本,<span style="color: black;">亦</span>是一个可行的<span style="color: black;">方法</span>。<span style="color: black;">另一</span>,还有一个<span style="color: black;">方法</span>,虽然有点<span style="color: black;">诈骗</span>玩家,但只要玩家觉得游戏流畅就<span style="color: black;">能够</span>了,<span style="color: black;">便是</span>派AI的<span style="color: black;">设备</span>人跟高延迟的玩家打。</span><span style="color: black;"><span style="color: black;">全部</span>同步的想法<span style="color: black;">日前</span>正在<span style="color: black;">实验</span>中,但理论上是可行的,看上去可能有些<span style="color: black;">繁杂</span>,但<span style="color: black;">实质</span>的代码框架搭建起来之后,代码写其实是很简洁的,<span style="color: black;">由于</span>所有的<span style="color: black;">规律</span>都不需要关注延迟。并且可能会变化的部分被隔离开了,<span style="color: black;">每一个</span>东西尽可能地独立。当然,在实现的过程中肯定是会碰到<span style="color: black;">更加多</span>的问题,有问题<span style="color: black;">处理</span><span style="color: black;">便是</span>了,关键是要有思路,有<span style="color: black;">处理</span>问题的方向。</span><span style="color: black;"><span style="color: black;">全部</span>想法的落地大概是<span style="color: black;">这般</span>的,前后端都是用的C++,前端是2dx,后端是kxserver,后端搭建一套模拟2dx的框架,实现一份简化版的Director,Schedule,Node,Component,<span style="color: black;">而后</span>制定编写<span style="color: black;">规律</span><span style="color: black;">关联</span>组件的规则,用自己写的<span style="color: black;">信息</span>机制来传递<span style="color: black;">信息</span>,当有一部分<span style="color: black;">规律</span>需要执行到<span style="color: black;">表示</span><span style="color: black;">关联</span>的内容时,<span style="color: black;">能够</span>用事件来处理,客户端存在这个监听者,而服务端不存在。<span style="color: black;">另一</span><span style="color: black;">亦</span><span style="color: black;">能够</span><span style="color: black;">运用</span>预处理,<span style="color: black;">按照</span><span style="color: black;">是不是</span>定义了Running In Server<span style="color: black;">这般</span>一个宏来预处理<span style="color: black;">有些</span>代码。</span><span style="color: black;">设计中是分了比较多的层和模块,来<span style="color: black;">保证</span>万一哪个不行了,不影响到其他的代码。在落地的过程中会<span style="color: black;">连续</span>地完善代码,打磨,验证想法。<span style="color: black;">期盼</span>这个项目结束后,能沉淀下一套Cocos2d-x网络实时同步的规范和前后端简易框架,来复用到其他有类似<span style="color: black;">需要</span>的项目中。</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz/uicUKliaDticRa1icOnHEcmoUfV99nGkyHLazZwib2tpFPD7RpylvzjlD5AZtxEAFnkO90qVYI8xW5clyzTSlfG3QJw/0?wx_fmt=gif&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1" style="width: 50%; margin-bottom: 20px;"></p>




nykek5i 发表于 2024-10-1 21:26:46

祝福你、祝你幸福、早日实现等。

nqkk58 发表于 2024-10-29 07:36:59

楼主发的这篇帖子,我觉得非常有道理。

b1gc8v 发表于 2024-11-9 06:15:17

软文发布平台 http://www.fok120.com/

4lqedz 发表于 3 天前

我完全赞同你的观点,思考很有深度。
页: [1]
查看完整版本: 对抗网络延迟 手游服务器实时同步办法分享