无法在碰撞事件中移除dynamic-body组件:TypeError错误排查
AFRAME碰撞处理组件移除属性触发TypeError问题排查
问题概述
在AFRAME开发中,注册collision-handler组件实现逻辑:当通过superhands抓取的#knife实体与#fruit实体碰撞时,移除#fruit的dynamic-body和body-merger组件。但在collide事件监听内执行移除操作时,会触发TypeError: _bi2 is undefined错误;将移除代码放在监听外部则无异常。
相关代码
组件代码
AFRAME.registerComponent('collision-handler', { init: function () { var el = this.el; var sceneEl = document.getElementsByTagName('a-scene'); var fruit = document.getElementById("#fruit"); el.addEventListener('collide', function collision (event) { var collidedEntity = event.detail.body.el; if (collidedEntity.id === '#fruit') { fruit.removeAttribute('body-merger: dynamic-body'); fruit.removeAttribute('dynamic-body'); // fruit.removeAttribute('scale'); el.removeEventListener('collide', collision); console.log('Collided with entity with ID "#fruit"'); } }); // fruit.removeAttribute('dynamic-body'); // fruit.removeAttribute('body-merger: dynamic-body'); } });
实体结构
<a-entity id="#fruit" position="1.5 2 -2" dynamic-body mixin="interactable" body-merger="dynamic-body" scale="0.5 0.5 0.5"> <a-box mixin="cube" dynamic-body position="0 0 0" color="blue"></a-box> <a-box mixin="cube" dynamic-body position="-0.5 0 0" color="red"></a-box> <a-box mixin="cube" dynamic-body position="0.5 0 0" color="green"></a-box> </a-entity> <a-box id="#knife" position="0.5 2 -2" static-body mixin="interactable" geometry="width: 0.25; height: 0.25; depth: 1" color="purple" collision-handler></a-box>
依赖包
<script src="https://aframe.io/releases/1.5.0/aframe.js"></script> <script src="https://cdn.jsdelivr.net/gh/c-frame/aframe-physics-system@v4.1.0/dist/aframe-physics-system.js"></script> <script src="https://cdn.jsdelivr.net/gh/c-frame/aframe-extras@7.2.0/dist/aframe-extras.min.js"></script> <script src="https://unpkg.com/aframe-physics-extras/dist/aframe-physics-extras.min.js"></script>
问题原因及解决方法
1. ID定义与选择错误
实体的id属性不需要带#符号,当前代码中id="#fruit"、id="#knife"的写法不符合规范,会导致document.getElementById("#fruit")无法正确获取元素,后续操作因元素为null触发异常。
修正点:
- 实体ID改为
id="fruit"、id="knife" - 获取元素改为
document.getElementById("fruit") - 碰撞判断条件改为
collidedEntity.id === "fruit"
2. 移除属性语法错误
removeAttribute方法只需传入属性名,不需要带属性值部分,当前fruit.removeAttribute('body-merger: dynamic-body')写法错误,应改为fruit.removeAttribute('body-merger')。
3. 物理引擎同步冲突
在collide事件回调中直接修改物理组件,会打断物理引擎当前帧的更新流程,导致内部引用丢失(即报错中的_bi2变量未定义)。需将移除操作延迟到下一帧,让物理引擎完成当前处理后再执行修改。
修正后的代码
组件代码
AFRAME.registerComponent('collision-handler', { init: function () { var el = this.el; var fruit = document.getElementById("fruit"); el.addEventListener('collide', function collision (event) { var collidedEntity = event.detail.body.el; if (collidedEntity.id === "fruit") { // 延迟执行避免打断物理引擎流程 requestAnimationFrame(() => { fruit.removeAttribute('body-merger'); fruit.removeAttribute('dynamic-body'); el.removeEventListener('collide', collision); console.log('Collided with entity with ID "fruit"'); }); } }); } });
实体代码
<a-entity id="fruit" position="1.5 2 -2" dynamic-body mixin="interactable" body-merger="dynamic-body" scale="0.5 0.5 0.5"> <a-box mixin="cube" dynamic-body position="0 0 0" color="blue"></a-box> <a-box mixin="cube" dynamic-body position="-0.5 0 0" color="red"></a-box> <a-box mixin="cube" dynamic-body position="0.5 0 0" color="green"></a-box> </a-entity> <a-box id="knife" position="0.5 2 -2" static-body mixin="interactable" geometry="width: 0.25; height: 0.25; depth: 1" color="purple" collision-handler></a-box>
内容的提问来源于stack exchange,提问作者Eduard Koczi
相关产品推荐
相关产品推荐

