小飞机工做笔记(三)关于预测与校订的一点思考

    项目虽然采用了帧同步+回滚的方案,可是实际上线后的表现却不如人意。目前表如今几个问题上:chrome

    1)不一样客户端网络延时不同,网速越好的客户端越容易出现回滚。频繁的回滚对性能形成了很大的影响。在chrome或者messenger中勉强还能够,可是在微信中因为执行引擎的落后,JS脚本成了性能的最大瓶颈,卡帧、掉帧很是严重;浏览器

    2)对战中发现其它玩家的表现很“飘”,分析是由于本地演算预测与实际的操做指令差异太大致使的。其它玩家指令到来时本地已经向前演算了一段时间,当前客户端回滚后,渲染层再插值,渲染层中其它玩家的当前位置与逻辑层的当前值差异太大时(包括方向和速度大小)就会致使飞机忽快忽慢,让人以为很“飘”。从目的上来说,即便在至关大的延迟内也依然尽可能让其它玩家的表现尽量平滑,这个方案已经达到了它的目的。可是从效果上来看,则并不能使人满意;服务器

    3)本地在向前演算中可能会出现不应发生却发生的行为,好比玩家B没有发出子弹,但因为未能接收到B的熄火指令,致使本地演算产生了子弹。这种状况下子弹个体就必须予以撤消。而有时则又可能出现该发生却未及时发生的行为,好比玩家B打出了子弹,可是因为未能及时收到玩家B的开火指令,致使子弹未能及时出如今屏幕上。而接收到B的指令时,回滚后会从新演算至本地当前帧,会致使在第N帧产生的子弹,却在当前是在第M帧时须要渲染出来,向前又演算了M-N帧,渲染层中子弹会出如今离发射点很远的地方,令玩家莫名其妙。此时(回滚+ECS)在渲染层对逻辑层属性插值的缺点就暴露出来了。因为不肯定什么时候会进行回滚,也不肯定会回滚多少次,每一个状态帧都是不可依赖的,难以依据它捕捉一个完整的行为的开始和结束。固然,真的要作也是能够作的,可是这个行为随时可能变更,必须对每一个阶段的行为作充分的撤消/重建/插值,复杂度很是之高。相比之下,若去除回滚,不采用实时对逻辑层插值的作法,而是按照传统的方式来捕捉事件,由渲染层根据此事件本身肯定子弹的出生点,而且从出生点出生,同时经过时间戳对子弹的速度插值,即可获得一个完整的加速追赶行为,而不会出现离开发生点很远的情形。不过这种方式也有它的问题。因为去除了回滚,逻辑层没法再超前于网络驱动帧演算,只能在渲染层作一些预测插值。微信

    此外,去除回滚后,因为逻辑帧依赖于网络驱动帧,网络抖动的状况下,本地的AI也会随之抖动,没法再平滑地向前演算渲染。至于玩家,由于其没有AI,只是依赖于玩家的操做,所以是否回滚对其影响不大,可是对机器人AI的影响在网络抖动较大时会有比较大的差异。在手游中还能够在UDP上定制可靠传输协议来提高传输效果,可是浏览器长连接走的是TCP上的WebSocket协议,是没辙的了。网络

    从以上分析来看,若想既兼顾性能,又能获得较好的AI预测体验,那么最好是能容许部分范围内的前向计算+回滚。除非是划分的模块状态相互之间彻底独立,不然要对单个状态模块加以回滚又保持不一样客户端的一致性,那只能在限制反作用的有限范围内去处理。性能

    另一种方法就是摒弃帧同步,采用状态同步,天然包括AI的状态也要同步下来。可是在前向演算时,依然能够在客户端编写AI(这时能够利用ECS模式复用服务器的AI代码),而且能够只依赖于部分状态进行演算。AI的表现并不要求是彻底准确的,在状态依赖与演算的策略上也有空间能够发挥。客户端能够选择在服务器同步部分必要的状态后便可回滚/演算,而不一样客户端并不要求在每一网络帧计算上都保持一致,只要在关键事件上由服务器同步一致便可。好比在一张大地图上,只对玩家当前所在的区域进行演算便可,服务器AOI同步过来时再作回滚校订。不过具体细节我也没有再思考了,有机会再进一步实践吧。而若是是手游项目并且附带至关AI(技能事实上也是AI之一种,一旦释放就要走完一个固定的流程),对实时要求也很是高的话,我仍是会优先选择帧同步+回滚的方案的。spa

相关文章
相关标签/搜索