关于地面-bug#

Data: 2025-12-25 04:55:05

先是强制回到天上

// 1. 强制重置位置 (回到安全点)
k.mainVPlayer.body.position.set(0, 100, 0); 

// 2. 归零速度 (非常重要,否则下一帧继续炸)
k.mainVPlayer.body.velocity.set(0, 0, 0);
k.mainVPlayer.body.angularVelocity.set(0, 0, 0);
k.mainVPlayer.body.force.set(0, 0, 0);
k.mainVPlayer.body.torque.set(0, 0, 0);

// 3. 修复旋转
k.mainVPlayer.body.quaternion.set(0, 0, 0, 1);

然后移除原来的那个,重新添加一遍:

// 1. 获取物理世界引用 (通过主角或者旧地面都能拿到)
var world = k.mainVPlayer.body.world || k.groundObj.body.world;

// 2. 备份旧地面的碰撞掩码 (非常重要,否则新地面接不住主角)
var oldGroup = k.groundObj.body.collisionFilterGroup;
var oldMask = k.groundObj.body.collisionFilterMask;
var oldMaterial = k.groundObj.body.material;

// 3. 从世界中移除旧地面
world.removeBody(k.groundObj.body);

console.log("旧地面已移除。碰撞组:", oldGroup, "碰撞掩码:", oldMask);


// 1. 创建新的 Box 形状 (参数是半长宽高)
// 我们先做一个 100x100 的安全平台,厚度保持 6 (半高 3)
var newSafeShape = new CANNON.Box(new CANNON.Vec3(50, 3, 50)); 

// 2. 创建新的物理体
var newGroundBody = new CANNON.Body({
    mass: 0, // 静态
    position: new CANNON.Vec3(0, -2.5, 0), // 保持原位置 Y
    shape: newSafeShape,
    material: oldMaterial // 沿用旧材质
});

// 3. 恢复碰撞分组 (关键!)
newGroundBody.collisionFilterGroup = oldGroup;
newGroundBody.collisionFilterMask = oldMask;

// 4. 添加到世界
world.addBody(newGroundBody);

// 5. 将新体重新挂载到 k 对象,防止报错
k.groundObj.body = newGroundBody;

console.log("新建的安全地面已生成 (100x100)。");

(并非这个!)目前的原因分析,可能是 我的拼写错误!

cannonDefaultContactMaterial。

现在暂时的恢复代码为(我也不知道是否有效):

(function() {
    console.clear();
    console.group("🛡️ 物理引擎终极修复程序");

    const world = k.world;
    const player = k.mainVPlayer.body;

    // ==========================================
    // 1. 环境清洗:彻底消灭所有重叠/幽灵地面
    // ==========================================
    console.log("🧹 正在清理所有疑似地面的物体...");
    const bodiesToRemove = [];
    world.bodies.forEach(b => {
        // 逻辑:只要是静止的(mass=0) 且不是主角 且位置在 Y=0 附近
        // 统统视为“嫌疑地面”进行删除
        if (b.mass === 0 && b !== player && Math.abs(b.position.y) < 5) {
            bodiesToRemove.push(b);
        }
    });
    bodiesToRemove.forEach(b => world.removeBody(b));
    console.log(`✅ 已移除 ${bodiesToRemove.length} 个旧地面/残留物体。`);

    // ==========================================
    // 2. 核心修复:切换最稳健的检测算法
    // ==========================================
    // NaiveBroadphase 虽然性能普通,但在直接操作 position 时最不容易出错
    if (world.broadphase.constructor.name !== "NaiveBroadphase") {
        world.broadphase = new CANNON.NaiveBroadphase();
        console.log("✅ Broadphase 已切换为 Naive 模式 (防穿透/防NaN)。");
    }

    // ==========================================
    // 3. 材质排雷:修复潜在的 friction: 100 问题
    // ==========================================
    // 无论之前怎么设置,强制把世界默认材质改回安全值
    world.defaultContactMaterial.friction = 0.3;
    world.defaultContactMaterial.restitution = 0.0;
    console.log("✅ 世界默认材质已修正 (Friction: 0.3, Restitution: 0.0)。");

    // 创建隔离材质(双重保险)
    const matPlayer = new CANNON.Material("safe_player");
    const matGround = new CANNON.Material("safe_ground");
    const matContact = new CANNON.ContactMaterial(matPlayer, matGround, {
        friction: 0.3,       // 标准摩擦
        restitution: 0.0,    // 无弹力 (防止震荡)
        contactEquationStiffness: 1e8, // 硬度强
        contactEquationRelaxation: 3
    });
    world.addContactMaterial(matContact);

    // ==========================================
    // 4. 重建地面:唯一的、纯净的 Plane
    // ==========================================
    const groundBody = new CANNON.Body({
        mass: 0, // 静态
        position: new CANNON.Vec3(0, 0.5, 0), // 表面高度
        shape: new CANNON.Plane(),
        material: matGround
    });
    // 旋转 Plane 让其面朝上 (Y+)
    groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2);
    // 碰撞掩码:跟谁都撞
    groundBody.collisionFilterGroup = 1;
    groundBody.collisionFilterMask = -1; 
    
    world.addBody(groundBody);
    
    // 更新全局引用
    k.groundObj = { 
        name: 'SafePlane', 
        body: groundBody,
        // 假参数,兼容旧逻辑
        width: 99999, depth: 99999, height: 0 
    };
    console.log("✅ 唯一标准 Plane 地面已创建 (Y=0.5)。");

    // ==========================================
    // 5. 主角归位与净化
    // ==========================================
    // 赋予新材质
    player.material = matPlayer;
    // 碰撞掩码:跟谁都撞
    player.collisionFilterGroup = 1;
    player.collisionFilterMask = -1;
    
    // 重置物理状态 (清除 NaN 残留)
    player.velocity.set(0, 0, 0);
    player.angularVelocity.set(0, 0, 0);
    player.force.set(0, 0, 0);
    player.torque.set(0, 0, 0);
    player.quaternion.set(0, 0, 0, 1); // 扶正

    // 放到安全位置 (稍高一点自然下落)
    player.position.set(0, 1.0, 0);
    player.wakeUp();

    console.log("✅ 主角已重置并投放。");
    console.groupEnd();
    
    console.log("%c🎉 物理世界修复完毕!现在您可以安全测试了。", "color: green; font-weight: bold; font-size: 14px;");
})();

- end -#

© 2025 –   海牧羽工厂 HMY Factory