html5游戏引擎碰撞检测应优先使用内置物理系统而非手写算法,phaser 3需确保物体启用物理体并每帧调用collide(),cannon-es须显式启用事件与接触材质,pixi.js可用getbounds()实现低成本aabb检测。

HTML5 游戏引擎里做碰撞检测,不靠手写 AABB 或射线算法硬刚,而是用引擎自带的物理系统或碰撞组件——否则你很快会掉进浮点误差、帧率依赖、穿透(tunneling)和坐标系混乱的坑里。
Phaser 3 的 arcade.collide() 怎么写才不漏判
Phaser 3 的 Arcade Physics 是最常用的轻量方案,但 collide() 不是“一调就灵”。它只在两物体都启用 setCollideWorldBounds(true) 且至少一个有 body.enable = true 时才生效。
- 必须手动调用
this.physics.arcade.collide(player, platforms)在update()里,不能只在create()里设一次 - 如果物体是动态生成的(比如子弹),要立刻调用
body.setAllowGravity(false)避免被重力拖偏轨迹,影响碰撞判定位置 - 默认碰撞箱是 sprite 的整个矩形框;想贴合图形轮廓,得用
body.setSize(w, h, offsetX, offsetY)手动缩放/偏移 - 两个静止物体(
body.immovable = true)之间不会触发回调,除非其中一个是动态的
Three.js + Cannon-es 做 3D 碰撞时,world.addEventListener('collide') 为什么没反应
Cannon-es 的事件监听不是自动开启的。它默认只计算物理状态,不广播事件——你得显式启用 allowSleep: false 和 contactMaterial 配置,否则连接触都检测不到。
- 初始化 world 后必须加
world.allowSleep = false,否则休眠物体会跳过碰撞检测 - 要监听
'collide',得先定义 contact material:const contactMaterial = new CANNON.ContactMaterial(materialA, materialB, { friction: 0.3, restitution: 0.2 }),再world.addContactMaterial(contactMaterial) - 实体的 shape 必须与 body 尺寸严格匹配;用
BoxGeometry创建 mesh 但用CANNON.Box创建 body 时,单位要一致(比如都用米,别一个用像素一个用单位长度) - 事件回调里的
bodyA和bodyB是 cannon-es 的 body 实例,不是 three.js 的 mesh,需提前用body.userData.mesh = mesh挂载引用
PIXI.js 没内置物理系统,怎么低成本加矩形碰撞
PIXI.js 本身不处理碰撞,但你可以用 getBounds() + 手动 AABB 判定,前提是绕开渲染延迟带来的坐标错位。
立即学习“前端免费学习笔记(深入)”;
- 别直接用
sprite.x / y,而要用sprite.getBounds().contains(x, y)或bounds1.intersects(bounds2),因为getBounds()考虑了 scale、rotation 和 parent transform - 如果物体有父子结构(比如角色手持武器),必须对齐坐标系:先
sprite.parent.toLocal(point, null, out)把世界坐标转为本地坐标再比 - 高频检测(如每帧)建议缓存 bounds 结果,避免重复计算;用
sprite._boundsID判断是否需要重算 - 想支持圆形检测?别自己写 sqrt 距离公式,用
PIXI.utils.isPointInCircle(x, y, cx, cy, radius),它已做 NaN 和负半径防护
真正麻烦的从来不是“有没有碰撞”,而是“什么时候算、在哪一级坐标系下算、谁负责清理临时接触状态”。引擎封装得越深,越要小心它帮你省掉的那几行代码里藏着的假设。











