06 - 物体休眠与休眠事件详解(Cannon.js)

发布于 2025-07-24 00:24 687 字 4 min read

做产品前,先别急着写代码:我是怎么判断一个点子值不值得做的想偷卷?但微信不支持md文档?这个软件助你!新手小白如何开发练手项目?前端常见安全问题 + 防御方法 + 面试回答吉比特(雷霆游戏)前端二面问题总结吉比特27前端实习面试纷享销客前端实习一面08-刚体约束 Constraint07-监听碰撞事件和获取碰撞信息06 - 物体休眠与休眠事件详解(Cannon.js)05-碰撞与碰撞组04 - 弹性与接触材质详解03 - Cannon 材质与摩擦系数设置02 - Cannon 引擎基础碰撞讲解01 - Cannon.js 引擎的用途和基本使用一款减轻前端图片命名工作量的图片转换器总结:一个双非大学生的两年,是怎么过来的?数学公式Input-输入框组件实现详解用HTML5实现实时ASCII艺术摄像头object-fit: contain - CSS 属性详解GSAP (GreenSock Animation Platform) 动画库学习指南Webview通信系统学习指南实现手势操控3D粒子动画?太好玩了!东田数码科技前端面试前端性能优化面试回答技巧(一)React与Vue表单的对比差异融山科技前端面经·React的入门学习(一)九方前端面试JavaScript 核心:数组/字符串 API 精要指南JavaScript的常用数组API原理解析前端练习小网站-新手突破之路前端の骚操作代码合集 (二)| 让你的网页变得有趣前端Threejs入门(五)Vue 3 响应式原理:computed的模板解包机制Vue 监听器 watch 深度解析Axios 深入解析从0到1配置vue项目跟git仓库连接!前端Three.js入门(四)你懂keep-alive吗?见过Vue的小区保安吗?前端Three.js入门(三)前端Three.js入门(二)前端Three.js入门(一)-Three的第一个简单的页面 Git 大冒险:解锁代码管理的秘密武器如何将网站加载速度提升50%?前端性能优化全攻略前端の骚操作代码合集 | 让你的网页充满恶趣味进击蓝桥杯!2025web前端HTML5uniapp-页面生命周期
06 物体休眠与休眠事件详解(Cannon.js) 作者: 前端AC | 原文: https://juejin.cn/post/7530106154313433098 06 物体休眠与休眠事件详解(Cannon.js) Cannon.js 提供了物体的休眠机制(Sleep),当刚体长时间处于...

06 - 物体休眠与休眠事件详解(Cannon.js)

作者: 前端AC | 原文: https://juejin.cn/post/7530106154313433098

06 - 物体休眠与休眠事件详解(Cannon.js)

Cannon.js 提供了物体的休眠机制(Sleep),当刚体长时间处于静止或低速状态时,会自动进入“休眠”状态,从而 节省计算资源


一、核心知识点

概念说明
allowSleep是否允许该物体休眠(默认 false)
sleepSpeedLimit速度低于该值会开始休眠计时(默认 0.1)
sleepTimeLimit静止多久后才真正休眠(默认 1 秒)
sleepState当前休眠状态(AWAKE, SLEEPY, SLEEPING
事件sleep, wakeup 可监听进入或唤醒状态

二、常量说明(CANNON.Body.SLEEPING

状态含义
CANNON.Body.AWAKE0活跃状态
CANNON.Body.SLEEPY1正在准备休眠
CANNON.Body.SLEEPING2已休眠

三、完整示例(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 能帮助构建游戏逻辑