Skip to content

脚踏实地

背景:程序化动作没有地面碰撞检测,脚会穿透地面。 过程:每帧检测脚骨 Y 坐标 → 与地面高度比较 → 动态修正腿部 IK → 防止穿透/悬空。


一、穿过去的脚

王逸看着屏幕上的初音未来。

她的右脚在某个动作帧里,穿过了地面网格。脚掌在地板下面,小腿在地板上面。

穿模。MMD 动作不会这样——MMD 的 IK 系统会自动修正。但程序化生成的动作没有 IK。它只有关键帧——骨骼位置、旋转、时间戳。没有碰撞检测,没有 IK 修正。

所以脚的位置只取决于"生成的参数",不取决于"地面在哪"。


二、地面在哪

从脚骨位置向下发射一条射线,检测与地面网格的交点。

typescript
function _queryGroundHeight(position) {
    const ray = new Ray(
        new Vector3(position.x, position.y + 0.1, position.z),
        Vector3.Down(),
        1.0
    );
    const hit = scene.pickWithRay(ray, (mesh) => mesh.name === 'ground');
    return hit?.hasHit ? hit.pickedPoint.y : 0;
}

只检测名字为 ground 的网格。不检测裙子、不检测道具。从脚上方 0.1m 开始,避免和脚自身发生碰撞。

如果场景里没有 ground 网格,返回默认值 0。


三、往上传播

脚低于地面时,计算差值,往上传播到腿部骨骼链。

脚抬高 0.05m,小腿要抬高 0.05m,大腿要抬高 0.05m,盆骨要抬高 0.05m。否则腿部会变形。

差值往上传播,像连锁反应。


四、平滑与跳跃

直接修正骨骼位置会导致抖动——脚会在地面高度附近来回跳。

加一个 Slerp 插值,smoothing 0.3。

跳跃时禁用地面跟随。检测脚骨的 Y 速度——如果大于阈值,说明在向上跳。直到 Y 速度降到阈值以下,才恢复地面跟随。


尾声

角色跳舞时,脚不再穿模了。

脚踏实地。不是成语,是物理。角色的脚现在知道地面在哪,知道什么时候该踩上去,什么时候该跳起来。

角色活着的第二个证明。第一个是呼吸。