找回密码
 立即注册
查看: 291|回复: 0

Unity 3D定点数物理引擎实战系列

[复制链接]
发表于 2022-12-8 11:16 | 显示全部楼层 |阅读模式
帧同步的游戏中如果用物理引擎,为了保证不同设备上的结果一致,需要采用定点数来计算迭代游戏过程中的物理运算。也就是我们通常说的定点数物理引擎(确定性物理引擎)。本系列教程给大家详细的讲解如何在你的项目中内置一个确定性物理引擎。确定性物理引擎我们使用github上开源的物理引擎BEPUphysicsint v1库。本节内容主要有:

(1) 定点数计算的原理与优缺点;

(2) BEPUphysicsint v1的由来;

BEPUphysicsint v1项目的github地址:

https://github.com/sam-vdp/bepuphysics1int

对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习unity的零基础小白,也有一些正在从事游戏开发的技术大佬,欢迎你来交流学习。

定点数计算的原理与优缺点

首先来给第一次接触定点数的开发者介绍一下定点数计算的基本原理。定点数计算的原理很简单, 例如: 1.2 * 1.2, 我们用整数来模拟小数,原理就是确定一个精度,把小数的小数部分放大, 比如1.2, 我们确定精度为在10进制下精确到小数点后1位, 那么1.2对应的定点数为12, (定点数是对应的小数扩大10倍后取整), 如果确定精度是小数点后2位,那么1.2对应的定点数位120(定点数是对应的小数扩大100倍)。我们都知道计算机是二进制的,一个int在32位的机器上, 为32bit, 最高位表示的是符号位,剩下的是31位, 31位中多少表示小数位,就代表定点数的精度。比如 8个bit表示小数部分的精度,那么这个定点数就扩大了2^8。所以1.2变成定点数就是 int (1.2 * 256 = 307.2 整数化后就为307)。

32bit位: 1111 1111 1111 1111 1111 1111 1111 1111, 当你把精度定在哪个bit位,就相当于把小数点定在了多少位, 如上面, 小数点定在了8bit地方, 1111 1111 1111 1111 1111 1111. 1111 1111所以叫做”定点数”。通过扩大倍数,把小数部分按照特定的精度变成了整数,后续都基于整数来进行运算。如果我们的物理引擎使用定点数计算,最后虽然将定点数转化为Unity Transform的相关浮点数显示物体位置,但是最终在决定物理碰撞,游戏事件中, 物理移动中都是定点数化后的整数运行,所以这样就做到了物理引擎迭代的确定性。做到了不同机器上跑物理引擎模拟,结果一致。

搞懂了原理后,我们来看下定点数的加,减,乘,除的模拟,以上述小数点后一位小数为例(扩大10倍):

加法:直接让两个定点数相加即可, 1.2 + 1.2 = 2.4, 12 + 12 = 24

减法:直接上两个定点数相减即可, 1.2 – 1.4 = -0.2 12 – 14 = -2;

乘法:两个定点数相乘相当于多扩大了一倍,最后再除以精度倍数

1.2 * 1.2 = 1.44 12 * 12 = 144 / 10 = 14

除法:两个定点数的除法,分子,分母都扩大10倍,结果相当于没有扩大, 我们可以先把分子再继续扩大十倍,然后再除以分母。也可以把分母缩小10倍再计算(有很多种处理方式)。一般做除法,我们会把分子扩大10倍,再除以分母。1.4 / 1.2 = 1.166 定点数: 14 * 10 / 12 = 11,表示的结果为1.1,也是精确到小数点后1位。

搞懂了上述的计算过程后,我们知道定点数的优点就是都是基于整数计算,结果确定,在没有浮点运算器的CPU下计算性能好接下来分析下定点数计算的缺点,就是定点数在做乘法 or 除法的时候容易溢出。我们拿乘法为例,假设32 bit的整数,16bit作为小数部分,那么就是 15.16的定点数(最高表示符号,15个bit表示整数部分,16bit表示小数部分),如果两个数相乘,很大的概率就溢出了(计算结果超过32bit)。如2^20与2^21两个定点数相乘为: (2^20 * 2^21)/ (2^16) = 2^41 / 2^16, 计算分子相乘的时候得2^41次,在32bit的int存储中就溢出了。 而2^20与2^21都是合法的定点数。

BEPUphysicsint v1的由来

在github中有一个开源的3D物理引擎的项目,叫做BEPUphysics, 它分成了v1, v2两个重大版本的分支如图1.1-1:


图1.1-1

BEPUphysicsint v1 开源项目是将BEPUphysics v1的代码中的浮点运算用定点数来代替而fork出的一个分支。BEPUphysicsint v1与BEPUphysics v1使用方式上基本都是一致的,只是内部采用的是定点与浮点的区别。在BEPUphysicsint这个项目中,采用定点数,所以精度很有限,无法达到浮点的精度,而且经常容易溢出,所以它有一个要求,物理世界中x, y, z每个轴的范围在1000的范围内。BEPUphysicsint 定点数物理引擎的性能要比BEPUphysics float版本的性能要差4倍左右。以后可能差距没有那么大,但是定点数版本的要比浮点数版本的性能差。如图1.1-2:

图1.1-2 官方关于性能与精度的介绍

如果在实际的项目中发现性能问题,也可以自己实现物理引擎或者基于自己项目实现一个阉割版的高性能物理引擎。

今天的分享就到这里了, 关注我们, 接下来还会继续更新定点3D物理引擎系列教程。

下节预告: 基于BEPUphysicsint的使用详解

本帖子中包含更多资源

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

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-15 21:08 , Processed in 0.090895 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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