客户端-服务端之间的位置同步一直是游戏开发中的一道难题,特别是还涉及到复杂的物理运动时。对于这个话题,来自《太空工程师》游戏的工程师在GDC 2023上为我们带来了他们的分享——《《太空工程师》中基于预测物理的多人游戏》(Predicted Physics Based Multiplayer in ‘Space Engineers’)。PPT可点击链接获取。

原PPT内容较长,足有120多页。本文取其精华以飨读者。

《太空工程师》是一款关于在太空中建造、探索和生存的沙盒游戏。游戏中所有的物品都可以被组装和拆解。玩家可以建造属于自己的太空飞船和宇宙空间站,还可以选择相互合作或者战斗。

对于这样一款涉及到复杂物理运动的游戏,有不少同步相关的问题需要解决。例如:

  • 运动状态是以服务端还是客户端为准?
  • 当遇到延时时,如何保证客户端的运动流畅?
  • 如果客户端和服务端不同步,应该如何做修正?
  • 对于有强关联性的一组物体(如太空飞船和在它表面的宇航员),它们的同步较容易产生状态不一致,这时应如何解决?

带着这些问题,我们看下《太空工程师》的应对策略。我们会从一个最简单的同步方案开始,一步步进化成完整的方案。

首先考虑基础同步方案(Naive Postion Updates)。主流的同步方案可以按服务端承担责任的轻重,粗略分为两大类:一类是客户端将状态发给服务端,服务端只做转发;另一类是服务端有一个完整的物理世界,运动状态以服务端每帧的计算结果为准,客户端只发送玩家操作给服务端,然后使用服务端的推送结果来修正当前的运动状态。由于《太空工程师》中的物理交互非常多而且重要,所以选择后面一种方案。

通信协议基于UDP,只对部分类型的包保证可靠性。这样做可以兼顾延时和可靠性。

状态推送采用一种分层AOI的策略。例如,玩家操纵的人物只接受他周围3km以内物体的更新;在20米半径内每4帧更新一次,在接近3km的地方降低到每60帧更新一次。


服务端每帧向客户端推送状态消息,在存在延时的情况下,包可能乱序到达,甚至出现丢包的情况。

解决办法是在服务端使用播放延迟缓冲器(PDB,playout delay buffer)。这个缓冲器包含4个包的存储位,每帧接收一个客户端的包,插入缓冲器中,并与已存储的包一起按序号顺序排列。如果存储的包总数大于4个,那么会把序号最小的一个包移出缓冲器,并推送到客户端。例如,服务端先后接收到2、5、3三个包,会按下图排列成2、3、5的顺序。

使用PDB的好处是可以在一定范围内将乱序的包重新排列成有序。缺点是会增加额外的延迟时间。

游戏中会用转子、活塞之类的部件把不同物体组合到一起。整体会运动,每个部件也会独立运动。如果为每个部件单独做运动插值,那么合并起来运动必然是断裂的。解决办法是使用相对位置同步(Relative Position Updates),具体来说是先定义物体之间的层次关系,再对子级物体做相对于它的父级物体的运动插值,即本地空间中的运动插值。一般选择被控制的物体或者最大的物体作为根级物体。

接下来我们考虑延时(Lag)对同步的影响。这里的延时是指从按下操作键到屏幕上出现反馈的时间。这个时间通常是难以忽视的,例如,当ping为50ms时,由于网络传输、渲染、GPU等多个步骤的时间累积,估算总延时高达200多ms。这里引述了卡马克的一句话:“我发送一个IP包到欧洲,速度竟然快过发送一个像素到屏幕上”。

对于这样高的延时,如果客户端完全等待服务端推送才能动起来,那么玩家体验必然很差。解决办法是预测服务端的状态(Basic Prediction),让客户端先动起来。

