开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2006

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 915|回复: 18

[韩宇飞] 帧同步:浮点精度测试

[复制链接]  [移动端链接]

7

主题

10

帖子

82

积分

Rank: 2Rank: 2

UID
67815
好友
2
蛮牛币
481
威望
0
注册时间
2015-1-12
在线时间
21 小时
最后登录
2017-12-13
QQ
发表于 7 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
      最早接触帧同步的概念是在2005年开发PS游戏高智能方程式赛车3的时候,当时负责赛车游戏的逻辑,物理,AI和录像回放等功能,录像回放就是使用点帧同步实现的。一场比赛只要保存玩家在不同时刻的操作即可,回放的时候就再跑一遍游戏在相同的时间执行相同的操作,得到相同的结果。对于主机游戏来说帧同步实现要简单很多,因为设备唯一,不存在浮点精度的问题,甚至都不需要逻辑层和表现层分离,只要简单的限帧即可。


1.png


      2015年开发一款3D战斗卡牌游戏的时候又使用了帧同步技术,因为当时服务器只有一个人战斗逻辑在客户端,一开始使用主机模式问题很多,迫不得已临时改成帧同步。因为是中途改的所以实现比较简单,使用FixedUpdate对逻辑限帧,使用TCP,可以说问题还是很多的。但因为1V1的横版游戏,玩家操作频率非常低,战斗也相对简单,有些不同步和延迟也还能接受。当时因为时间紧迫,开发的时候就遇到一个不同步问题解决一个,例如脚本更新顺序,逻辑帧更新等,其实也发现有浮点精度的问题,但因为时间有限只是对一些地方做了截断保护,后续项目又改成状态同步了也没有深究。


      后来也了解过同类型游戏刀塔传奇的帧同步,刀塔传奇逻辑使用lua脚本,双精度浮点数double的精度问题比float好很多,另外2D游戏的运算相对3D简单,当时只遇到过一个数学运算有问题做了特殊处理就解决了。


      最近在做一款射击类MOBA项目的时候,又采用了帧同步技术(帧同步和状态同步的对比和选择后续做更详细的介绍)。这是一款3D物理的俯视角射击MOBA项目,游戏中大量运用了真3D物理运算,双摇杆射击,最多支持16人战斗。游戏节奏非常快,操作频率非常高,一直会有大量玩家同屏团战,每个角色射速极高每帧有多发子弹,每个子弹都有弹道和物理计算,是一款对性能和延迟要求非常高的游戏。这时候同步就不能有一点问题了,任何一个Error或者运算的不同步就会导致结果的巨大差异,并且非常显而易见,使游戏无法进行,因此浮点精度问题也必须得到彻底解决了。


      浮点精度的问题在PC上就有跨平台的问题,因为语言编译器不同使用的寄存器和运算过程中的舍入方式不同。就会导致在不同平台下相同的float运算会出现不同的结果,这方面有很多文章阐述就不多做阐述。而在手机上IOS还好比较单纯,设备系统硬件千差万别就更容易出现精度问题了。


首先我做了一些单元测试:
2.png 3.png


*如上图,通过简单的单元测试函数对各种常规的数学运算做了测试。

测试方法是:
  • 首先在Windows64位电脑上生成浮点型测试数据,然后通过测试函数执行n次运算。


  • 将测试结果的二进制保存到配置文件中。这里需要说明的是因为float是小数点后7位,在编辑中最多可以显示到9位例如1.876777650比较起来不直观。另外也存在多个十进制数据对应一个二进制浮点数的情况,例如在编辑器中看到5.0,保存之后再读取显示可能就是4.9999999,他们两个对应相同的二进制是一样的。为了便于对比,我写了一个简单的函数将各种类型统一转成二进制,保存的时候按二进制写入和读取,输出的时候也对应输出浮点数的二进制表达方式






未命名图片.png



*如上图,将各种类型转换成二进制字符串的函数。


  • 在其他各种设备运行测试程序,读取浮点测试数据,执行相同的运算,显示测试数据和运算结果的十进制和二进制结果。
  • 读取Windows64位电脑上的二进制测试结果,和当前运算结果进行比较,如果不同显示Error,并显示双方的二进制结果。




结果如下:
5.png



       可以发现连简单的x*x+y*y+z*z计算就出现了结果不一致,并且x*x,y*y,z*z和x*x+y*y都是一致的,就是y*y+z*z出现了不一致,猜测可能是不同设备的寄存器使用和舍入方式不同导致的误差,任何一个数学运算都有可能出现。


