物理系统项目设置

Author: Charley

LayaAir 引擎同时支持 2D 与 3D 物理系统,在默认实现中,引擎已适配主流物理引擎方案:

  • 2D 物理:Box2D
  • 3D 物理:Bullet 与 PhysX

此外,LayaAir 也支持 自定义物理引擎的接入,以满足特定项目或行业场景的需求。

在项目设置中的 物理系统 配置项中,提供了 2D 与 3D 物理的全局设置入口,用于统一管理物理相关全局参数。

1、2D物理

1.1 2D物理碰撞组定义

2D 物理碰撞组定义用于对 物理碰撞分组 进行可视化与语义化管理,是对底层位掩码(Bit Mask)机制的一种易用封装。

在不使用碰撞组定义时,通常需要直接通过代码操作碰撞掩码。示例代码如下:

//直接指定xxx碰撞体 可以与  某个碰撞类别(组) 发生碰撞
xxx.mask = 1 << 2;  //只与分组ID为2的(值为4)分成发生碰撞

//通过 按位或,指定xxx碰撞体 可以与 多个碰撞类别(组) 发生碰撞
xxx.mask = (1 << 1) | (1 << 2) | (1 << 5); //只与分组ID为1、2、5的进行碰撞

//通过按位取反的方式,排除指定的碰撞分组
xxx.mask = ~((1 << 3) | (1 << 6)); // 不与分组3、6进行碰撞,除3与6组之外都可以发生碰撞
//-1 在位运算中表示所有位为 1(32 位掩码),通过异或的方式将指定分组位清零
xxx.mask = -1 ^ (1 << 3) ^ (1 << 6)  //不与分组3、6进行碰撞,除3与6组之外都可以发生碰撞

这种方式虽然灵活,但在 IDE 的可视化配置环境中并不直观,也不利于项目维护。

为此,LayaAir 提供了 2D 物理碰撞组定义 功能,将基于数字与位运算的分组方式,转换为 具名标签形式,显著提升了可读性与易用性。

如图 1-1 所示,开发者可以在碰撞组定义中添加两个分组,例如 rolenpc,并为角色对象的刚体碰撞形状设置:

碰撞类别(category)role

碰撞掩码(mask)npc

(图1-1)

该配置表示:role 类型的碰撞体可以与 npc 类型的碰撞体发生碰撞。当另一个对象的碰撞类别设置为 npc 时,二者在物理世界中即可正常产生碰撞关系。

整个配置过程直观清晰,避免了直接操作位掩码带来的理解成本。

在操作上:

  • 点击 “+” 可新增一个碰撞组定义;
  • 点击 ID 前的删除图标,可移除对应的碰撞组定义。

1.2 默认配置与自定义2D物理配置

默认配置 中,引擎提供了一套全局的 2D 物理参数设置。由于默认配置与自定义配置所包含的具体参数项是完全一致的,相关参数的说明将在后续小节中统一介绍。

本小节重点介绍 自定义 2D 物理配置的启用与使用流程

在 2D 物理设置界面底部,提供了 “添加 2D 物理配置” 入口,如图 1-2 所示。

(图1-2)

点击 “+” 后,可创建一个自定义配置分组。该分组下将拥有一套 独立的 2D 物理全局参数,并可在场景的 2D 根节点(Scene2D)中进行选择与应用,如图 1-3 所示。

(图1-3)

通过这种方式,开发者可以在 不同场景中使用不同的物理全局配置,从而满足多关卡、多玩法或不同物理规则并存的需求,整体灵活性显著提升。

1.3 刚体休眠功能开关 allowSleeping

开启该选项,允许刚体属性决定是否休眠。关闭开选项,所有刚体均无法设置休眠。为刚体设置启用休眠可节省性能开销,但影响运动或受到外力时的灵敏度,是否启用休眠取决于具体需求和对性能的权衡。

1.4 重力加速度 gravity

重力是一种模拟物体在地球表面受到的引力,重力受两个参数影响一个是质量另一个是加速度,此处设置的是重力加速度参数,该参数的XY会影响重力的方向,X表示水平方向的重力,Y表示垂直方向的重力,通常只使用垂直方向的重力设置。在地球表面,重力加速度值为9.8,对应于现实世界中的9.8米/秒²(m/s²)。

1.5 速度迭代次数 velocityIterations

