游戏思考系列01:游戏的一些问题和思考:1)游戏浮点数精度计算(持续更新)

以问题的形式提出疑问并解答

1.我们游戏采用帧同步框架,计算逻辑的时候不可避免地产生浮点数运算,如移动和跳跃等。为了保证在不同的平台和不同的机器上得到一致的结果,有什么好的方案能解决或避免浮点数结果不一致的问题呢?

这里主要是基于服务器的角度

0)浮点数计算不确定的原因

1)cpu
2)编译器
3)操作系统
4)操作系统的位数
5)IEEE 754浮点数算数的标准
6)汇编指令集

人话解释:计算机并不能天然处理小数,对于小数的计算,不同的编译器、处理器使用了不用的计算标准和优化方式,导致了小数的精度出现了差异。

1)回答一(保留2到四位的小数位即可)

一般情况下,浮点计算涉及到的位置同步无需保留过高的精度,小数点后保留2位到4位足矣。

  • 注意点(也是我用的方法,计算伤害):
1)因此计算前将浮点数乘以1000,然后取整再进行计算,可以有效地解决多端的精度不同步问题。
2)但是需要注意一个问题,就是别超出了你数值类型的最大值范围。(可以用double去计算,float来存)
  • 详细做法
#define BIG_RATE_MAX   1000000LL//定义100W,因为浮点数乘以1W,百分之一百就是100W
double  paraA_trans = (double)paraA/BIG_RATE_MAX; //paraAa就是给的万分制的数

2)回答二(相当于没说)

根据我们自己正在摸索的帧同步经验,如果不是王者荣耀这种级别的游戏,帧同步的浮点数精度影响不是系统的瓶颈。如果战斗时长不长,露馅的概率很低,全改整数的工作量是非常巨大。如果是小公司,要好好评估是否能挺住。逻辑与表现的分离才是最大的问题,意味着Unity的大量组件不能使用。大量的重新实现的东西需要从头去写,当然全用整数也一样得重头去写。游戏小公司需慎重评估生存问题和完美方案的性价比

3)回答三(使用定点数)

帧同步还是定点数,用定点数库比较保险和靠谱,浮点数带来的误差有可能累计到一个无法接受的地步。另外回答其他朋友的一些问题。

  • 解答第二个回答的问题

1)网络传输,使用可靠的UDP(TCP)传输;
2)另外看到其他朋友提到的逻辑与表现的分离,这个是帧同步方案必须的,至于说到的Unity中大量组件组件无法使用,主要是帧同步方案逻辑的处理不应该按照本地时钟时序,而是严格按照服务器逻辑帧处理,说不可用其实主要针对逻辑层而言,表现层其实不见得Unity组件都不可以用,表现层上Unity的组件其实必不可少的

4)定点数的解释连接

传送门

5)浮点数大体解决方案

(1)定点数学库

首先要搞明白什么是浮点数,什么是定点数。

浮点:小数点非固定的数,可表示数据范围较广,整数小数都可以表示,包含float,double。

定点:小数点固定,整数小数都可以表示。int本质是小数点位于末尾的32位定点数而已。
(参考上面的传送门资料)
浮点数的计算不确定性往往是出现在小数点很多位之后,这里是用定点数学库可以保证计算结果相对固定。

(2)查表计算

通常情况下,在计算三角函数的时候,会用到查表的方式获取相应的值。

用枚举法把度数对应的值存在一个数据结构表里,如xml或者json里,这样在用到三角函数计算的时候,我们实际上是查表获取对应的值,这样就会避免在各个平台或者硬件环境下计算结果不一样的情况。(比如sin a ,cos a)

(3)放大截断法

其实就是使用整数去替代浮点数进行的一种计算。首先确认放大因子,比如放大10000倍,实际上就是保留了小数点后四位,然后剩余的小数部分全部截取掉。所有参与计算的浮点数都经过了放大截断的处理然后就是纯整数之间的计算,这样就绕过了浮点数计算的。最后得到需要用来做表现逻辑的数字再除以放大因子10000,就是实际的浮点数值,因为这个值已经不需要在参与逻辑运算了,所以不会带来太大的偏差,只会用于最终的显示。

放大截断法如上面的代码那样

(4)整数计算

把要计算的数值全部弄到整数上面计算,都是整数运算,MMORPG不是很注重这部分误差,所以用整数计算也行,天刀是用的整数计算

6)题外话

游戏开发中,其实上面提到的三种解决方案都是需要结合到一起使用。而且如果要确定使用帧同步技术,Unity中的很多方法和系统都不能使用,例如移动方法,物理系统,寻路系统等,包括使用插件时,也要主要其实是否使用到了浮点数。

猜你喜欢

转载自blog.csdn.net/weixin_43679037/article/details/121531768