休眠
当一个物体在小范围内移动时,物理引擎会认为它是静止的,此时物体就会进入休眠状态,不再受到物理引擎的影响。休眠状态可以减少物理引擎的计算量,提高性能。
- 设置物理世界休眠
js
const world = new CANNON.World();
world.allowSleep = true;
allowSleep: 是否允许休眠,默认为 false。
- 设置物体休眠
js
const boxBody = new CANNON.Body({
shape: new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)),
position: new CANNON.Vec3(-2, 5, 0),
mass: 1,
material: boxMaterialCon,
collisionFilterGroup: GROUP1,
collisionFilterMask: GROUP1 | GROUP2 | GROUP3 | GROUP4,
});
boxBody.allowSleep = true; // 允许休眠
boxBody.sleepSpeedLimit = 0.5; //速度小于0.5时休眠
boxBody.sleepTimeLimit = 1; // 休眠时间超过1秒
world.addBody(boxBody);
sleepSpeedLimit: 速度小于该值时,物体进入休眠状态。
sleepTimeLimit: 休眠时间超过该值时,物体从休眠状态恢复。
休眠事件
当物体从运动状态到休眠状态,会触发很多事件,我们可以监听这些事件,做一些操作。
- 监听物体休眠事件
js
boxBody.addEventListener("sleep", () => {
console.log("休眠");
});
- 监听即将休眠事件
js
boxBody.addEventListener("sleepy", () => {
console.log("即将休眠");
});
物体组合
将多个物体组合成一个物体,可以减少物理引擎的计算量,提高性能。
js
// 创建一个物理组合体
const capsuleBody = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(0, 4, 0),
material: boxMaterialCon,
collisionFilterGroup: GROUP2,
collisionFilterMask: GROUP1 | GROUP2 | GROUP3,
});
//创建球体
const sphereShape = new CANNON.Sphere(0.5);
//创建圆柱体
const cylinderShape = new CANNON.Cylinder(0.5, 0.5, 1.5, 20);
//创建胶囊体
capsuleBody.addShape(sphereShape, new CANNON.Vec3(0, 0.75, 0));
capsuleBody.addShape(cylinderShape, new CANNON.Vec3(0, 0, 0));
capsuleBody.addShape(sphereShape, new CANNON.Vec3(0, -0.75, 0));
capsuleBody.velocity.set(2, 0, 0); //设置速度
world.addBody(capsuleBody);
//创建胶囊体网格
const capsuleGeometry = new THREE.CylinderGeometry(0.5, 0.5, 1.5, 20);
const capsuleMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const capsule = new THREE.Mesh(capsuleGeometry, capsuleMaterial);
capsule.position.copy(capsuleBody.position);
capsule.quaternion.copy(capsuleBody.quaternion);
scene.add(capsule);
//创建球体网格
const sphereGeometry = new THREE.SphereGeometry(0.5, 20, 20);
const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(0, 0.75, 0);
capsule.add(sphere);
const sphere2 = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere2.position.set(0, -0.75, 0);
capsule.add(sphere2);
addShape: 添加形状,第一个参数为形状,第二个参数为形状相对于物体的位置。
施加力
给物体施加力,可以让物体运动。
applyForce
js
//创建物理球
const sphereBody = new CANNON.Body({
mass: 1,
shape: new CANNON.Sphere(0.5),
position: new CANNON.Vec3(0, 5, 0),
material: boxMaterialCon,
collisionFilterGroup: GROUP2,
collisionFilterMask: GROUP1 | GROUP2 | GROUP3,
});
world.addBody(sphereBody);
//创建3D球
const sphereGeometry = new THREE.SphereGeometry(0.5, 8, 8);
const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphere);
//监听鼠标点击事件
window.addEventListener("click", () => {
console.log("点击了:", sphereBody.position);
sphereBody.applyForce(new CANNON.Vec3(10, 0, 0), sphereBody.position);
});
applyForce: 施加力,第一个参数为力的大小,第二个参数为力的方向。
applyLocalForce
js
sphereBody.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), Math.PI / 2); //设置旋转
window.addEventListener("click", () => {
console.log("点击了:", sphereBody.position);
sphereBody.applyLocalForce(new CANNON.Vec3(10, 0, 0), new CANNON.Vec3(0, -0.5, 0));
});
applyLocalForce: 施加局部力,第一个参数为力的大小,第二个参数为力的方向。
这个是相对物体自身的力,物体自身旋转后,力的方向也会跟着旋转。就会出现向后滚动的效果。
applyImpulse
js
sphereBody.applyImpulse(new CANNON.Vec3(10, 0, 0), sphereBody.position);
applyImpulse: 施加冲量,第一个参数为冲量的大小,第二个参数为冲量的方向。
冲量是力的积累,力的作用时间越长,冲量越大。所以如果想达到上面的效果,就需要修改冲量的大小。如果是 60 帧,那么就需要将冲量的大小改为 new CANNON.Vec3(10*(1/60), 0, 0)
applyTorque
js
sphereBody.applyTorque(new CANNON.Vec3(0, 0, 10));
applyTorque: 施加扭矩,第一个参数为扭矩的大小,第二个参数为扭矩的方向。