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

如何在Three.js中让BoxGeometry墙体实现碰撞阻挡物体穿透

Three.js 3D迷宫碰撞检测解决方案

问题概述

使用Three.js构建3D迷宫,通过BoxGeometry创建墙体,需要实现控制的car物体无法穿越墙体的碰撞效果,尝试过RayCaster和Cannon.js但未成功。


方案一:基于RayCaster的射线碰撞检测

你之前的问题在于直接修改car的位置,没有在移动前进行碰撞检测。以下是修正后的实现:

步骤1:准备墙体集合

先将所有墙体存入数组,方便统一检测:

const walls = [box1, box2, box3, box4];
const rayCaster = new THREE.Raycaster();
// 假设car的尺寸是x:2, z:4(根据你的car模型实际尺寸调整)
const carHalfSize = new THREE.Vector3(1, 0, 2);

步骤2:修改键盘事件,加入碰撞检测

替换原有的document.onkeydown事件,在移动前检测是否会碰撞墙体:

document.onkeydown = function (e) {
    let moveDir = new THREE.Vector3();
    // 确定移动方向,修正旋转角度为标准弧度
    switch(e.keyCode) {
        case 87: // W
            moveDir.set(0, 0, 1);
            car.rotation.y = 0;
            break;
        case 83: // S
            moveDir.set(0, 0, -1);
            car.rotation.y = Math.PI;
            break;
        case 65: // A
            moveDir.set(1, 0, 0);
            car.rotation.y = -Math.PI/2;
            break;
        case 68: // D
            moveDir.set(-1, 0, 0);
            car.rotation.y = Math.PI/2;
            break;
        default: return;
    }

    // 计算car的碰撞检测起点(从car边缘向外偏移,避免误判)
    const startPos = car.position.clone().add(moveDir.multiply(carHalfSize));
    // 设置射线:起点 + 移动方向,长度为移动步长+余量
    rayCaster.set(startPos, moveDir.normalize());
    // 检测与墙体的碰撞
    const intersects = rayCaster.intersectObjects(walls);

    // 无碰撞或碰撞距离大于步长时,执行移动
    if (intersects.length === 0 || intersects[0].distance > 1.1) {
        car.position.add(moveDir.multiplyScalar(1));
    }
};

注意:必须根据car模型的实际尺寸调整carHalfSize,确保射线从car的边缘发出,避免car还未接触墙体就被阻挡。


方案二:基于Cannon.js的物理引擎碰撞(更稳定)

物理引擎能精准处理复杂碰撞,你之前的失败大概率是没正确同步Three.js与Cannon的物体状态。以下是完整实现:

步骤1:初始化Cannon物理世界

// 引入Cannon.js后创建物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.8, 0); // 重力向下
world.broadphase = new CANNON.SAPBroadphase(world); // 优化碰撞检测性能
world.defaultContactMaterial.restitution = 0; // 关闭弹性,避免碰撞后反弹

步骤2:为墙体、地面和car创建物理体

// 辅助函数:同步Three.js网格到Cannon刚体
function createPhysicsBody(mesh, type = CANNON.Body.STATIC) {
    const geoParams = mesh.geometry.parameters;
    const shape = new CANNON.Box(new CANNON.Vec3(
        geoParams.width/2 || geoParams.x/2,
        geoParams.height/2 || geoParams.y/2,
        geoParams.depth/2 || geoParams.z/2
    ));
    const body = new CANNON.Body({
        mass: type === CANNON.Body.DYNAMIC ? 1 : 0, // 静态物体质量设为0
        shape: shape,
        type: type
    });
    body.position.copy(mesh.position);
    body.quaternion.copy(mesh.quaternion);
    world.addBody(body);
    return body;
}

// 为墙体创建静态物理体
const wallBodies = walls.map(wall => createPhysicsBody(wall));
// 为地面创建静态物理体
const planeBody = createPhysicsBody(plane);
// 为car创建动态物理体
const carBody = createPhysicsBody(car, CANNON.Body.DYNAMIC);
carBody.fixedRotation = true; // 禁止car翻滚
carBody.linearDamping = 0.5; // 增加阻力,避免car滑动不止

步骤3:动画循环中同步物理体与Three.js物体

在你的渲染循环中加入物理世界更新与状态同步:

function animate() {
    requestAnimationFrame(animate);
    // 更新物理世界,固定步长1/60
    world.step(1/60);
    // 同步car的位置与旋转
    car.position.copy(carBody.position);
    car.quaternion.copy(carBody.quaternion);
    // 执行渲染
    renderer.render(scene, camera);
}
animate();

步骤4:修改键盘控制,通过物理力移动car

替换原有的键盘事件,改为给物理体施加力:

const moveForce = 50; // 移动力度,根据需求调整
document.onkeydown = function (e) {
    switch(e.keyCode) {
        case 87: // W
            carBody.applyLocalForce(new CANNON.Vec3(0, 0, moveForce), new CANNON.Vec3(0,0,0));
            car.rotation.y = 0;
            break;
        case 83: // S
            carBody.applyLocalForce(new CANNON.Vec3(0, 0, -moveForce), new CANNON.Vec3(0,0,0));
            car.rotation.y = Math.PI;
            break;
        case 65: // A
            carBody.applyLocalForce(new CANNON.Vec3(moveForce, 0, 0), new CANNON.Vec3(0,0,0));
            car.rotation.y = -Math.PI/2;
            break;
        case 68: // D
            carBody.applyLocalForce(new CANNON.Vec3(-moveForce, 0, 0), new CANNON.Vec3(0,0,0));
            car.rotation.y = Math.PI/2;
            break;
    }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 04:45:32