跳到主要内容

直接调用 ammo.js

rigidbody、collision 和 joint 组件覆盖大多数游戏需求,但 Bullet 提供的功能更多。可以直接调用 ammo.js 使用连续碰撞检测、自定义碰撞标志、其他约束、软体和车辆。

ammo.js 直接移植 Bullet,因此 API 与 C++ 对应。虽然没有独立 ammo.js 文档,但 Bullet 用户手册适用,JavaScript 暴露的类和方法列在仓库的 ammo.idl 中。编辑器从商店导入及引擎示例提供的构建包含该文件全部接口。如需更多功能,可自行编译并替换;编辑器中作为 WASM 模块资源添加。

注意

直接使用 Ammo 会绕过引擎组件,将项目绑定到 ammo.js 后端,不属于 PlayCanvas API 参考覆盖范围;相关对象也属于引擎内部,版本间可能变化。组件能够满足需求时,应优先使用组件。

访问原生对象​

每个 rigidbody 包装一个 Bullet btRigidBody,组件初始化后通过 entity.rigidbody.body 访问。整个模拟位于 btDiscreteDynamicsWorld,通过 app.systems.rigidbody.dynamicsWorld 访问。ammo.js 未加载时,两者为 null。各开发方式属性相同,实体和应用的获取方式见移动刚体。

保持 ammo.js 代码稳定的两个规则:

  • **使用时再取刚体。**修改类型或碰撞形状等属性时,引擎会重建原生刚体,因此不要跨帧缓存 rigidbody.body。每次使用时重新读取,变化后重新应用自定义设置。
  • **释放自己分配的对象。**ammo.js 对象位于 WebAssembly 内存,不由 JavaScript 垃圾回收管理。创建的 btVector3、btTransform 或约束用完后,调用 Ammo.destroy()。

连续碰撞检测​

高速刚体有时会互相穿透。Bullet 的连续碰撞检测(CCD)通过在刚体前后位置间扫掠球体,检查沿途交点,补充常规检测。rigidbody 组件未暴露 CCD,但可通过原生刚体上的两个调用启用:

// Run this once the body exists, for example in a script's initialize(), and again
// if the body is recreated by a change of type or shape
const body = entity.rigidbody.body;

// Distance in meters the body must move in one step before CCD kicks in
body.setCcdMotionThreshold(1);

// Radius of the swept sphere. Keep it below the half extent of the shape:
// for an object about 1 meter across, try 0.2
body.setCcdSweptSphereRadius(0.2);

CCD 物理教程将两个值封装为可配置脚本,项目在这里。

扩展内置组件之外的功能​

同样的方法也可用于其他 Bullet 功能:

  • 约束。关节组件支持固定、球形、铰链、滑块和 6dof。其他类型或参数可自行创建 Bullet 约束,通过 addConstraint() 加入物理世界,结束时移除并销毁。Physics Constraints 项目以此方式驱动全部 Bullet 约束类型。
  • **车辆。**Bullet 射线车辆在底盘刚体上模拟车轮、悬挂和转向。没有专门车辆组件,因此车辆物理教程和引擎 vehicle.js 直接控制 btRaycastVehicle。
  • **软体和布料。**ammo.js 包含 Bullet 软体求解器,但需要软刚体世界,而非引擎默认离散世界,属于较高级集成。
车辆

另请参阅​