06 - 物体休眠与休眠事件详解(Cannon.js)
Cannon.js 提供了物体的休眠机制(Sleep),当刚体长时间处于静止或低速状态时,会自动进入“休眠”状态,从而 节省计算资源。
一、核心知识点
| 概念 | 说明 |
|---|
allowSleep | 是否允许该物体休眠(默认 false) |
sleepSpeedLimit | 速度低于该值会开始休眠计时(默认 0.1) |
sleepTimeLimit | 静止多久后才真正休眠(默认 1 秒) |
sleepState | 当前休眠状态(AWAKE, SLEEPY, SLEEPING) |
| 事件 | sleep, wakeup 可监听进入或唤醒状态 |
二、常量说明(CANNON.Body.SLEEPING)
| 状态 | 值 | 含义 |
|---|
CANNON.Body.AWAKE | 0 | 活跃状态 |
CANNON.Body.SLEEPY | 1 | 正在准备休眠 |
CANNON.Body.SLEEPING | 2 | 已休眠 |
三、完整示例(Vue3 + Cannon.js)
<!-- App.vue -->
<script setup>
import { onMounted, ref } from 'vue'
import * as THREE from 'three'
import * as CANNON from 'cannon-es'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
const canvasRef = ref()
onMounted(() => {
// 场景、相机
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100)
camera.position.set(0, 5, 10)
// 渲染器与轨道控制
const renderer = new THREE.WebGLRenderer({ canvas: canvasRef.value })
renderer.setSize(window.innerWidth, window.innerHeight)
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
// 灯光
const light = new THREE.DirectionalLight(0xffffff, 1)
light.position.set(10, 10, 10)
scene.add(light)
// 物理世界
const world = new CANNON.World()
world.gravity.set(0, -9.82, 0)
// 地面刚体
const groundBody = new CANNON.Body({
mass: 0,
shape: new CANNON.Plane()
})
groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0)
world.addBody(groundBody)
// 地面可视化
const groundGeo = new THREE.PlaneGeometry(10, 10)
const groundMat = new THREE.MeshStandardMaterial({ color: 0x999999, side: THREE.DoubleSide })
const groundMesh = new THREE.Mesh(groundGeo, groundMat)
groundMesh.rotation.x = -Math.PI / 2
scene.add(groundMesh)
// 创建一个立方体(可休眠)
const boxSize = 1
const boxGeo = new THREE.BoxGeometry(boxSize, boxSize, boxSize)
const boxMat = new THREE.MeshStandardMaterial({ color: 0x44aa88 })
const boxMesh = new THREE.Mesh(boxGeo, boxMat)
boxMesh.position.set(0, 5, 0)
scene.add(boxMesh)
const boxBody = new CANNON.Body({
mass: 1,
shape: new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)),
position: new CANNON.Vec3(0, 5, 0)
})
// ✅ 允许休眠
boxBody.allowSleep = true
boxBody.sleepSpeedLimit = 0.1
boxBody.sleepTimeLimit = 1.0
world.addBody(boxBody)
// 💤 监听休眠与唤醒事件
boxBody.addEventListener('sleep', () => {
console.log('🟦 物体进入休眠状态')
boxMesh.material.color.set(0xaaaaaa)
})
boxBody.addEventListener('wakeup', () => {
console.log('🟩 物体被唤醒')
boxMesh.material.color.set(0x44aa88)
})
// 动画循环
const clock = new THREE.Clock()
const timeStep = 1 / 60
function animate() {
requestAnimationFrame(animate)
const delta = clock.getDelta()
world.step(timeStep, delta)
boxMesh.position.copy(boxBody.position)
boxMesh.quaternion.copy(boxBody.quaternion)
controls.update()
renderer.render(scene, camera)
}
animate()
})
</script>
<template>
<canvas ref="canvasRef"></canvas>
</template>
四、常见用途
- 性能优化:大量静态物体(如积木塔)静止后进入休眠,不再参与模拟。
- 状态切换提示:休眠时更换颜色、显示文字、播放音效等。
- 唤醒机制:被碰撞、手动移动物体时自动唤醒。
小结
| 优点 | 描述 |
|---|
| 减少 CPU 计算开销 | 休眠体不会参与碰撞检测和力更新 |
| 适用于静态场景 | 如地面上的箱子、稳定的堆叠结构 |
| 事件驱动更直观 | sleep / wakeup 能帮助构建游戏逻辑 |