aframe - 使用 Ammo 驱动程序时,如何使用 A-Frame 物理系统移动动态物体?
问题描述
这个先前的问题和答案解释了如何在 A-Frame 物理系统中移动动态物体,方法是在更改位置后使用 syncToPhysics() 方法调用。 如何翻译 A-Frame 动态体
我一直在使用这种技术,并且在使用 CANNON.js 驱动程序时对我来说效果很好。
参见例如https://unmarred-ambiguous-shad.glitch.me/
但是,我想使用 Ammo 驱动程序,如此处所述。 https://github.com/n5ro/aframe-physics-system/blob/master/AmmoDriver.md
(想要使用 Ammo 驱动程序的一个关键原因是,目前 CANNON.js 不适用于 A-Frame 1.2+ https://github.com/n5ro/aframe-physics-system/issues/187)。
我希望我可以在 ammo-body 组件上使用 syncToPhysics() 做同样的事情:
this.el.components["ammo-body"].syncToPhysics();
但我试图在这个故障中这样做,但它不起作用 - 身体只是卡在一个地方。 https://roasted-snow-replace.glitch.me/
有什么方法可以让这个功能与 Ammo 一起工作,或者在使用 Ammo 驱动程序时无法直接操纵动态物体的位置?
解决方案
这并不优雅,但我发现“传送”对象的唯一解决方案是:
- 将身体碰撞标志设置为 KINEMATIC (2) - 否则子弹只是忽略运动状态更新
- 应用新位置(通过
syncToPhysics()
使用框架物理时) - 重置身体速度,因此物体不会在传送后立即反弹
- 恢复原始标志(通过
updateCollisionFlags()
使用框架物理时)
像这里的东西:
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://mixedreality.mozilla.org/ammo.js/builds/ammo.wasm.js"></script>
<script src="https://cdn.jsdelivr.net/gh/n5ro/aframe-physics-system@v4.0.1/dist/aframe-physics-system.js"></script>
<script>
AFRAME.registerComponent("moving-dynamic-body", {
init: function() {
// wait until the physics engine is ready
this.el.addEventListener("body-loaded", e => {
// cache the ammo-body component
this.ammoComponent = this.el.components["ammo-body"];
// use this vector to zero the velocity
// keep in mind this needs to be deleted manually from the memory with Ammo.destroy(this.zeroSpeed)
this.zeroSpeed = new Ammo.btVector3(0, 0, 0);
});
}
,
tick: function() {
// wait for the physics
if (!this.ammoComponent) return;
// restore stuff if the "teleport magic" has been done in the last renderloop.
// this should probably be done in steps instead of tick
if (this.collisionFlag === 2) {
// this just tells us that we reverted to normal
this.collisionFlag = 0;
// restore the original collision flags
this.ammoComponent.updateCollisionFlags();
// reset the speed, or the body will bounce away
this.ammoComponent.body.setLinearVelocity(this.zeroSpeed);
}
// if the body is below 1m
if (this.el.object3D.position.y < 1) {
// set the THREEJS position.y
this.el.object3D.position.y = 2;
// change the collision flag to the KINEMATIC_BODY
this.collisionFlag = 2;
// apply the flag
this.ammoComponent.body.setCollisionFlags(this.collisionFlag);
// sync the physisc transforms to the THREEJS transform
this.ammoComponent.syncToPhysics();
}
}
});
</script>
<a-scene physics="driver: ammo; debug: true; debugDrawMode: 1;" renderer="colorManagement:true">
<a-box id="test1" ammo-body="type: dynamic" ammo-shape="type: box" material="color:#dd1111" height="0.1" width="0.1" depth="0.1" position="0 2 -1" moving-dynamic-body>
</a-box>
</a-scene>
推荐阅读
- node.js - 如何在 Heroku 上设置环境变量?
- html - 突出显示垫行单元格的全宽
- javascript - 在 react js 中使用 ant design 上传图片
- python - 如何计算Django中一个对象的多个字段的值?
- lightningchart - LineSeries-onMouseClick的麻烦
- scala - 计算给定列集的不同列值
- wordpress - Worpress 上的 icomoon.ttf 显示 404 和较长的响应时间减慢了我的网站
- php - Concrete5 MySQL 查询问题
- vue.js - 有没有办法传递 v-chip-group v-model id 而不是项目索引?
- machine-learning - 使用文本和数字列构建机器学习模型