Phaser 中如何检测物理组与 TilemapLayer 的碰撞?
数据小陈
结论
在 Phaser 3 的 Arcade Physics 中,可以使用 this.physics.add.collider(this.bullets, this.groundLayer, callback) 检测物理组与 TilemapLayer 的碰撞。你贴出的 setCollisionByProperty 用法也适用于这个场景。玩家能撞到这些瓦片,说明瓦片碰撞属性至少已对玩家生效。
仅凭这段代码还无法确定回调没有触发的具体原因。可以先检查 this.bullets 中的子对象是否都启用了 Arcade Physics body,以及 collider 是否只在初始化时创建一次。碰撞回调的第二个参数是瓦片(Tile),不是另一个物理游戏对象。
建立碰撞器并处理命中
this.bullets = this.physics.add.group();
this.physics.add.collider(
this.bullets,
this.groundLayer,
(bullet, tile) => {
console.log("hit", tile.index);
bullet.disableBody(true, true);
}
);
使用物理组的 create 方法创建子弹,会为子弹添加 Arcade Physics body:
const bullet = this.bullets.create(x, y, "bullet");
bullet.setVelocity(300, 0);
disableBody(true, true) 会禁用物理体,并停用和隐藏子弹。单独调用 setActive(false) 和 setVisible(false) 只会改变对象状态,不会明确禁用物理体,所以命中后使用 disableBody 更合适。
如果通过 get 重用已禁用的子弹,需要重新启用它的物理体:
bullet.enableBody(true, x, y, true, true);
bullet.setVelocity(300, 0);
逐项检查
- 确认子弹有启用的 Arcade Physics body。 如果子弹是普通对象,或属于普通
Group,仅把它加入组并不会自动使它成为物理对象。可以使用this.physics.add.group()创建物理组,也可以为对象显式添加 Arcade Physics body。 - 确认子弹没有被禁用。 检查
bullet.body是否存在,以及bullet.body.enable是否为true。如果子弹曾被回收或调用过disableBody,生成时需要重新启用。 - 确认碰撞器只创建一次。 通常在场景初始化时添加 collider。不要只在发射子弹时创建,也不要在多处重复创建。
- 核对图层和瓦片属性。
this.groundLayer应是实际参与 Arcade Physics 碰撞的 TilemapLayer,目标瓦片也须具有匹配的collides: true属性。玩家碰撞正常可以作为线索;还可以检查子弹是否靠近同一批可碰撞瓦片。 - 检查子弹是否真的到达墙面。 临时打印子弹坐标和 body 状态,确认它的移动轨迹与图层位置及碰撞体积相交。
overlap 用于检测重叠,不会执行碰撞分离。如果子弹撞墙后应停下或反弹,请使用 collider。如果只需检测命中并自行处理,也可以用 overlap,但它同样要求对象有可用的物理体,且瓦片碰撞设置有效。
备注:内容仅供参考。
