CannonJS碰撞处理问题:角色盒子与房屋盒子碰撞后异常滑动
解决CannonJS角色碰撞后异常滑动的问题
1. 先把房屋对象(Box2)设为静态体
CannonJS里哪怕质量极大的动态体,也会被外力推动,必须将Box2设为静态体才能完全固定:
const box2Body = new CANNON.Body({ mass: 0, // 质量为0是标记静态体的核心 shape: new CANNON.Box(new CANNON.Vec3(1, 1, 1)), position: new CANNON.Vec3(0, 0, 0) }); world.addBody(box2Body);
2. 修正角色(Box1)的移动逻辑
如果是直接设置velocity来控制角色移动,会绕过物理引擎的力计算逻辑,摩擦参数根本无法生效。必须改用**施加力(force)或冲量(impulse)**的方式:
// 方向键施加力示例 document.addEventListener('keydown', (e) => { const moveForce = new CANNON.Vec3(0, 0, 0); const baseSpeed = 6; switch(e.key) { case 'ArrowLeft': moveForce.x = -baseSpeed; break; case 'ArrowRight': moveForce.x = baseSpeed; break; case 'ArrowUp': moveForce.z = -baseSpeed; break; case 'ArrowDown': moveForce.z = baseSpeed; break; } box1Body.applyForce(moveForce, box1Body.position); });
如果是需要瞬间响应的移动(比如冲刺),可以用冲量替代:
box1Body.applyImpulse(moveForce, box1Body.position);
3. 配置接触材质的摩擦与恢复系数
单独设置单个物体的参数可能不生效,需要给两个物体设置共享的接触材质,强制覆盖碰撞时的物理表现:
// 创建两个物体的材质 const playerMat = new CANNON.Material(); const houseMat = new CANNON.Material(); // 创建接触材质,明确碰撞规则 const contactMat = new CANNON.ContactMaterial( playerMat, houseMat, { friction: 1, // 最大摩擦系数,完全阻止滑动 restitution: 0 // 恢复系数设为0,碰撞后完全不反弹 } ); // 绑定材质到物体并添加到物理世界 box1Body.material = playerMat; box2Body.material = houseMat; world.addContactMaterial(contactMat);
4. 启用物体睡眠机制
开启睡眠可以让静止的角色停止物理计算,避免微小残留力导致的滑动:
box1Body.sleepSpeedLimit = 0.1; // 速度低于该值时触发睡眠检测 box1Body.sleepTimeLimit = 0.3; // 持续低速超过该时间进入睡眠状态
5. 检查物理世界全局参数
确保物理世界的默认配置没有拖后腿:
const world = new CANNON.World(); world.gravity.set(0, -9.82, 0); world.defaultContactMaterial.friction = 1; // 全局默认摩擦 world.defaultContactMaterial.restitution = 0; // 全局默认无反弹
内容的提问来源于stack exchange,提问作者Gaurav Sharma
相关产品推荐
相关产品推荐