速度迭代次数(velocityIterations 是物理世界每次更新时的一个关键参数,用于控制速度约束求解阶段的迭代次数。该参数直接影响碰撞响应、摩擦效果以及关节系统的稳定性,是物理模拟精度与运行性能之间的重要调节因素。

Box2D 采用基于 顺序冲量法(Sequential Impulse) 的迭代数值方法来求解复杂的物理约束系统。由于场景中往往同时存在多个碰撞接触点、关节约束以及不同质量和惯性的物体,物理系统在单次计算中无法得到精确解。因此,引擎通过多次迭代逐步传播和修正冲量,逼近一个在当前时间步内相对稳定且合理的解,从而在保证实时性能的前提下获得可信的物理效果。

在每一个物理时间步中,Box2D 的约束求解过程主要分为两个阶段。第一阶段是速度约束求解阶段,用于计算和修正物体在碰撞、摩擦以及关节作用下的线速度和角速度;第二阶段是位置约束求解阶段,用于修正由于数值误差导致的物体重叠和位置偏差。速度迭代次数(velocityIterations仅作用于第一阶段,用于决定速度约束求解的重复执行次数。

速度约束求解阶段的核心目标并非简单计算速度数值,而是通过多次迭代,使系统中各个接触点和关节产生的冲量逐步达到一致和平衡。随着速度迭代次数的增加,碰撞冲量和摩擦力的分配会更加稳定,物体之间的相互作用也会更加接近真实物理行为。这通常表现为更平滑的碰撞响应、更稳定的物体堆叠,以及关节系统抖动的明显减少。

需要注意的是,速度迭代次数对穿透问题的改善属于间接影响。它通过提高速度解的稳定性,降低下一帧继续产生不合理穿透的概率,但并不直接负责几何层面的重叠修正。真正用于修复物体重叠和位置误差的是位置约束求解阶段,即位置迭代次数(positionIterations。因此,在出现严重穿透或不稳定问题时,应综合考虑时间步长设置、物体质量比例以及位置迭代次数,而不应仅依赖提高速度迭代次数。

在实际项目中,Box2D 官方及业界普遍推荐将速度迭代次数(velocityIterations设置为 8,该值在大多数游戏和交互场景中能够在稳定性和性能之间取得良好平衡。在性能受限的平台(如移动设备)或物理复杂度较低的场景中,可适当降低至 6 以减少 CPU 开销;而在对物理精度和稳定性要求较高的场景(例如物理解谜类游戏或包含复杂关节结构的系统)中,可提高至 10–12 以获得更可靠的物理表现。

速度迭代次数(velocityIterations是一个用于调节物理模拟质量的工程参数,并不存在“数值越大越好”的情况。当迭代次数超过一定阈值后,计算成本会持续增加,而物理效果的提升则逐渐减弱。在实际使用时,应结合具体玩法需求、目标设备性能以及整体物理参数配置,通过测试和调优选择最合适的取值范围。

1.6 位置迭代次数 positionIterations

位置迭代次数(positionIterations 是 2D 物理系统在每个模拟步(Step)中,用于控制位置约束求解阶段迭代次数的关键参数。该参数决定了物理引擎在单个时间步内,对碰撞、堆叠及关节约束所产生的位置误差进行修正的强度与程度。

它要解决的核心问题是:当刚体发生碰撞、堆叠、被关节连接时,系统不仅要计算“速度该怎么变”(速度约束),还要把已经产生的位置误差纠正回来(例如轻微穿透、堆叠下陷、关节被拉长/抖动)。positionIterations 越高,通常越能把这些“位置层面”的误差在单步内收敛得更干净,表现为更少的穿透/下陷、更稳定的堆叠、更不易抖动或拉伸的关节;代价是每步求解更耗 CPU。

理解与使用时不要把它当成孤立旋钮。引擎里时间步 delta 和 subStep 都会显著影响稳定性:当帧率较低或波动导致单步位移变大时,穿透与抖动更容易出现,这时提高 subStep 往往比单纯把 positionIterations 拉很高更有效,再配合适度提高 positionIterations 来收敛位置误差;而 速度迭代次数(velocityIterations更偏向碰撞响应、摩擦与关节速度约束的收敛,两者需要配合调。

应用场景上,默认值 3 更偏“性能与效果的平衡”,适合轻量碰撞与低速移动。如果你有明显的箱子堆叠下陷、链条/车辆悬挂等关节结构抖动或拉伸、高速运动接触后重叠明显等稳定性问题,可以采用小幅递增的方式(例如 4→6→8)观察改善幅度,同时关注性能变化;若问题主要出现在掉帧时,优先检查是否需要增加 subStep 或改善帧时间稳定性,再决定是否提高本参数。

1.7 长度单位转换比率 pixelRatio

长度单位转换比率 (pixelRatio)用来定义渲染像素(px)与 2D 物理世界长度单位(Box2D 的“米”)之间的换算比例。默认值为 50,含义是:物理世界 1 个长度单位 ≈ 渲染 50 像素。从开发者视角,你在场景里看到的精灵位置、碰撞盒宽高、关节锚点等通常以“像素”为直觉单位,而物理引擎内部更适合在“米”这样数量级稳定的单位里计算;pixelRatio 就是把两者对齐的桥梁。

在引擎源码里,这个比例会被 Physics2DWorldManager 读取并缓存为 _pixelRatio 与 _RePixelRatio=1/_pixelRatio,用于坐标/长度的双向换算;同时它也会被写入 box2DWorld._pixelRatio,供 WASM 物理工厂在创建形状、关节、刚体等时统一缩放。换算关系可以直观理解为:物理值(米) = 像素值 / pixelRatio,像素值 = 物理值(米) * pixelRatio

1.7.1 它会影响哪些内容

pixelRatio 会影响“所有需要把像素量变成物理量”的地方:刚体的位置与线速度、形状尺寸(盒/圆/多边形顶点)、关节锚点与关节的长度/移动范围、射线/查询输入与输出(命中点会再换回像素),以及调试绘制时从物理坐标回到屏幕坐标的显示位置。源码中 physics2DwasmFactory.convertLayaValueToPhysics() 直接用 1/world._pixelRatio 做缩放,这意味着只要你的输入数据是以像素为单位,最终都会在进入 Box2D 前按该比例转换。

与之相伴的一个关键点是重力:引擎把重力值直接作为 Box2D 的重力向量使用(默认 9.8,按“米/秒²”理解)。当 pixelRatio=50 时,9.8 m/s² 在屏幕上的直觉加速度大约等价于 9.8×50=490 px/s²;如果你改了 pixelRatio,你看到的“下落速度的像素表现”也会随之线性变化(因为像素与米的映射变了)。

1.7.2 典型应用场景与推荐用法

大多数 2D 游戏/交互应用中,默认 pixelRatio=50 往往是一个好起点:例如 50~100px 的角色高度可对应 1~2m 的物理高度,既符合直觉也比较稳定。如果你项目整体美术比例更偏大(例如角色 300px 高)或偏小(例如像素风 16px/32px),你可以通过调整 pixelRatio 让“角色高度换算到米”仍落在合理范围内,而不是让角色在物理世界里变成几十米的巨人或几厘米的小点。

当你遇到“需要更稳定”的场景(比如密集堆叠、复杂关节链、较高速运动)时,优先不要用 pixelRatio 去“硬救稳定性”,因为它是尺度定义而不是求解器精度参数。更合适的方式是配合 subStep、velocityIterations、positionIterations 等求解参数来提升稳定性;pixelRatio 只应在你确认“整体尺度不合理”时再调整,否则会牵一发而动全身(所有长度/速度/关节参数的物理意义都会变)。

1.8 是否开启 2D 物理绘制 debugDraw

当 2D 节点添加了物理属性(如刚体、碰撞体、关节等)后,开启 2D 物理绘制(debugDraw 可在场景中实时显示物理系统的调试信息,包括碰撞形状、关节连接关系及相关辅助可视元素。

该功能主要用于物理调试与参数校准,能够直观反映物理数据在引擎中的实际计算结果,有助于快速定位碰撞异常、关节配置错误及稳定性问题。通常仅建议在开发和调试阶段启用。

1.8.1 绘制形状 drawShape

是否绘制物理碰撞形状,默认为开启。

开启后,场景中会显示刚体所使用的碰撞盒、圆形、多边形等实际参与物理计算的形状,如图 1-4 所示。通过该可视化信息,可以直观确认碰撞体的大小、位置与旋转是否与美术节点对齐,常用于排查“看起来碰到了但没有触发碰撞”或“碰撞范围异常”等问题。

(图 1-4)

1.8.2 绘制关节 drawJoint

是否绘制物理关节,默认为开启。

开启后,会以连线或辅助图形的形式显示关节两端的连接关系和约束位置,如图 1-5 所示,便于观察关节是否正确连接到目标刚体,以及在受力或运动过程中是否出现异常拉伸、抖动或断裂等情况。该选项在调试链条、车辆、摆锤等关节结构时尤为有用。

(图 1-5)

1.8.3 绘制包围盒 drawAABB

是否绘制物理对象的轴对齐包围盒(AABB),默认为关闭。

开启后,将显示用于宽相位碰撞检测的包围盒范围,如图 1-6 所示,有助于分析物体在物理系统中的参与检测区域。当出现性能问题、异常触发碰撞或怀疑碰撞检测范围过大时,可通过该选项辅助定位原因。

(图 1-6)

1.8.4 绘制质心 drawCenterOfMass

是否绘制刚体的质心位置,默认为关闭。

开启后,将在刚体上显示其质量中心点,如图 1-7 所示。该信息对于分析物体受力、旋转行为和稳定性非常有帮助,尤其在刚体形状不对称、质量分布异常或旋转结果不符合预期时,可用于判断是否需要调整碰撞形状或质量参数。

(图 1-7)

2、3D物理

2.1 固定模拟步长fixedTimeStep

固定模拟步长(fixedTimeStep) 用于定义物理世界中单次物理模拟步(Step)所对应的时间长度(单位:秒)。物理系统并不直接使用渲染帧的 deltaTime 进行求解,而是始终以该固定时间片推进模拟,从而降低帧率波动对物理结果的影响。

在引擎实现中,每帧会累积真实经过的时间,并按 fixedTimeStep 切分为若干个完整的物理步执行。当帧率较高时,可能一帧内不需要执行物理步;当帧率较低时,则可能在单帧内执行多个物理步以“追赶”真实时间。因此,fixedTimeStep 实际决定的是物理模拟的时间精度与更新频率

fixedTimeStep 越小,单位时间内执行的物理步越多,碰撞、关节和堆叠的稳定性通常更好,但 CPU 开销也会相应增加;反之,步长越大,性能压力更小,但更容易出现高速穿透、关节变软或堆叠不稳定等问题。

一般建议从 1/60 秒作为起点,根据项目对稳定性与性能的需求进行调整。

2.2 单帧最大追帧步数(maxSubSteps)

单帧最大追帧步数(maxSubSteps) 用于限制在单个渲染帧内,最多允许执行多少个完整的物理模拟步。该参数的主要作用是防止在严重掉帧时,物理系统为了追赶时间而在一帧内执行过多步数,导致 CPU 峰值过高、进一步加剧卡顿。

当某一帧的 deltaTime 较大时,物理系统理论上需要执行更多固定步才能追上真实时间;maxSubSteps 会对这一数量进行上限截断。若超过上限,多余的时间将被延后处理,表现为物理世界在掉帧期间可能出现轻微“变慢”,但可以有效避免物理计算拖垮主线程。

该参数本质上是稳定性与性能之间的保护阀。数值越大,掉帧时物理结果越接近真实时间,但单帧负载越高;数值越小,则更有利于限制性能波动。常见配置范围为 1~4,并应与 fixedTimeStep 结合考虑。

2.3 连续碰撞检测全局开关(enableCCD

连续碰撞检测全局开关(enableCCD 用于指示物理系统是否启用连续碰撞检测(CCD,Continuous Collision Detection)相关机制,以降低高速、小体积物体在离散碰撞检测(Discrete)条件下发生穿透的概率。

该参数表达的是全局层面的启用意图或默认策略,当该选项关闭时,物理系统不会启用任何 CCD 相关处理;当该选项开启时,表示允许物理系统在满足条件的情况下使用 CCD,但并不保证所有刚体都会实际采用连续碰撞检测。是否真正生效,还需结合刚体自身的碰撞检测模式,以及 CCD 相关阈值参数(如位移阈值、扫掠半径)共同决定。

2.4 CCD 启动位移阈值(ccdThreshold)

CCD 启动位移阈值(ccdThreshold) 用于定义:当刚体在单个物理模拟步内的位移距离超过该阈值时,才会触发连续碰撞检测逻辑。其目的是避免所有物体在任何情况下都使用成本更高的 CCD 计算。

该参数的物理直觉可以理解为:

单步位移约等于 速度 × fixedTimeStep。当这个位移已经接近或超过物体的有效厚度时,才存在明显的穿透风险,才有必要启用 CCD。

合理的设置应与场景尺度、物体尺寸、速度上限以及 fixedTimeStep 保持一致。过小的阈值会导致 CCD 频繁触发,增加计算成本;过大的阈值则可能失去防穿透的意义。

2.5 CCD 扫掠球半径(ccdSphereRadius)

CCD 扫掠球半径(ccdSphereRadius) 用于定义连续碰撞检测中所使用的扫掠体近似半径。在 CCD 计算中,物体在一个物理步内的运动轨迹通常会被近似为一个“沿运动方向扫掠的球体”,该半径决定了扫掠体的保守程度。

该参数并不表示物体真实的几何形状,而是一种用于提高检测可靠性的近似值。半径过小,扫掠体过“细”,仍可能发生漏检;半径过大,则会使物体在物理上显得更“粗”,可能提前发生碰撞或引入不必要的接触。

一般建议根据物体的最小厚度或有效半径进行设置,并通过实际测试在“防穿透能力”和“物理保守性”之间取得平衡。

2.6 3D物理碰撞组定义

3D 物理碰撞组定义与 1.1 小节介绍的 2D 物理碰撞组定义一样,也是对 物理碰撞分组 进行可视化与语义化管理,是对底层位掩码(Bit Mask)机制的一种易用封装。

区别仅是该处定义的碰撞组名称用于 3D 物理组件的碰撞形状,如图 2-1 所示。

(图 2-1)

Copyright ©Layabox 2026 all right reserved,powered by LayaAir Engine更新时间: 2026-01-22 16:35:36

results matching ""

    No results matching ""