预测方法是:客户端每帧向服务端同步当前的操作和位置,并且在本地保存同步的历史记录;服务端接到消息后推送给所有客户端;客户端接到服务端推送后与历史记录比较,若有误差则修正当前运动状态。
有时候客户端或者服务端会出现掉帧,掉帧会影响同步的正确性。出现掉帧时,我们可以让客户端临时提升或者降低帧频,以保证和服务端一致。

当客户端接收到服务端的推送和本地历史记录不一致时,即为预测不同步。这时我们需要按服务端的推送数据来对客户端的运动状态做预测修正(Prediction Correction)。例如,在下图的示例中,服务端某个时刻出现了一个新的障碍物,这个情况暂时还没能同步到客户端那边。因此服务端和客户端会有不同的运动状态:服务端会尝试碰撞障碍物但进不去,然后沿着其表面向上运动;客户端会进入到障碍物所在的位置再向上,直到接收到服务端的推送与本地记录不符,再修正成退出障碍物所在区域。
由于浮点运算等原因,服务端推送结果不可能与客户端历史记录100%匹配,所以我们只在差异足够大的情况下做修正。

另一个要解决的重要问题是时间矛盾(Time Paradox),即由于网络传输延时导致的客户端、服务端状态不一致,多见于多个运动物体发生交互时。例如,在太空中,宇宙飞船和宇航员同样以50m/s的速度向左运动,宇航员试图进入到船舱中。由于存在网络延时,客户端的宇宙飞船运行状态落后于服务端2.5m,导致客户端看到宇航员正对着舱门,而服务端对着墙壁。
这样造成的结果是:客户端上宇航员成功进入船舱,而服务端会碰壁,稍后服务端把碰壁消息推送给客户端,客户端据此修正,又将宇航员移出船舱。
如果纯靠客户端修正的话,玩家体验不佳。优化方法是使用相对预测(Relative Prediction)。

具体做法是:当宇航员接近宇宙飞船时,将宇航员设为飞船的子物体,并且将服务端的状态立即通知客户端做修正。这里的父子物体概念与前面通过物理限制连接在一起有所不同,这里的概念是逻辑上的。将宇航员和飞船绑定后,宇航员的运动状态更新改为相对飞船的相对运动。
当发生绑定时,客户端的宇航员状态要根据服务端的相对位置做修正,这个过程使用插值保证平滑过渡。
最终结果就是不再会出现客户端上宇航员进舱后又被拖出来的尴尬场景。

这里需要提及一下客户端物理设置的标准。标准是:所有动画驱动的物体设置成静态刚体。当物体切换为受控状态时,对应刚体也切换成动态刚体,并且向客户端持续推送运动状态更新。如果该物体有父级物体,那么需要继承父级物体的运动。
最后是对本次分享整体思路的总结,都浓缩在下张PPT中:

