Appearance
脚踏实地
背景:程序化动作没有地面碰撞检测,脚会穿透地面。 过程:每帧检测脚骨 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 速度降到阈值以下,才恢复地面跟随。
尾声
角色跳舞时,脚不再穿模了。
脚踏实地。不是成语,是物理。角色的脚现在知道地面在哪,知道什么时候该踩上去,什么时候该跳起来。
角色活着的第二个证明。第一个是呼吸。