这似乎已经解决了,但如果您不习惯使用光线投射和创建自己的物理环境,我有一个更简单的解决方案。
CANNON.js 和 AMMO.js 都是建立在 THREE.js 之上的物理库。它们创建了一个辅助物理环境,您将对象位置与该场景联系起来以模拟物理环境。 CANNON 的文档很简单,我使用的是它,但它自 4 年前发布以来一直没有更新。该回购已被分叉,社区将其更新为大炮。我将在这里留下一个代码 sn-p 以便您查看它是如何工作的
/**
* Floor
*/
const floorShape = new CANNON.Plane()
const floorBody = new CANNON.Body()
floorBody.mass = 0
floorBody.addShape(floorShape)
floorBody.quaternion.setFromAxisAngle(
new CANNON.Vec3(-1,0,0),
Math.PI / 2
)
world.addBody(floorBody)
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(10, 10),
new THREE.MeshStandardMaterial({
color: '#777777',
metalness: 0.3,
roughness: 0.4,
envMap: environmentMapTexture
})
)
floor.receiveShadow = true
floor.rotation.x = - Math.PI * 0.5
scene.add(floor)
// THREE mesh
const mesh = new THREE.Mesh(
sphereGeometry,
sphereMaterial
)
mesh.scale.set(1,1,1)
mesh.castShadow = true
mesh.position.copy({x: 0, y: 3, z: 0})
scene.add(mesh)
// Cannon
const shape = new CANNON.Sphere(1)
const body = new CANNON.Body({
mass: 1,
shape,
material: concretePlasticMaterial
})
body.position.copy({x: 0, y: 3, z: 0})
world.addBody(body)
这会产生一个地板和一个球,但也会在 CANNON.js 环境中创建相同的东西。
const tick = () =>
{
const elapsedTime = clock.getElapsedTime()
const deltaTime = elapsedTime - oldElapsedTime
oldElapsedTime = elapsedTime
// Update Physics World
mesh.position.copy(body.position)
world.step(1/60,deltaTime,3)
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
在此之后,您只需根据物理场景的位置在动画函数中更新 THREE.js 场景的位置。
请查看文档,因为它可能看起来比实际更复杂。使用物理库将是模拟碰撞的最简单方法。另请查看 Physi.js,我从未使用过它,但它应该是一个更友好的库,不需要您创建辅助环境