精华内容
下载资源
问答
  • 帧同步技术,帧同步技术的优点,matlab源码
  • 同步技术中的帧同步,用于在通信系统中进行同步。
  • 同步技术中的帧同步,用于在通信系统中进行同步。
  • 基于FPGA的STM-64帧同步技术.pdf
  • 二维扩频系统帧同步技术研究与FPGA实现.pdf
  • 电信设备-数据通信中的可靠帧同步技术.zip
  • 行业资料-电子功用-扩频无线电通信的帧同步技术和系统
  • unity帧同步技术demo

    2018-10-19 20:47:45
    网络游戏的经典同步方式帧同步的实现demo。里面有两个untiy工程(c#),对应服务端和客户端代码。很不错的教程。可以了解实现原理。
  • 《王者荣耀》帧同步技术理解

    千次阅读 2017-12-27 21:23:08
    帧同步的核心思想是客户端只发送玩家的操作,或者将玩家操作解释为可执行的指令,发给服务器执行并广播给其它客户端执行。相同的输入+相同的逻辑 = 相同的结果。...因为帧同步技术只同步输入,结果由各个客户端

    帧同步的核心思想是客户端只发送玩家的操作,或者将玩家操作解释为可执行的指令,发给服务器执行并广播给其它客户端执行。相同的输入+相同的逻辑 = 相同的结果。

    快进功能其实就是在一帧里处理多帧的数据,所以一般都有一个队列辅助维护每帧要处理的数据。关于掉线网络延迟的处理,一般会短时间内维持上一帧的移动指令,但没有其他的按键指令。

    有些坑的地方,主要是不同步。因为帧同步技术只同步输入,结果由各个客户端自己执行,中间相当于是黑盒操作。由于各个客户端千差万别,中间难免不一致,时间戳、随机数、浮点数精度计算误差等都是不完全一样的。前俩个可以统一使用服务器的时间戳和随机种子,精度问题就看情况自己处理吧,采用定点数替换,或者服务器对影响的系统强制矫正等。

    帧同步技术感觉很适合移动端游戏,手游、ps等等,电脑输入一般情况复杂,所有操作都做指令解析情况太多,实现上应该困难许多。

    展开全文
  • 改进后的算法仍使用两个训练符号,以训练符号本身的强自相关性来消除定时同步中的峰值平台问题,并将训练符号的循环前缀(CP)置为0,以尽量消除CP对定时同步的影响。新的训练符号可直接在时域估计出载波频偏。改进...
  • Unity 3D实现帧同步技术

    万次阅读 多人点赞 2017-05-11 15:38:00
    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。...

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

    CSDN视频网址:http://edu.csdn.net/lecturer/144

    现在竞技类网络游戏比较火,市面上也出现了很多这种类型的游戏竞赛,提到网络游戏就回避不了一个问题:同步技术,多个人在一个游戏场景围攻一个怪物或者说多人组队战斗等等。现在在移动端的游戏由于带宽的限制,一般采用实时同步的方式是状态同步,也就是说角色的状态发生改变,才会去发送消息。举个例子:

    3D角色一般的动作状态有:Idle,walk,run,attack等,玩家操作键盘或者触摸屏按钮,会触发这些动作,一个游戏场景中会有多个角色,每个角色都有自己的动作状态,为了让玩家能够看到其他玩家在做什么,需要同步,玩家默认状态是idle,玩家刚出现时是idle状态,这个时候,客户端会把玩家的状态,位置,方向传送给服务器,其他玩家也是一样的,服务器接收到信息后,会把这些信息发送给除了它本人之外的其它玩家,这样我们就可以看到其他玩家的状态了。如果玩家从idle状态转化到walk状态,这表明玩家的动作状态发生了变化,这也需要将信息发给服务器,服务器进行群发给其他玩家,这样其他玩家就可以看到角色开始walk了。接下来如果玩家继续走,客户端就不发送消息给服务器了,因为状态没发生变化,等状态再变化时才会发送消息给服务器,然后服务器再群发消息,在此过程中,其他客户端会通过插值的方式把两个状态之间的距离实现出来,以此类推。。。。。。这就是所说的状态同步模式。

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

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

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

     

    private float AccumilatedTime = 0f;
     
    private float FrameLength = 0.05f; //50 miliseconds 
    //called once per unity frame 
    public void Update() {
        //Basically same logic as FixedUpdate, but we can scale it by adjusting FrameLength 
        AccumilatedTime = AccumilatedTime + Time.deltaTime;
     
        //in case the FPS is too slow, we may need to update the game multiple times a frame 
        while(AccumilatedTime > FrameLength) {
            GameFrameTurn ();
            AccumilatedTime = AccumilatedTime - FrameLength;
        }
    }

     

     

     

     

    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;
            }
        }
    }

     

     

     

     

    帧同步游戏中,由于需要“每一帧”都要广播数据,所以广播的频率非常高,这就要求每次广播的数据要足够的小。最好每一个网络帧,能在一个MTU以下,这样才能有效降低底层网络的延迟。同样的理由,我们为了提高实时性,一般也倾向于使用UDP而不是TCP协议,这样底层的处理会更高效。但是,这样也会带来了丢包、乱序的可能性。因此我们常常会以冗余的方式——比如每个帧数据包,实际上是包含了过去2帧的数据,也就是每次发3帧的数据,来对抗丢包。也就是说三个包里面只要有一个包没丢,就不影响游戏。

    帧同步实现的过程有个很重要的地方就是逻辑层和表现层一定要分开,表现层先行,逻辑层等发到服务端的指令再处理。帧与帧之间的播放频率,则由服务器统一控制,但由于网络抖动等影响,帧的频率并不是太稳定,为避免播放抖动,帧数控制器需要进行一定的平滑处理。

     

     

     

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

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

     

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

     

    Demo下载地址:链接:https://pan.baidu.com/s/1jAV-4h8QAncxnMDVtNeO4g 
    提取码:n7ia 
     

    重新更换链接

     

     

     

     

    展开全文
  • 帧同步是一种前后端数据同步的方式,一般应用于对实时性要求很高的网络游戏。 其基本实现流程及思路可以概括为: 1.所有客户端每帧上传操作指令集到服务器; 2.服务端将这些操作指令集保存到对应帧序列字典,并记录帧...

    前言:

    1.0 帧同步原理与简介

    A.什么是帧同步?
    帧同步是一种前后端数据同步的方式,一般应用于对实时性要求很高的网络游戏。

    其基本实现流程及思路可以概括为:

    1.所有客户端每帧上传操作指令集到服务器;
    2.服务端将这些操作指令集保存到对应帧序列字典,并记录帧号,并在下一帧将其广播给所有客户端;
    3.客户端收到指令集后,分别按帧序,帧号进行执行指令集中的操作命令。
    4.也就是:相同的时机(帧序列) + 相同的操作命令(指令集-确定性) = 相同的结果(帧同步)

    帧同步实现流程图
    B.帧同步解决方案的适用范围?
    通常针对于RTS[即时战略],ACT(多人实时格斗),MOBA类的游戏类型提供帧同步解决方案建议。
    上述类型的网络对战游戏的特点是:实时性要求极高,追求公平竞技,打击感。
    综上所述类型的游戏开发时应该优先考虑帧同步解决方案,以追求一致性。

    C.帧同步解决方案内容
    帧同步游戏开发中,其核心原理实现的解决方案主要有三种:

    • 目前帧同步主要处理方式为以下三种:
    • 1.0 帧锁步[Lockstep]
    • a.什么是帧锁步?
    • 当客户端A存在网络延迟导致服务器第X帧收集不到A的第X帧输入指令包时,
    • 服务器就需要等待所有客户端的X帧指令收集完成,才会下发X帧的所有客户端包数据以此保持同步,
    • 也就意味着一人延迟,所有客户端都得等,显然这种同步概念不太适用于竞技性比较高的游戏,玩家体验会很差。
    • 2.0 乐观帧
    • a.什么是乐观帧?
    • 其他乐观帧是在帧锁步的基础上进行改良,为了提高游戏体验,服务器不再要求必须收集所有客户端X帧的操作指令才进行分发,
    • 而是每个客户端都进行本地输入指令快照存储,存储各自的输入指令(并带有帧号)。
    • 如果A客户端因为延迟从第2帧(逻辑帧)开始丢包直到第5帧传输正常,那么服务器即使收不到A客户端2-5帧的输入指令还是继续分发,
    • 直到第5帧再将A客户端2-5帧的本地快照一并分发出去,同时将其他客户端2-5帧的输入指令同步到本地客户端,当然丢失3帧的数据直接在一帧同步
    • 到客户端会导致卡顿瞬移,所以A客户端需要进行加速操作执行指令操作,通常会做差值计算,通过补间动画的方式让同步更平滑。
    1. 预测回滚
      每个客户端按照帧同步的方案推进着游戏,但是如果遇到服务器没能及时返回其他玩家操作的时候,给对应的玩家预测一个操作(复制该玩家最后一次操作),并继续推进游戏,如果在其后收到了服务器玩家关于这个人的操作,则把游戏回滚到预测开始的那一帧重新计算一遍。
      《守望先锋》便采取了这种模式,获得了很大效率的网络优化。预测回滚核心在于预测写入快照,适当时机进行回滚,然而每一帧都写入快照显然内存会吃紧,同时回滚机制会变得异常复杂。
    • a.什么是预测回滚?
    • 预测回滚是一种同步机制,是乐观帧的一种解决方案,上面提到的乐观帧有个最大的缺点是一旦A客户端丢包,那么其他客户端的A在丢包期间将不会有任何
    • 操作指令同步,这样会影响游戏体验,所以这里引用预测机制,如果客户端在X帧没有指令数据那么服务器会给它在X帧一个预测的输入指令,当A客户端连接后,
    • 服务器会对预测数据和真实丢失快照数据进行和解,回滚。
    • b.如何和解
    • 下章详细介绍
    • c.为什么推荐使用ECS架构做预测回滚?
    • ECS框架可以很轻松的做到逻辑与渲染分离,所有的数据快照都存储在Component中,这将让回滚变得容易,
    • 我们只需要将每帧的Component快照进行存储,我们就可以很容易的回滚到任何逻辑帧的状态。

    D.网络解决方案

    E.帧同步与状态同步

    1. 两者有何区别?

    2. 状态同步方案能否替代帧同步方案?

      这里我们引入ECS架构模式:
      

    2.0 ECS框架

    A.ECS架构概念:
    在这里插入图片描述
    B. 基本原理:
    ECS系统的特征是将状态(由Component提供)与行为(由System系统)进行分离.在Unity传统编程中,我们利用MonoBehavior来编写游戏 核心思想:将数据和行为分开。即逻辑与渲染分离 !·

    1.在Unity中,我们将MonoBehavior组件放到GameObject中。但Entity系统中不同,Component被设计为附加到Entity上。·
    2.使用一个pool来包含所有Entity。通过pool我们可以看到所有的entity。·
    3.我们可以对entity进行分组,分组叫做group。之后我们可以通过指定的规则来区分不同的group,·
    4.这个规则叫做matcher,通过matcher可以方便地快速获得指定类型的entity。

    C. ECS相关链接:
    游戏开发ECS设计模式初探
    守望先锋 网络架构设计分享
    Unity ECS简介
    UnityECS高性能探索

    **

    3.0 定点数

    1.什么是定点数?为什么要使用定点数?

    定点数是指在计算机中小数点的位置固定的数。相反小数位数不固定的则是浮点数,例如float,double数据类型,它们属于高精度单双浮点数类型,由于不同机器CPU对浮点数的处理结果会存在偏差,再加之网路延迟影响,由此而带来的蝴蝶效应影响,终会导致不相同的计算结果,导致逻辑不可控,因此为了数据的完全的一致,应采用定点数替代浮点数。

    • 由此我们发现帧同步网络服务器只负责收发指令数据,不进行战斗逻辑的计算。那么由于客户端性能算力不一样,导致浮点数数据类型(float(单),double(双))不再适用,
    • 因为浮点数带有精度,会导致每个客户端的计算结果会存在偏差,从而导致不同步,进而产生蝴蝶效益导致正常战斗完全不同步。所以这里引入定点数。
    • 定点数专为解决浮点数精度差,主要实现方式有两种:
    • a.尾数截断
    • 可以到这里去看看这里帧同步项目的实例,注明:这是早期Photon的TrueSync经过大佬完善后的实例,有参考价值,其中用到就是[尾数截断]实现定点数
    • b.移位运算
    • ps:
    • 左移操作时将运算数的二进制码整体左移指定位数,左移之后的空位用0补充
    • 右移操作是将运算数的二进制码整体右移指定位数,右移之后的空位用符号位补充,如果是正数用0补充,负数用1补充
    • 通过移位操作我们可以消除精度,至于移位数我觉得(16位)已经完全可以满足需求。
    • 注:65536是右移位16的结果
    • 将浮点数右移16位得到一个long类型,long类型赋值给Fixed类型编码,便得到一个定点数。
    • var l= (long)unchecked(value * 65536f)
    • public static Fixed FromRaw(long value)
      {
      Fixed r;
      r.RawValue = value;
      return r;
      }
    • 同样将反向转换只需左移位操作即可:
    • public static explicit operator float(Fixed value)
      {
      return (float)value.RawValue / 65536f;
      }

    这里为大家提供一个定点数库(采用第一种方式,通过移位运算精确):
    帧同步开发-【标准定点数库】[FP] [FPMath] [FPMatrix2x2] [FPQuaternion] [FPVector2][FPVector3]

    下一篇博客,Unity游戏帧同步技术分享篇【02】帧同步物理引擎解决方案

    感谢你的关注!

    展开全文
  • 帧同步

    千次阅读 2019-05-07 11:49:29
    帧同步技术是早期RTS游戏常用的一种同步技术,本篇文章要给大家介绍的是RTX游戏中帧同步实现,帧同步是一种前后端数据同步的方式,一般应用于对实时性要求很高的网络游戏,想要了解更多帧同步的知识,继续往下看。

    帧同步技术是早期RTS游戏常用的一种同步技术,本篇文章要给大家介绍的是RTX游戏中帧同步实现,帧同步是一种前后端数据同步的方式,一般应用于对实时性要求很高的网络游戏,想要了解更多帧同步的知识,继续往下看。

    一.背景

    帧同步技术是早期RTS游戏常用的一种同步技术。与状态同步不同的是,帧同步只同步操作,其大部分游戏逻辑都在客户端上实现,服务器主要负责广播和验证操作,有着逻辑直观易实现、数据量少、可重播等优点。

    部分PC游戏如帝国时代、魔兽争霸3、星际争霸等,Host(服务器或某客户端)只当接收到所有客户端在某帧输入数据后,才会继续执行,等待直至超时认为该客户端掉线。很明显,当部分客户端因网络或设备问题无法及时上传操作数据,会影响其它客户端的表现,造成不好的游戏体验。考虑到游戏公平竞争性,这种需要等待的机制是必需的,但并不符合手游网络环境的需求。为此,需要使用“乐观”模式,即是Host采集客户端上传操作并按固定频率广播已接收到的操作数据,不在乎部分客户端的操作数据是否上传成功,且不会影响到其它客户端的游戏表现,如图1所示。

    二.剖析Unity3D

    帧同步技术最基础的核心概念就是相同输入,经过相同计算过程,得出相同计算结果。按照该概念,下面将简单描述Unity3D实现帧同步时所需要改造的一些方面,Unity3D中脚本生命周期流程图如图2所示。

    帧同步需要避免使用本地计时器相关数值。因此,使用Unity3D实现帧同步的过程所需注意的几点:

    1. 禁用Time类相关属性及函数,如Time.deltaTime等。而使用帧时间(第N帧 X 固定频率)

    2. 禁用Invoke()等函数

    3. 避免在Awake()、Start()、Update()、LateUpdate()、OnDestroy()等函数中实现影响游戏逻辑判断的代码

    4. 避免使用Unity3D自带物理引擎

    5. 避免使用协程Coroutine

    三.具体实现

    对于本文的实现,有如下定义:

    关键帧:服务器按固定频率广播的操作数据帧,使用唯一ID标识,主要包括客户端输入数据或服务器发送的关键信息(例如游戏开始或结束等消息)

    填充帧:由于设备性能和网络延迟等原因,服务器广播频率不可能达到客户端的更新频率。若只使用关键帧来驱动游戏运作,就会造成游戏卡顿,影响体验。因此,除关键帧外,客户端需要自行添加若干空数据帧,以使游戏表现更为流畅

    逻辑帧更新时间:客户端执行一帧所需时间,可根据设备性能和网络环境等因素动态变化

    服务器帧更新时间:服务器广播帧数据的固定频率,一般用于帧间隔时间差的逻辑计算

    3.1 主循环

    帧同步要求相同的计算过程,这就涉及到两个方面,其一是顺序一致,Unity3D主循环不可控,需自定义游戏循环,统一管理游戏对象以及脚本的执行,确保所有对象更新与逻辑执行顺序完全一致。另一方面是结果一致,凡有浮点数参与的逻辑计算需要特殊处理。
    class MainLoopManager : MonoBehaviour
    {
    bool m_start;
    int m_logicFrameDelta;//逻辑帧更新时间
    int m_logicFrameAdd;//累积时间

    void Loop()
    {
        ......//遍历所有脚本
    }
    
    void Update()
    {
        if (!m_start)
            return;
    
        if (m_logicFrameAdd < m_logicFrameDelta)
        {
            m_logicFrameAdd += (int)(Time.deltaTime * 1000);
        }
        else
        {
            int frameNum = 0;
            while(CanUpdateNextFrame() || IsFillFrame())
            {
                Loop();//主循环
                frameNum++;
                if (frameNum > 10)
                {
                    //最多连续播放10帧
                    break;
                }
            }
            m_logicFrameAdd = 0;
        }
    }
    
    bool CanUpdateNextFrame();//是否可以更新至下一关键帧
    bool IsFillFrame();//当前逻辑帧是否为填充帧
    

    }
    复制代码

    3.2 自定义MonoBehaviour

    Unity3D脚本生命周期中部分函数、Invoke、Coroutine调用时机与本地更新相关,并不满足帧同步机制的要求。我们通过继承MonoBehaviour类来实现上述函数和功能需求,并使所有涉及逻辑计算的组件都继承该自定义类。

    class CustomBehaviour : MonoBehaviour
    {
    bool m_isDestroy = false;

    public bool IsDestroy
    {
        get { returnm_isDestroy; }
    }
    
    public virtual void OnDestroy() {};
     
    public void Destroy(UnityEngine.Objectobj)
    {
    
        ......//销毁游戏对象
    
    }
    

    }

    3.2.1 Update()与LateUpdate()

    从可控性和高效性两方面来看,不建议采用逐一遍历游戏对象获取CustomBehaviour的方式去调用Update()与LateUpdate(),而是单独使用列表来管理。

    delegate void FrameUpdateFunc();
    class FrameUpdate
    {
    public FrameUpdateFunc func;
    public GameObject ower;
    public CustomBehaviour behaviour;
    }

    class MainLoopManager : MonoBehaviour
    {

    List m_frameUpdateList;
    List m_frameLateUpdateList;

    public RegisterFrameUpdate(FrameUpdateFunc func, GameObject owner)
    public UnRegisterFrameUpdate(FrameUpdateFunc func, GameObject owner)
    public RegisterFrameLateUpdate(FrameUpdateFunc func, GameObject owner)
    public UnRegisterFrameLateUpdate(FrameUpdateFunc func, GameObject owner)
    

    void Loop()
    {
    //先遍历m_frameUpdateList
    //再遍历m_frameLateUpdateList
    }

    }

    采取添加删除的方式,对组件是否需要执行Update()与LateUpdate()进行动态地管理,除了具有相对的灵活性,也保证了执行效率。

    3.2.2 Invoke相关函数

    Invoke、 InvokeRepeating、 CancelInvoke等函数需要使用C#中的反射机制,根据object对象obj和函数名methodName来获取MethodInfo如:

    var type = obj.GetType();
    MethodInfo method = type.GetMethod(methodName);

    通过接口封装,组成相关数据(InvokeData),放入列表等待执行。

    class InvokeData
    {
    public object obj;
    public MethodInfo methodInfo;
    public int delayTime;
    public int repeatRate;
    public int repeatFrameAt;
    public bool isCancel = false;
    }

    如上述结构,delayTime用于记录延迟执行时间,repeatRate代表重复调用的频率,repeatFrameAt则标记上次调用发生的帧序号,而isCancel标记Invoke是否被取消。最后,统一使用MethodBase.Invoke(objectobj, object[] parameters)执行调用。

    class MainLoopManager : MonoBehaviour
    {

    List m_invokeList;

    void Loop()
    {
        //先遍历m_frameUpdateList
        //再遍历m_frameLateUpdateList
        //遍历m_invokeList,并根据相关属性分别进行Invoke、 InvokeRepeating、CancelInvoke
    }
    ......
    

    }

    3.2.3 协程Coroutine

    协程Coroutine较复杂,必需采用的情况较少,本文方案未实现协程Coroutine功能,而是避免使用。

    3.2.4 Destroy相关

    在Destroy游戏对象或组件后,OnDestroy()将在下一帧执行。因此,需要采取可控的方式代替OnDestroy()函数完成资源的释放。

       class CustomBehaviour : MonoBehaviour
        {
            bool m_isDestroy = false;
            public bool IsDestroy
            {
                set { m_isDestroy = value; }
                get { return m_isDestroy; }
            }
            public virtual void DoDestroy() {};
            public void Destroy(UnityEngine.Object obj)
            {
                if (obj.GetType() == typeof(GameObject))
                {
                    GameObject go = (GameObject)obj;
                    CustomBehaviour behaviours = go.GetComponents();
                    for (int i = 0; i < behaviours.Length; i++)
                    {
                        behaviours[i].IsDestroy = true;
                        behaviours[i].DoDestroy();
                    }
                }
                else if (obj.GetType() == typeof(CustomBehaviour))
                {
                    CustomBehaviour behaviour = (CustomBehaviour)obj;
                    behaviour.IsDestroy = true;
                    behaviour.DoDestroy();
                }
                UnityEngine.Object.Destroy(obj);
            }
        }
    

    3.3 Time类与随机数

    帧同步游戏逻辑所有涉及时间的计算都应采用帧时间,即:当前帧序列数 * 服务器帧更新时间 /(填充帧数 + 1),而每帧随机数计算都由服务器下发种子来控制。如下:

    class MainLoopManager : MonoBehaviour
    {

    int m_serverFrameDelta;//毫秒
    int m_curFrameIndex;
    int m_fillFrameNum;
    int m_serverRandomSeed;

    public int serverRandomSeed
    {
        get { return m_serverRandomSeed; }
    }
    public int curFrameIndex
    {
        get { return m_curFrameIndex; }
    }
    public static int curFrameTime
    {
        return m_curFrameIndex * m_serverFrameDelta / (1 + m_fillFrameNum);
    }
    public static int deltaFrameTime
    {
        return m_serverFrameDelta / (1 + m_fillFrameNum);
    }
    .......
    

    }

    可写入CustomBehaviour中,便于自定义Time类的调用,避免误用Unity3D的Time类,Random类同理。

    class CustomBehaviour : MonoBehaviour
    {
    protected class Time
    {
    public static Fix time
    {
    get { return (Fix)MainLoopManager.curFrameTime / 1000; }
    }

        public static Fix deltaTime
        {
            get { return (Fix)MainLoopManager.deltaFrameTime / 1000; }
        }
    }
    
    protected class Random
    {
        public static Fix Range(Fix min, Fix max)
        {
            Fix diff = max - min;
            Fix seed = MainLoopManager.serverRandomSeed;
            return min + (int)FixMath.Round(diff * (seed / 100));
        }
    }
    

    }

    其中Fix是定点数,3.4小节会简单描述如何将定点数运用在Unity3D中。本文实现中约定随机种子范围在0-100之间,并采用简单的计算方式。如有特殊需求,自行实现。

    3.4 定点数

    比较简单的方式是,在原来浮点数的基础上乘1000或10000,对应地方除以1000或10000
    其中FP,就可以完全代替Float,我们只需要将我们自己的逻辑部分,Float等改造为FP,TSVector对应Vector3
    Photon网络的早期版本,Truesync

    客户端必须保证对网络帧操作的运算过程和结果一致,然而不同系统平台对浮点数的处理有差别,即便差别甚微,也会造成“蝴蝶效应”,导致不同步现象出现。绝大多数情况下,只需要对游戏对象方位进行定点数改造即可。而Unity3D并非开源游戏引擎,无法对底层transform的position和rotation进行修改。因此,逻辑层计算时需要使用到自定义以定点数为基础的position和rotation,并在每次循环结束之前,将自定义的方位逻辑计算之后所得信息转化Unity3D transform,以便Unity3D更新表现层。使用Unity3D的协同功能Coroutine以及WaitForEndOfFrame()可满足上述需求,即在逻辑层计算完成后,在Unity3D渲染之前更新底层transform的position和rotation。

    3.5 网络波动

    帧同步机制下,玩家输入发送到网络,所有响应都必须要等网络逻辑帧才能进行处理。理想环境下,网络帧操作接收到的频率是固定的,能保证客户端表现正常不卡顿。但事实是,绝大多数情况下网络都是不稳定的,时快时慢难以预测。最简单的方案就是建立一个网络逻辑帧的缓冲区,设置一个缓冲区上限,当存入缓存区的帧数满足上限之后,按照固定频率播放。若缓冲区变空,等待其重新填满。通过累积网络逻辑帧延迟,平均分布到固定频率,平滑处理了网络波动造成的卡顿。

    3.6 丢帧处理

    由于TCP的丢包重传机制会导致较大的延迟,大多数情况下,帧同步都采用UDP协议进行网络通信,这就意味着需要自行解决丢包问题。

    预防:关键帧数据包里携带前面两帧的数据,可大大降低丢包率,但会带来冗余的增加。因此,值得注意的是不能使用UDP数据包过大,否则部分路由器会在组合UPD分组时发生错误,建议不超过Internet标准MTU尺寸576byte。

    补救:虽然上述方案能起到预防丢帧的作用,仍然无法避免丢帧问题。在出现丢帧问题时,需要客户端根据所需帧序号主动向服务器请求关键帧,包括单帧请求和批量帧请求。为了保证能够获取到所需关键帧,建议采用TCP协议。

    四.结束语

    上述内容都是基于《全民XXX》帧同步机制,是对实现过程中所面临难题的总结。在此分享,希望对他人有所帮助。由于作者技术和写作水平有限,若有更好的意见或错误的地方,欢迎指导。

    http://www.360doc.com/content/17/0424/15/6432946_648246185.shtml
    https://blog.csdn.net/UWA4D/article/details/81486242
    http://www.sohu.com/a/153269736_163917

    展开全文
  • 帧同步方案

    2018-04-15 14:55:43
    自研游戏帧同步方案分享-novaliu-41632755.ppt是来自大鹅厂的高级技术分享内容,揭示帧同步技术难点以及攻克方案
  • 帧同步原理

    千次阅读 2019-01-21 00:40:44
    常见游戏同步方案1、状态同步2、帧同步二、帧同步技术基础概念1.基础概念1.MOBA类游戏基本服务器架构2.通信方式 一.常见游戏同步方案 同步问题的本质是一致性的问题,在同一局多人游戏的过程中,玩家A看到玩家B的...
  • 【参考博文】GAD-网络游戏同步技术引言 帧同步的形式很泛,根据不同游戏,使用的技术范围又不一样,所以大家都在讲方法论,要全面覆盖可能需要较大的篇幅,所以,我简单描述下。 假定大家对帧同步和状态同步有一定...
  • 帧同步_Quartus II

    2015-07-29 22:29:44
    用Quartus II实现帧同步技术,其中用的是VHDL语言!
  • 同步技术是数字通信系统中非常重要的技术。一般来说数字通信系统要实现多种同步功能才能实现正确的数据通信任务。其技术目标是实现不同地域收发双方的同步通信互联,实现一致的信息数据交换,因此,通信系统是否能够...
  • 帧同步教程 Lockstep Tutorial 00 总纲

    千次阅读 2019-09-03 23:48:08
    本教程的目标是普及帧同步技术,含基本帧同步,以及预测回滚式帧同步,不含ECS 配套的Blog 配套的视频教程 视频项目版本对应 关系 阶段一 视频id 项目版本号 0 none 1 v0.0.1 2 v0.1.1 3 v0.1.1 4 v...
  • 1 引言 数字通信网中,...因此帧同步是同步复接设备中的重要部分[1,2]。 2 同步方案的选择 帧同步通常采用的方法有逐位调整法和置位调整法[3,4]。2.1 逐位调整法 逐位调整法的基本原理[3]是调整收端
  • 网络同步(帧同步)

    千次阅读 2018-02-08 22:12:36
    网络同步采用是帧同步技术。 帧同步的背景介绍:就是一个对于一个f(x) 函数,对于同一输入,输出结果一定相同。 拿格斗游戏举例,a挥刀,b下蹲作为输入的参数,x1,x2 ,函数f(x1,x2) 输出固定的一个结果(相对俩个...
  • Unity3D RTS游戏中帧同步实现

    千次阅读 2019-10-03 16:59:21
    帧同步技术是早期RTS游戏常用的一种同步技术,本篇文章要给大家介绍的是RTX游戏中帧同步实现,帧同步是一种前后端数据同步的方式,一般应用于对实时性要求很高的网络游戏,想要了解更多帧同步的知识,继续往下看。...
  • 帧同步和状态同步

    万次阅读 2017-06-18 20:03:58
    实时游戏发展迅猛,同步技术也逐渐成为解决方案的核心之一。 本文简单讨论了帧同步和状态同步。
  • 游戏帧同步学习笔记

    2020-07-31 09:30:20
    现代多人游戏中,多个客户端之间的通讯大多以同步多方状态为主要目标,为了实现这一目标,主要有两个技术方向:状态同步、帧同步。 二、状态同步 1、什么是状态同步 状态同步简单来说就是同步游戏中的各种状态,当...
  • 网络游戏之帧同步物理模拟

    千次阅读 2017-07-25 19:36:09
    笔者介绍:姜雪伟,IT公司技术合伙人,IT...CSDN视频网址:http://edu.csdn.net/lecturer/144 本篇博客我们将用网络中的帧同步技术进行物理模拟,帧同步是通过仅发送控制该系统的输入而不是该系统的状态将系统从一

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 56,163
精华内容 22,465
关键字:

帧同步技术