PAYATHON 2026

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);

逐项检查

  1. 确认子弹有启用的 Arcade Physics body。 如果子弹是普通对象,或属于普通 Group,仅把它加入组并不会自动使它成为物理对象。可以使用 this.physics.add.group() 创建物理组,也可以为对象显式添加 Arcade Physics body。
  2. 确认子弹没有被禁用。 检查 bullet.body 是否存在,以及 bullet.body.enable 是否为 true。如果子弹曾被回收或调用过 disableBody,生成时需要重新启用。
  3. 确认碰撞器只创建一次。 通常在场景初始化时添加 collider。不要只在发射子弹时创建,也不要在多处重复创建。
  4. 核对图层和瓦片属性。 this.groundLayer 应是实际参与 Arcade Physics 碰撞的 TilemapLayer,目标瓦片也须具有匹配的 collides: true 属性。玩家碰撞正常可以作为线索;还可以检查子弹是否靠近同一批可碰撞瓦片。
  5. 检查子弹是否真的到达墙面。 临时打印子弹坐标和 body 状态,确认它的移动轨迹与图层位置及碰撞体积相交。

overlap 用于检测重叠,不会执行碰撞分离。如果子弹撞墙后应停下或反弹,请使用 collider。如果只需检测命中并自行处理,也可以用 overlap,但它同样要求对象有可用的物理体,且瓦片碰撞设置有效。

备注:内容仅供参考。