Unity 基于帧同步的网络优化方案

本文介绍了Unity中基于帧同步的网络优化方案,强调帧同步原理与实施要点,如UpdateNet函数、数据包最小化、UDP冗余策略、逻辑层与表现层分离等。并探讨了如何处理网络抖动、数据堆积以及优化游戏流畅性的问题。

帧同步含义

游戏客户端接受来自网络的多个客户端的操作,如果这些操作在各个客户端是一样的,那么多个客户端的显示也就一样了,这就带来了“同步”的效果。所以在这种情况下,各个客户端的运算要绝对一致,不能依赖诸如本地时间、本地随机数等等“输入”,而要一切以网络来的操作数据为主。


一般来说,大多数的游戏客户端引擎,都会定时调用一个接口函数,这个函数由用户填写内容,用来修改和控制游戏中各种需要显示的内容。比如在在Unity里面叫Update(),这类函数通常会在每帧画面渲染前调用,当用户修改了游戏中的各个角色的位置、大小后,就在下一帧画面中显示出来。而在帧同步的游戏中,这个Update()函数依然是存在,只不过里面大部分的内容,需要挪到另外一个类似的函数中,我们可以称之为UpdateNet()函数——由网络层不断的接收服务器发来的“网络帧”数据包,每收到一个这样的数据包,就调用一次这个UpdateNet()函数,这样游戏就从通过本地CPU的Update()函数的驱动,改为根据网络来的UpdateNet()函数驱动了。显然,网络发过来的同步帧速度会明显比本地CPU要慢的多,这里就对我们的游戏逻辑开发提出了更高的要求——如何同步的同时,还能保证流畅?

实现UpdateNet函数内容,其实就是定义一个堆栈用于存放网络发过来的消息,通过帧监测将其数据拿出来使用,因为Update函数明显比UpdateNet快的多,这就需要我们定义一个时间间隔用于消息的发送,比如50毫秒或者100毫米等。

private void GameFrameTurn() {
    //first frame is used to process actions 
    if(GameFrame == 0) {
        if(LockStepTurn()) {
            GameFrame++;
        }
    } else {
        //update game 
        SceneManager.Manager.TwoDPhysics.Update (GameFramesPerSecond);
         
        List<IHasGameFrame> finished = new List<IHasGameFrame>();
        foreach(IHasGameFrame obj in SceneManager.Manager.GameFrameObjects) {
            obj.GameFrameTurn(GameFramesPerSecond);
            if(obj.Finished) {
                finished.Add (obj);
            }
        }
         
        foreach(IHasGameFrame obj in finished) {
            SceneManager.Manager.GameFrameObjects.Remove (obj);
        }
         
        GameFrame++;
        if(GameFrame == GameFramesPerLocksetpTurn) {
            GameFrame = 0;
        }
    }
}
private void GameFrameTurn() {
    //first frame is used to process actions 
    if(GameFrame == 0) {
        if(LockStepTurn()) {
            GameFrame++;
        }
    } else {
        //update game 
        SceneManager.Manager.TwoDPhysics.Update (GameFramesPerSecond);
         
        List<IHasGameFrame> finished = new List<IHasGameFrame>();
        foreach(IHasGameFrame obj in SceneManager.Manager.GameFrameObjects) {
            obj.GameFrameTurn(GameFramesPerSecond);
            if(obj.Finished) {
                finished.Add (obj);
            }
        }
         
        foreach(IHasGameFrame obj in finished) {
            SceneManager.Manager.GameFrameObjects.Remove (obj);
        }
         
        GameFrame++;
        if(GameFrame == GameFramesPerLocksetpTurn) {
            GameFrame = 0;
        }
    }
}

帧同步游戏中,由于需要“每一帧”都要广播数据,所以广播的频率非常高,这就要求每次广播的数据要足够的小。最好每一个网络帧,能在一个最大传输单元(Maximum Transmission Unit,MTU)以下,这样才能有效降低底层网络的延迟。同样的理由,我们为了提高实时性,一般也倾向于使用UDP而不是TCP协议,这样底层的处理会更高效。但是,这样也会带来了丢包、乱序的可能性。因此我们常常会以冗余的方式——比如每个帧数据包,实际上是包含了过去2帧的数据,也就是每次发3帧的数据,来对抗丢包。也就是说三个包里面只要有一个包没丢,就不影响游戏。
帧同步实现的过程有个很重要的地方就是逻辑层和表现层一定要分开,表现层先行,逻辑层等发到服务端的指令再处理。帧与帧之间的播放频率,则由服务器统一控制,但由于网络抖动等影响,帧的频率并不是太稳定,为避免播放抖动,帧数控制器需要进行一定的平滑处理。

网络抖动的产生原因:在网络游戏中,各个客户端的运行条件和环境往往千差万别,有的硬件好一些,有的差一些,各方的网络情况也不一致;时不时玩家的网络还会在游戏过程中,发生临时的拥堵,我们称之为“网络抖动”。可能导致客户端收到“过去时间”里的一堆网络帧,客户端需要拿出一定的时间去处理这些堆积的网络帧,因此,客户端必须要有处理这些堆积起来的网络数据的能力。

实时同步游戏最重要的是流畅,然而影响游戏流畅的因素很多,网络带宽的限制,CPU运算和渲染效率的限制。一般玩家控制的角色的动作,包括当前客户端控制的角色,还是应该从网络帧里面获得行为数据,因为如果玩家爱控制角色不一致的太多,整个游戏场面就会差更多。很多游戏中的怪物AI都是根据玩家角色来设定的,所以一旦玩家角色的行为是同步的,那么大多数的怪物的表现还是一致的。

帧同步游戏技术,并不存在一种可以让游戏流畅的通用做法,而是需要和游戏具体做很多结合,在减少数据包,优化游戏快进体验,控制发包速度上尽量调优。同时还需要和游戏产品策划一起,平衡一致性、实时性、公平性的策略,才能真正达到流畅游戏的目的。


优化方案:

1:减少数据包;

帧同步游戏中,由于需要“每一帧”都要广播数据,所以广播的频率非常高,这就要求每次广播的数据要足够的小。最好每一个网络帧,能在一个最大传输单元(Maximum Transmission Unit,MTU)以下,这样才能有效降低底层网络的延迟。

2:使用UDP冗余的方式

比如每个帧数据包,实际上是包含了过去2帧的数据,也就是每次发3帧的数据,来对抗丢包。也就是说三个包里面只要有一个包没丢,就不影响游戏。这样,即便丢包,也能保证大概率客户端稳定。

3:逻辑层和表现层分离

表现层先行,逻辑层等发到服务端的指令再处理。帧与帧之间的播放频率,则由服务器统一控制,但由于网络抖动等影响,帧的频率并不是太稳定,为避免播放抖动,帧数控制器需要进行一定的平滑处理。

4:优化游戏快进体验,控制发包速度上尽量调优


参考:

Unity 3D实现帧同步技术

unity c#帧同步网络优化方案


 

 

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独立游戏开发指南

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值