进一步测试:
  • 进过更细致的测试,我发现Windows,IOS,Android三个平台之间会出现float运算结果不一致的情况,其中Windows设备之间、IOS设备之间是一致的(也可能设备较少),Android平台下即使同一个平台不同机型之间也会有大量运算不一致。并且各种运算都有可能出现,没有规律可言(例如某个只有数学运算不一致)。


  • 此外我又针对Unity的Physx物理引擎做了精度测试,创建一个3D世界,随机分布各种几何体胶囊,球,茶壶,立方体等等,然后从原点位置随机发射1000根射线,再用相同的方式记录和对比结果,最终发现物理运算也出现了不一致的现象!


  • 最后我还让做AI的同事对Unity的寻路系统Navmesh做了测试,生成一张带Navmesh的场景生成10000个测试路径然后保存和对比,这次结果就比较有趣了,让我吃了一惊,结果居然是一致的!


测试结果:
  • 通过测试可以发现在如果逻辑代码中使用float连最基本的数学运算都保证不了,可见逻辑部分是不可能使用float了。
  • 同样物理运算也会有不一致的问题,不能直接使用,但测试结果主要在浮点数位数的误差上。
  • 使用Navmesh没有发现不一致的问题,可能有隐患但应该还是可以使用的。


解决方案:
  • 代码中使用float的问题,我们通过在逻辑层使用定点数取代float来解决。我在刚入行的时候使用过定点数,当时主要是为了解决在手机上浮点数运算非常慢的问题。早期Doom,Quick等都使用过定点数的优化方式,在3D游戏编程大师的书中还提供过一套定点数学库。我的一个同事在此基础上实现了一套基于定点数的数学库,提供和Unity相似的接口,并对一些函数做了查表优化。另一个同事修改了导表工具,使得策划的填表数据也支持定点数,完美解决。后来我们还逆向了另外一款爆款帧同步游戏看了一下,他们也做了特殊处理,使用乘1000的方式来解决,类似我们的顶点数学库但更难使用。



    6.png



  • 因为大量使用了真实的3D物理,所以物理对我们来说是一道跨不过去的槛。我们尝试过多种解决方案,先是让公司引擎组的同事帮忙修改Unity和PhysX源码发现工作量巨大,然后又尝试修改bullet为定点数替换PhysX,但是修改后的Unity版本性能差了几百倍无法使用。最终迫于时间压力,我们还是采用了有些隐患的做法:只使用Unity最基本的射线和BoxCollider,在此基础上实现了一套简单的定点数物理引擎。但是即使这样还是会出现不一致的问题,我们又加入了尾数截断,按碰撞方向截断等方式保障一致性。最终在几十万把上线测试中还没有发现物理导致的不一致问题。(需要说明的是,如果要使用动态碰撞器,需要修改一下Unity源码,让物理引擎的Update可以再逻辑帧驱动,非常感谢引擎组同事的帮忙。Unity的新版好像提供了这个功能。)



  • Navmesh没有发现问题,我们实际使用也没出现问题,我们只使用了Navmesh的路点。


总结:
        Float的一致性问题是帧同步方案的最基本的问题,也是相对比较好解决的问题,在后续开发过程中我们还遇到了无数帧同步的坑和难点,特别是同步和延迟的问题。帧同步是一个上手简单快速的技术,但是对操作频繁对延迟要求极高的大型游戏来说就变的非常难了。
针对同步问题我们还开发了一整套工具,当出现不同步的时第一时间就会上报,同时上传录像和日志到文件服务器,可以较快速的定位问题,统计不同步率。配合敏捷开发每日自动构建,代码Review,每次提交自动编译等,及时发现问题。最近一次上线测试玩家进行了39727次战斗未出现不同步,同步率至少达到王者荣耀的水平。


帧同步的不同步的测试还是比较困难和痛苦的,因为只要有一点没测到导致不同步上线之后可能就有非常大的风险,后续也会开发更强大的自动化测试工具,实现一种愉悦的开发方式!

补充:
  • 针对double类型我也做了测试,不一致性较float大幅下降,但还是会产生不一致问题。
  • PhysX有一个一致性开关,即使打开了,也还是会产生不一致问题。
  • 在延迟上也做了大量优化,逻辑层和表现层完全分离,不使用FixedUpdate的方式降低输出延迟;同时使用了TCP,自己实现的可靠UDP和冗余包的非可靠UDP三种方式通信;极致压缩优化协议包降低在MTU范围以内;逻辑帧负载均衡;分地域部署和匹配;多线程收发等等。延迟数据接近王者荣耀的水平(双摇杆操作更多,服务器部署上延迟略高)。

评分

参与人数 2鲜花 +15 收起 理由
mmuu1987 + 5 很给力!
lilexy + 10 2005年就搞游戏开发,厉害了

查看全部评分


回复

使用道具 举报

7日久生情
3280/5000
排名
4934
昨日变化
36

4

主题

2740

帖子

3280

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
209186
好友
5
蛮牛币
3787
威望
0
注册时间
2017-3-1
在线时间
306 小时
最后登录
2017-12-13
发表于 7 天前 | 显示全部楼层
谢谢分享

回复

使用道具 举报

7日久生情
2970/5000
排名
2113
昨日变化
10

0

主题

1891

帖子

