我是靠谱客的博主 飞快蜜粉,最近开发中收集的这篇文章主要介绍ue4如何恢复初始状态_UE4的Networking模块的一点思考(1),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

networking模块对于开发multiplayer功能非常关键,目前ue4的网络同步是基于状态的,当然也可以改成lockstep,只是基于状态的同步更加的通用,大部分的游戏一般都采用这种模式。

对于开发那些需要高频同步和要求低延迟的项目,udp的传输模式显然更加的适应。当然它的弹性也很大,即便是那些不需要那么高频同步的应用,udp也能胜任。只不过udp在开发难度上会比tcp来得高一些,因为它大部分的功能是可以定制的,不像tcp那样很多协议都被固化在管线里了。尤其是对于传输数据的可靠性保证上,tcp有着天然的优势。但是话分两头,tcp在提供稳定性的同时也付出了相应的代价,最令人诟病的就是它的flow and congestion control,例如当侦测到丢包严重时它会自动采取降低流量的方式进行控制,这对于那些需要低延迟保证的游戏简直就是灾难性的。所以fps或者是赛车类型的游戏都会选择udp来进行同步数据。看起来似乎如果克服了udp的实现复杂性这一缺点就一切完美了,其实udp在传输上也存在着劣势,例如以下的情形:

"当队列已满时,路由器不必丢弃每个传入的包。相反,它可以删除以前排队的数据包。这些情形发生在当路由器确定新传入的数据包具有更高的优先级,或者比排队的数据包更重要时。路由器一般是基于网络层头段中的QoS数据进行优先级决策,有时也会基于通过检查数据包里的有效负载而收集到的信息做出对应的判断。一些路由器甚至被配置为做出贪婪的决定以减少他们必须处理的总流量:有时在TCP数据包之前丢弃UDP数据包,因为它们知道丢弃的TCP数据包自动重新发送。"

------<<Multiplayer Game Programming>>

总而言之,udp和tcp协议各有自己的优缺点,需要针对不同的项目进行选择,天下没有免费的午餐。

回头再来说说ue4里面的实现,为了同步游戏的状态,属性自动复制以及rpc调用成为两大利器。那么我们先了解一下属性复制是如何工作的,首先属性复制要保证其传输的可靠性,也就是说服务器端所有的属性变化信息都需要同步给所有关注它的客户端,而这个同步的数据都必须准确达到客户端,不能丢包和乱序。这里说的所有关注它的客户端的意思是,游戏客户端对于某些服务器端的Actor或Component上的属性变化并不是所有时间点上都是需要获取的。例如Actor可以根据一些规则让它的属性复制功能对某些客户端暂停,ue4里面把这种现象称之为Dormancy,与之对应的ActorChannel也会关闭,并从NetConnection里移除。当后面从冬眠状态恢复回正常状态时又会重新创建Channel,从而保证网络带宽的有效利用。

一般的服务器端引擎都会有属性自动复制的功能,而且mmorpg大都采用tcp的协议,但是这种方式的代价会比较大,尤其是同步频率很高的情况下更是如此。早期的ue4版本虽然使用的是udp协议,但是为了保证数据包能够按序完整的到达客户端,采用了预测丢包后及时重传的策略,而且它会把多个数据包里的属性变化信息按先后循序逐一的应用到客户端中。这里就带来了一个问题,当packet在传输过程中丢失后,服务器端会立即将这个packet重新传输,也就是这个bunch会在服务器端一直保留着,等收到确认(ack)消息才从outgoing链表中删除。如果前一个sequence number的packet尚未到达时,客户端不敢妄自应用当前bunch里的属性变化信息。而且客户端每次收到这些reliable的packet时都要回复一个ack消息,这个代价也是比较大的,虽然说一个tick中,多个bunch会填满packet后才会发送出去,但是零碎小包的额外开销还是需要避免的。另外多个ack信息其实是可以进行有效的合并,从而减少不必要的带宽浪费。总体说来属性的传输虽然需要稳定可靠的保证,但其实它对丢包和乱序是有一定耐受性的,因为同个属性的变化只要求最后一次的结果就行,中间的变化过程并不重要,所以即使被丢掉也不可惜。根据这些特点,后期ue4对其属性复制的逻辑进行了大刀阔斧的改造,就如我所说的那样,epic将关于属性变化信息的传输改成了unreliable的方式,但为了确保所有的变化信息都能抵达客户端,客户端还是需要回复ack消息的,只不过这次不是单独的发送,而是将这些信息pack到当前packet的头部和其他数据一起发送。虽然信息有些冗余,但是由于占用的字节数较低,因此也能忍受,具体实现可以参考(FNetPacketNotify)。每个packet都有ack的history,所以即使网络出现波动,丢包率升高,ack的信息完整性还是要优于之前的方案。根据这些ack的history信息,服务器端就能判断哪些属性变化已经被客户端成功接收,如果某些属性变化数据没有抵达客户端,它就会将这些的属性变化内容与当前的属性变化内容进行merge,最后形成一个新的bunch再发送给客户端,如果中间变化的属性有重叠,那么重传的数据量其实是比之前要低的。

从以上这个案例可以看出udp的灵活性对状态同步的策略设计大有裨益。下一次我要谈谈如何对属性的复制功能做进一步的改进和提升,从而可以满足更大规模状态同步的需求。

最后

以上就是飞快蜜粉为你收集整理的ue4如何恢复初始状态_UE4的Networking模块的一点思考(1)的全部内容,希望文章能够帮你解决ue4如何恢复初始状态_UE4的Networking模块的一点思考(1)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(89)

评论列表共有 0 条评论

立即
投稿
返回
顶部