网络游戏同步技术五:帧同步的优化与实现

本文讲一讲 “帧同步” 的优化手段。


优化手段

帧同步的确定性,要求各种平台之上的客户端计算都是确定的,这些都可能导致不确定计算:浮点数,随机数,执行顺序,排序的稳定性,物理引擎。

  • 浮点数可以使用定点数替代。
  • 随机数可以统一随机数种子。
  • 执行顺序,要保持一致,需要所有的逻辑要有一个统一的入口,每次 tick update 进入一个统一的入口,依次调用各个模块的逻辑。
  • 排序的稳定性,可以指定统一的稳定排序算法。
  • 物理引擎,要求确定性的模拟,需要选用保证确定性的物理引擎。

帧同步的挑战很大,由于误差累积会变大,基本上只要有一次计算不一致,那后续结果就都不一致了,游戏也就玩不下去了,王者荣耀的这个分享[1]就讲了很多这一方面的努力。

可以使用的优化手段包括以下这些:


乐观帧

现在事实意义上的帧同步算法都是用的乐观帧了,即每帧固定时长,超时不等待。

但这里有个细节问题,客户端发送给服务端的 input 数据包都是带有客户端帧号的,那么服务端是否要抛弃客户端过时的 input 数据包,即客户端帧号小于当前服务端帧号的数据包?

比如这个 demo 项目(https://github.com/JiepengTan/Lockstep-Tutorial)就是会抛弃客户端 input 数据包的。 https://github.com/JiepengTan/Lockstep-Tutorial/blob/master/Server/Src/SimpleServer/Src/Server/Game.cs:

void C2G_PlayerInput(Player player, BaseMsg data){
    ...
    if (input.Tick < Tick) {
        return;
    }
    ...
}

这样抛弃是否会带来问题?似乎是有问题的,即一个延迟高的客户端,它的 input 永远不会被服务端应用。我认为这样是不妥的,那么如何实现才是好的呢?

参考另一个 demo ( https://github.com/Enanyy/Frame ),这个实现不会抛弃客户端过时的 input 数据包,代码在此( https://github.com/Enanyy/Frame/blob/master/FrameServer/FrameServer/Program.cs ):

private void OnOptimisticFrame(Session client, GM_Frame recvData)
{

    int roleId = recvData.roleId;

    long frame = recvData.frame;

    Debug.Log(string.Format("Receive roleid={0} serverframe:{1} clientframe:{2} command:{3}", roleId, mCurrentFrame, frame,recvData.command.Count),ConsoleColor.DarkYellow);
    
    if (mFrameDic.ContainsKey(mCurrentFrame) == false)
    {
        mFrameDic[mCurrentFrame] = new Dictionary<int, List<Command>>();
    }
    for (int i = 0; i < recvData.command.Count; ++i)
    {
        //乐观模式以服务器收到的时间为准
        Command frameData = new Command(recvData.command[i].frame, recvData.command[i].type, recvData.command[i].data, mFrameTime);
        if (mFrameDic[mCurrentFrame].ContainsKey(roleId) == false)
        {
            mFrameDic[mCurrentFrame].Add(roleId, new List<Command>());
        }
        mFrameDic[mCurrentFrame][roleId].Add(frameData);
    }
}

buffering

针对延迟以及网络抖动,可以通过增加缓冲区的方式来对抗:
输入 -> 缓冲区 -> 渲染
缓冲区的问题在于会增加延迟。


预测回滚

不止是状态同步,帧同步也是可以 “预测回滚” 的,但叫法是 timewarp。大体做法都是记录快照,然后出现冲突的时候回滚到快照点。韦易笑的这篇文章《帧同步游戏中使用 Run-Ahead 隐藏输入延迟》[2]介绍过这种做法。


参考

[1] 邓君. 王者技术修炼之路. Available at https://youxiputao.com/articles/11842, 2017-5.

[2] 韦易笑. 帧同步游戏中使用 Run-Ahead 隐藏输入延迟. Available at https://www.skywind.me/blog/archives/2746, 2023-10.

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 帧同步 Unity demo 是 Unity 引擎开发的一款演示程序,主要展示了帧同步技术游戏中的应用。帧同步是一种在多人联机游戏中常用的同步方法,它的作用是保证游戏中各个玩家的行为在各自的客户端中是一致的,从而避免了因网络延迟导致的卡顿和不一致性等问题。 这个 demo 的玩法是多人同时进行射击,每个玩家可以看到所有人的射击轨迹和得分,同时也会受到其他玩家的射击影响。整个游戏场景设计简洁,主要通过一些简单的几何体和粒子效果来呈现射击轨迹和得分效果。 在技术实现上,这个 demo 使用了 Photon Network 插件来实现帧同步功能。Photon Network 是一款专门为多人联机游戏开发的网络插件,它提供了一套完整的同步方案,可以方便地集成到 Unity 项目中。通过使用 Photon Network,游戏中各个玩家可以实时地同步数据,包括射击轨迹、得分以及其他玩家的位置等信息。 总的来说,这个帧同步 Unity demo 展示了帧同步游戏中的应用和效果,并为其他开发者提供了一些参考和学习的资料。帧同步技术在现代多人联机游戏中非常重要,开发者需要充分掌握这种技术,并结合自己的实际需求来选择最合适的同步方案。 ### 回答2: 帧同步 Unity Demo是一个基于Unity引擎开发的多人游戏示例,它的主要特点是采用了帧同步技术帧同步是一种实现多人游戏同步技术,其原理是在每个客户端上运行相同的游戏逻辑,通过同步每一帧的状态信息,来实现多人游戏同步。因此,帧同步可以保证游戏的公平性和严密性。 该Demo主要包括两个部分:客户端和服务器端。客户端主要负责渲染游戏画面和响应玩家的输入操作,而服务器端则负责协调各个客户端之间的信息交互,并且统一控制游戏规则。 该Demo提供了多种游戏模式,比如竞速、对战等模式。玩家可以通过选择不同的游戏模式来体验不同的游戏玩法。此外,该Demo还支持多种游戏设备,比如键盘、手柄等设备,玩家可以根据自己的喜好来选择适合自己的设备进行游戏。 总之,帧同步Unity Demo是一款非常精彩的多人游戏示例。它的核心技术帧同步可以有效地保证游戏的公平性和稳定性,而且游戏玩法丰富多样,能够满足玩家不同的需求。如果你是一名多人游戏爱好者,那么帧同步Unity Demo绝对是你不容错过的一款游戏。 ### 回答3: 帧同步 unity demo 是指使用 unity 引擎开发的游戏 demo,并在网络互联环境中实现帧同步功能。帧同步是一种常用的网络同步技术,它能保证多个玩家在游戏中的行为完全一致,从而实现真实的多人在线游戏体验。 在帧同步 unity demo 中,首先需要将游戏的场景和物体定义好,并设置好网络通信环境。然后玩家在游戏中进行的所有操作都需要通过网络传输到其他玩家的客户端进行处理和显示。同时,服务器需要对玩家的操作进行验证和同步,确保所有玩家的游戏状态以及操作是相同的。 帧同步 unity demo 的实现过程中,需要解决多种问题。例如,如何处理网络延迟导致的玩家操作不同步问题;如何防止作弊和恶意攻击;如何优化网络通信以提高游戏性能等。 总之,帧同步 unity demo 是一种高度技术化的多人在线游戏开发方案,它能够帮助开发者更好地构建真实、稳定、流畅的多人游戏体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值