2970

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
94526
好友
0
蛮牛币
1714
威望
0
注册时间
2015-4-22
在线时间
537 小时
最后登录
2017-12-13
发表于 7 天前 | 显示全部楼层
感谢楼主分享
[发帖际遇]: Lnoe 乐于助人,奖励 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

4四处流浪
479/500
排名
8393
昨日变化
83

3

主题

260

帖子

479

积分

Rank: 4

UID
236677
好友
0
蛮牛币
742
威望
0
注册时间
2017-8-9
在线时间
104 小时
最后登录
2017-12-13
发表于 7 天前 | 显示全部楼层
[发帖际遇]: 一个袋子砸在了 lidong91 头上,lidong91 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

排名
29328
昨日变化
23

0

主题

14

帖子

30

积分

Rank: 1

UID
256652
好友
0
蛮牛币
7
威望
0
注册时间
2017-11-28
在线时间
9 小时
最后登录
2017-12-12
发表于 7 天前 | 显示全部楼层
谢谢分享
[发帖际遇]: 一个袋子砸在了 Kit_RDjZ2 头上,Kit_RDjZ2 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

7日久生情
1525/5000
排名
5628
昨日变化
46

2

主题

1119

帖子

1525

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
241666
好友
0
蛮牛币
6002
威望
0
注册时间
2017-9-6
在线时间
208 小时
最后登录
2017-12-13
发表于 6 天前 来自Mobile--- | 显示全部楼层
感谢分享

回复

使用道具 举报

5熟悉之中
813/1000
排名
8108
昨日变化
83

1

主题

582

帖子

813

积分

Rank: 5Rank: 5

UID
246489
好友
0
蛮牛币
1395
威望
0
注册时间
2017-9-28
在线时间
112 小时
最后登录
2017-12-13

活力之星迈向小康

发表于 6 天前 | 显示全部楼层
谢谢分享

回复

使用道具 举报

5熟悉之中
605/1000
排名
5578
昨日变化
47

1

主题

285

帖子

605

积分

Rank: 5Rank: 5

UID
234265
好友
1
蛮牛币
46
威望
0
注册时间
2017-7-26
在线时间
121 小时
最后登录
2017-12-13
发表于 6 天前 | 显示全部楼层
6666666666666

回复

使用道具 举报

6蛮牛粉丝
1115/1500
排名
4840
昨日变化
28

7

主题

482

帖子

1115

积分

Rank: 6Rank: 6Rank: 6

UID
168159
好友
2
蛮牛币
4358
威望
0
注册时间
2016-9-12
在线时间
394 小时
最后登录
2017-12-13

迈向小康

发表于 6 天前 | 显示全部楼层

回复

使用道具 举报

6蛮牛粉丝
1021/1500
排名
3355
昨日变化
21

0

主题

488

帖子

1021

积分

Rank: 6Rank: 6Rank: 6

UID
18067
好友
0
蛮牛币
1140
威望
0
注册时间
2014-3-18
在线时间
184 小时
最后登录
2017-12-12
QQ
发表于 6 天前 | 显示全部楼层
謝謝版主分享
[发帖际遇]: jbsuen 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复

使用道具 举报

4四处流浪
366/500
排名
5410
昨日变化
33

0

主题

51

帖子

366

积分

Rank: 4

UID
159593
好友
0
蛮牛币
796
威望
0
注册时间
2016-7-30
在线时间
111 小时
最后登录
2017-12-13
发表于 6 天前 | 显示全部楼层
相关的同步工具会公开吗?新人求教
[发帖际遇]: 那谁你别跑呀 在网吧通宵,花了 2 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

5熟悉之中
507/1000
排名
8679
昨日变化
89

0

主题

321

帖子

507

积分

Rank: 5Rank: 5

UID
219676
好友
0
蛮牛币
235
威望
0
注册时间
2017-7-12
在线时间
80 小时
最后登录
2017-12-13
发表于 6 天前 | 显示全部楼层
谢谢分享

回复

使用道具 举报

排名
15027
昨日变化
381

0

主题

29

帖子

87

积分

Rank: 2Rank: 2

UID
254155
好友
0
蛮牛币
125
威望
0
注册时间
2017-11-13
在线时间
20 小时
最后登录
2017-12-13
发表于 6 天前 | 显示全部楼层
深度好文。。

回复

使用道具 举报

4四处流浪
477/500
排名
7621
昨日变化
76

0

主题

248

帖子

477

积分

Rank: 4

UID
182268
好友
0
蛮牛币
465
威望
0
注册时间
2016-11-9
在线时间
99 小时
最后登录
2017-12-13
发表于 6 天前 | 显示全部楼层
老铁很6啊

回复

使用道具 举报

5熟悉之中
529/1000
排名
5904
昨日变化
51

0

主题

255

帖子

529

积分

Rank: 5Rank: 5

UID
185339
好友
0
蛮牛币
710
威望
0
注册时间
2016-11-20
在线时间
90 小时
最后登录
2017-12-13
发表于 6 天前 | 显示全部楼层
谢谢分享

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表