近年GDC服务器分享合集(二): 《太空工程师》中基于预测物理的多人游戏相关推荐

  1. 近年GDC服务器分享合集(一):在《黑道圣徒》的boss工厂中创建可扩展和吸引人的UGC

    为什么写作这个系列 GDC(Game Developers Conference)是游戏界最富盛名的开发者大会,每年有来自全球各地的顶级游戏开发者分享前沿的游戏设计.技术和运营经验. GDC上的技术分 ...

  2. 算法合集之《信息学中守恒法的应用》(不错的文章保存一下)

    算法合集之<信息学中守恒法的应用>(不错的文章保存一下) by 三江小渡 [摘要]本文提出和总结了"守恒法",以及它在信 息学竞赛中的一些应用.守恒的本质是寻找变化中的 ...

  3. 嵌入式分享合集137

    一.5大电气制图软件 一个电气人的基本从业准则就是要识图.绘图.首先要了解什么是电气图?电气图常用于建筑行业,是建筑内的线路.照明.空调及相关电气设备的平面展示.同时也是建筑工人施工的依据,因此,准确 ...

  4. MATLAB | 特殊绘图小合集(二) | 金字塔图、类桑基图、y轴分段填充折线图

    居然又攒出了一期特殊绘图小合集文章,本来以为要攒很久的,本系列主要拿出来一些简单的,单独拿来写篇幅会很短的绘图小技巧做个合集,本期代码为了绘制好看大部分情况使用了以下这段简单小代码进行修饰: func ...

  5. JAVA Web项目中所出现错误及解决方式合集(不断更新中)

    JAVA Web项目中所出现错误及解决方式合集 前言 一.几个或许会用到的软件下载官网 二.Eclipse的[preferences]下没有[sever]选项 三.Tomcat的安装路径找不到 四.T ...

  6. Plant Simulation、NX MCD、PDPS,SIMIT,PLCSIM仿真与虚拟调试合集(持续更新中)

    一文了解PLCSIM.SIMIT.Amesim.NX MCD. Process Simulate.Plant Simulation等仿真与虚拟调试软硬件: 一文了解PLCSIM.SIMIT.Amesi ...

  7. Stable Diffusion 个人推荐的各种模型及设置参数、扩展应用等合集(不断更新中)

    本文主要是把平时使用的模型及其参数进行推荐和整理,相关 安装及其问题解决参考:<Windows安装Stable Diffusion WebUI及问题解决记录>: 运行使用时问题<Wi ...

  8. IDEA 2020.3.2控制台中文乱码分享(亲测二、下图中控制台的编码改为UTF-8)

    IDEA 2020.3.2控制台中文乱码的个人解决方案分享 我的电脑环境:win1020h2,IDEA2020.3.2,Tomcat9.0.40,终端配的powershell 1 一.改文件编码,下面 ...

  9. 嵌入式分享合集105

    一.智能灯光控制系统(基于stm32) 带你走进物联网的世界说一个整天方案哦 这次是基于stm32的 当然你可以用esp "智能光照灯"使用STM32作为系统的MCU,由于单片机I ...

最新文章

  1. iOS多线程编程:线程同步总结 NSCondtion
  2. 信息项目管理师-项目时间管理知识点
  3. IDE之VS:Visual Studio2017版本安装图文教程之详细攻略
  4. redis应用之——注册、登录
  5. 作品分享_作品分享 | No. 1
  6. HDU 5510 Bazinga
  7. 话筒好坏测试软件,如何简单地判断麦克风的质量好坏?
  8. C# windows定时服务+服务邮箱发送
  9. Ride to Office(信息学奥赛一本通-T1227)
  10. matlab fft函数说明_关于“如何使用FFT计算天线阵列方向图”学习资料总结
  11. 表单多条相同name数据的获取
  12. 使用javadoc命令制作帮助文档(API)
  13. 软件设计开发笔记2:基于QT设计串口调试工具
  14. python微信商城_GitHub - pythonsir/nideshop: NideShop 开源微信小程序商城服务端(Node.js + ThinkJS)...
  15. 微信公众号推送模板消息(四):Java调用实现模板消息推送
  16. proc sys文件系统对比
  17. dede标签帮助手册参考
  18. 位操作技巧:Bit Twiddling Hacks
  19. Zabbix 如何实现邮件报警通知以及免费短信报警通知
  20. 邮件服务器(eas)找不到服务器,Exchange ActiveSync 无法访问邮箱服务器上的邮箱,因为邮箱服务器处于脱机状态...

热门文章

  1. refactoring?
  2. 【进度总结】软件工程选题报告
  3. line-hight的影响
  4. 新的选择,该如何择业
  5. 金杉号:2022年农村创业有哪些投资项目?
  6. 程序江湖:第三章 莫等闲白了少年头
  7. 基于CNN的人脸表情识别系统
  8. 【华为OD机试真题 python】最多等和不相交连续子序列【2022 Q4 | 100分】
  9. 进制问题 权滴滴滴滴滴
  10. 7-3 复数四则运算