zoukankan      html  css  js  c++  java
  • 服务器客户端同步 之 关于跳帧问题

    网上有很多同步方案, 我看了下,都比较麻烦,新人也看不懂,老人也不要看。于是我简单写了一下,方便大家快速上手。

    做之前,服务端 必须是udp 通讯,这个我不多解释,我用的是lidgren 通讯框架,不知道的,可以看我过去的文章。

    代码思路,服务器每秒 发一次,可以用线程做。

      public static void Confrontation()
            {
                while (true)
                {
                    Thread.Sleep(1000);
                    Output("目前" + Frame);
                    List<NetConnection> all = s_server.Connections; // get copy
                    //   all.Remove(msg.SenderConnection);
                    if (all.Count > 0)
                    {
                        NetOutgoingMessage om = s_server.CreateMessage();
                        JsonDatas message = new JsonDatas();
                        message.jsons["type"] = "5";
                        message.jsons["msg"] = Frame;
                        string json = JsonConvert.SerializeObject(message);
                        om.Write(json);
                        s_server.SendMessage(om, all, NetDeliveryMethod.ReliableOrdered, 0);
                    }
                    if (Frame%7==0)
                    {
                        Frame += 2;
                    }
                    else
                    {
                        Frame++;
                    }
                }
            }

    这个是 线程里面的方法,all是代表所有在线 用户 套接字端口。 数据是 json格式,方便客户端判断。Frame是 帧,每秒加1,最后我 Frame%7 是为了方便 跳帧测试,也就是说,到7倍数帧时候,我的帧 不是 加1,而是加2,让客户端 来判断,需要跳帧。

    再看看客户端,因为客户端 在 updata里面是 一秒60帧,我把他变成 一秒10帧。类似

     if (GameModel.getInstance().Rate == 6)
            {
                GameModel.getInstance().Rate = 0;
    }   GameModel.getInstance().Rate++;

    然后,我把服务器发过来的 Frame乘以  10;对应起来;

    客户端逻辑处理有三个方式,等待,正常运行,跳帧。

    等待是因为 客户端执行完毕所有帧,服务端帧还没过来,这个时候需要等待,也可以做暂停。

    跳帧是  通过判断 客户端帧 和 服务端帧 差 大于 10帧。 那么就 遍历,使得快速 让 客户端和服务端差距只有 10帧以内。

    最后结果:  前面数据是  客户端当前帧,后面是 服务端帧

    结尾等待是 我把服务器关了,客户端自然等待了。

    最后代码:非常短

        void Update()
        {
            if (FrameBool && GameModel.getInstance().LogicalFrame > 0)
            {
                Frame = GameModel.getInstance().LogicalFrame;
                FrameBool = false;
            }
            if (FrameBool == false)
            {
                OnSetShaderFrame();
            }
        }
    
        //总负责 战斗 逻辑处理
        public void OnSetShaderFrame()
        {
            if (GameModel.getInstance().Rate == Rate)
            {
                GameModel.getInstance().Rate = 0;
    
                if (GameModel.getInstance().LogicalFrame == Frame)//帧相同,客户端等待
                {
                    Debug.Log("-><color=#E88748>" + Frame + "客户端等待 " + GameModel.getInstance().LogicalFrame + "</color>");
                }
                else
                {
                    Debug.Log("-><color=#90E848>" + Frame + "逻辑帧 " + GameModel.getInstance().LogicalFrame + "</color>");
                    Frame++;//执行完毕 帧加一
    
                    if (GameModel.getInstance().LogicalFrame - Frame > 7)//超过1秒 ,6帧 一秒
                    {
                        for (int i = 0; i < (GameModel.getInstance().LogicalFrame - Frame); i++)//保留当前6帧,其他跳帧
                        {
                            Debug.Log("-><color=#E84848>" + Frame + "跳帧执行 " + GameModel.getInstance().LogicalFrame + "</color>");
                            Frame++;//执行完毕 帧加一
                        }
                    }
                }
    
            }
            GameModel.getInstance().Rate++;
        }

    祝大家好运!

  • 相关阅读:
    面向对象(6day)
    pycharm使用问题总结
    docker学习(一)ubuntu上安装docker
    docker指令
    docker简单使用
    使用Docker搭建多人使用GPU服务器
    ubuntu常用指令
    高斯滤波
    ubuntu创建个人账户
    第一次使用SSE指令集
  • 原文地址:https://www.cnblogs.com/big-zhou/p/11387886.html
Copyright © 2011-2022 走看看