You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确移除关联射线检测且超出屏幕的游戏对象?

动态创建/销毁带射线检测的汽车对象时的引用清理问题

我在主游戏类中实现了createCar方法,用于动态创建汽车对象,并遍历已有汽车互相映射射线检测(使汽车可检测彼此距离):

createCar(scene, x, y, angle, speed, name) {
  const car = new Car(scene, x, y, angle, speed);
  car.name = name; // 调试用
  this.carsGroup.children.iterate((c) => {
    c.raycaster.mapGameObjects(car, true);
    car.raycaster.mapGameObjects(c, true);
  });
  this.carsGroup.add(car);
}

这段逻辑运行正常,但删除超出屏幕的汽车时出现问题,当前删除逻辑如下:

update() {
  this.carsGroup.children.iterate((car) => {
    // 判断汽车是否超出屏幕
    if (!this.cameras.main.worldView.contains(car.x, car.y)) {
      this.carsGroup.remove(car);
      this.carsGroup.children.iterate((c) => {
        c.raycaster.removeMappedObjects(car);
        car.raycaster.removeMappedObjects(c);
      });
      car.destroy();
    } else {
      car.update();
      car.debug();
    }
  });
}

执行删除操作时触发错误,内部尝试获取raycasterMap并销毁时失败:

object.data.get('raycasterMap').destroy();

具体报错信息:

raycaster-core.js:396 Uncaught TypeError: Cannot read properties of undefined (reading 'destroy')
at Raycaster.removeMappedObjects (raycaster-core.js:396:48)
at game.js:51:23

若直接调用car.destroy(),其他汽车会因射线检测仍保留对该汽车的引用而抛出异常,我无法找到正确从场景和内存中移除汽车的方法。


问题分析与修复方案

错误根源

  1. 遍历组时直接修改组:在this.carsGroup.children.iterate循环中直接调用this.carsGroup.remove(car),会导致迭代过程中数组结构变化,可能出现遍历不完整或对象引用异常。
  2. 无效对象的射线清理操作:移除汽车后再调用car.raycaster.removeMappedObjects(c),此时car的部分内部资源可能已经开始释放,导致raycasterMap无法被正常获取。

修复代码

修改update方法,先收集待删除汽车,再批量清理引用并销毁:

update() {
  // 第一步:收集所有需要删除的汽车
  const carsToRemove = [];
  this.carsGroup.children.iterate((car) => {
    if (!this.cameras.main.worldView.contains(car.x, car.y)) {
      carsToRemove.push(car);
    } else {
      car.update();
      car.debug();
    }
  });

  // 第二步:批量处理删除与引用清理
  carsToRemove.forEach(car => {
    // 清理其他汽车射线检测中对当前汽车的映射
    this.carsGroup.children.iterate((c) => {
      if (c !== car) {
        c.raycaster.removeMappedObjects(car);
      }
    });

    // 清理当前汽车射线检测中的所有映射(无需逐个遍历,直接清空)
    car.raycaster.removeMappedObjects();

    // 从组中移除并销毁汽车
    this.carsGroup.remove(car);
    car.destroy();
  });
}

额外优化建议

  • 确认raycaster.removeMappedObjects()无参数时是否会清空所有映射对象(根据报错的raycaster库API,通常支持此用法),这样可以避免逐个遍历其他汽车,提升效率。
  • 检查Car类的destroy方法,确保内部已正确清理raycaster相关资源;若未实现,可在car.destroy()前手动调用car.raycaster.destroy()(如果库支持该方法)。

内容的提问来源于stack exchange,提问作者Vololodymyr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:41:03