You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

2D圆形碰撞Resolution问题求助:求实现真实刚体碰撞的正确方案

2D刚体碰撞Resolution的正确实现方案

先说说你之前代码的问题:

  • 第一个代码用持续加力处理碰撞,刚体碰撞是瞬间冲量作用,不是持续受力;而且没处理物体重叠,导致每帧都触发受力,所以物体像弹簧一样来回晃。
  • 第二个代码只改了速度,但没解决重叠问题,物体一直卡在一起,每帧都重复碰撞检测和速度修改,自然会卡顿;另外冲量公式没考虑弹性(恢复系数),质量项的计算也有问题。

刚体碰撞的正确处理需要分两步:先把重叠的物体分开(位置修正),再计算碰撞后的速度变化(冲量),下面是具体实现和原理:

第一步:位置分离(解决物体重叠)

碰撞检测得到的depth是两个物体的重叠深度,必须沿碰撞法线方向把它们分开,不然下一帧还会触发碰撞。按质量反比分配位移更真实——轻的物体被推开更多,重的物体几乎不动:

public static void FixOverlap(RigidBody a, RigidBody b, Vec2 collisionNormal, float depth)
{
    // 计算位移比例,避免质量为0的静态物体出问题
    float totalMass = a.Mass + b.Mass;
    float aMoveRatio = b.Mass / totalMass;
    float bMoveRatio = a.Mass / totalMass;

    // 沿法线方向修正位置,消除重叠
    Vec2 aMove = collisionNormal * depth * aMoveRatio;
    Vec2 bMove = collisionNormal * depth * -bMoveRatio;

    a.Position += aMove;
    b.Position += bMove;
}

第二步:速度冲量计算(模拟刚体碰撞反弹)

基于动量守恒和恢复系数(控制弹性)计算瞬间冲量,直接修改速度,这才是刚体碰撞的正确方式:

  • 恢复系数e:0是完全非弹性碰撞(粘在一起),1是完全弹性碰撞(无能量损失),一般设0.8左右接近真实刚体
  • 先判断物体是否已经在分离,避免重复处理
  • 冲量公式是从动量守恒和碰撞定律推导来的,核心是修正法线方向的相对速度
public static void UpdateCollisionVelocity(RigidBody a, RigidBody b, Vec2 collisionNormal, float restitution = 0.8f)
{
    // 计算两个物体的相对速度在法线方向的分量
    Vec2 relVelocity = b.Velocity - a.Velocity;
    float relVelDotNormal = relVelocity.Dot(collisionNormal);

    // 如果物体已经在往分离的方向动,不用处理
    if (relVelDotNormal > 0)
        return;

    // 计算冲量大小
    float impulseMagnitude = -(1 + restitution) * relVelDotNormal;
    impulseMagnitude /= (1 / a.Mass) + (1 / b.Mass);

    // 把冲量应用到两个物体的速度上
    Vec2 impulse = collisionNormal * impulseMagnitude;
    a.Velocity -= impulse / a.Mass;
    b.Velocity += impulse / b.Mass;
}

完整的碰撞处理函数

把两步结合起来,就是完整的碰撞Resolution逻辑:

public static void OnCollision(RigidBody a, RigidBody b, float depth)
{
    // 计算碰撞法线(从a指向b,必须归一化)
    Vec2 collisionNormal = b.Position - a.Position;
    collisionNormal = VectorMath.Normalize(collisionNormal);

    // 先解决重叠问题
    FixOverlap(a, b, collisionNormal, depth);

    // 再处理速度变化
    UpdateCollisionVelocity(a, b, collisionNormal);
}

核心原理说明

  1. 位置分离是基础:离散碰撞检测的特性决定了,当你检测到碰撞时,物体已经重叠了。如果不分离,会反复触发碰撞处理,导致卡顿或异常运动。按质量反比分配位移,符合现实中“重物体难推动”的规律。
  2. 冲量替代持续力:刚体碰撞是瞬间作用,冲量是力×时间的累积,直接修改速度比每帧加力更符合刚体的“硬”特性,不会出现弹簧一样的软效果。
  3. 恢复系数控制弹性:不同材质的物体碰撞弹性不同,这个参数能让你调整碰撞的真实感,比如橡胶球设0.9,石头设0.5。
  4. 分离判断避免无效处理:如果碰撞后物体已经在分开,就不用再修改速度,避免重复操作导致的异常。

内容的提问来源于stack exchange,提问作者Avi_H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 03:47:02