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

Phaser 3中isPlaying动画属性异常致游戏崩溃问题求助

解决Phaser 3中导弹碰撞动画导致的isPlaying未定义报错问题

问题根源

报错Uncaught TypeError: Cannot read properties of undefined (reading 'isPlaying')的核心原因:

  • 碰撞回调会多次触发——导弹与平台接触的连续帧中,Phaser会重复调用碰撞回调
  • 即使第一帧回调已经触发爆炸动画并标记导弹销毁,后续帧的回调仍会执行,此时导弹精灵可能已进入销毁流程,anims属性被Phaser清理为undefined
  • 原代码的missile &&判断只能确保精灵本身未被完全销毁,但无法保证anims属性仍有效

修复方案

从避免重复触发回调、增强安全判断、防止重复绑定事件三个维度修复:

  1. 保存碰撞器实例,触发后立即销毁
    创建碰撞器时将其赋值给变量,回调触发后直接销毁碰撞器,避免后续重复触发回调。

  2. 增强安全判断,先检查anims属性存在
    在访问anims.isPlaying前,先判断missile.anims是否存在,避免访问undefined属性。

  3. 用once绑定动画完成事件
    替换on为once,确保动画完成事件只执行一次销毁操作,避免多次绑定导致的异常。

  4. 添加自定义状态标记,避免重复处理
    给导弹精灵添加自定义属性(如isProcessing),标记是否正在处理碰撞逻辑,防止同一导弹被重复处理。

修改后的代码示例

玩家导弹碰撞逻辑

// 保存碰撞器实例
const missileCollider = this.physics.add.collider(missile, platforms, () => {
    // 安全判断:精灵存在、anims属性有效、未在处理中
    if (missile && missile.anims && !missile.isProcessing) {
        missile.isProcessing = true;
        // 销毁碰撞器,阻止后续回调触发
        missileCollider.destroy();

        if (!missile.anims.isPlaying || missile.anims.currentAnim.key !== 'missExplosion') {
            missile.setTexture('expl1');
            missile.play('missExplosion');
            // 用once确保仅执行一次销毁
            missile.once('animationcomplete', () => {
                missile.destroy();
            });
        }
    }

    setTimeout(() => {
        keyIsDown = true;
    }, 500);
});

CPU导弹碰撞逻辑

// 保存碰撞器实例
const cpuMissileCollider = this.physics.add.collider(cpuMissile, platforms, () => {
    // 安全判断:精灵存在、anims属性有效、未在处理中
    if (cpuMissile && cpuMissile.anims && !cpuMissile.isProcessing) {
        cpuMissile.isProcessing = true;
        // 销毁碰撞器,阻止后续回调触发
        cpuMissileCollider.destroy();

        if (!cpuMissile.anims.isPlaying || cpuMissile.anims.currentAnim.key !== 'cpuMissExplosion') {
            cpuMissile.setTexture('expl1');
            cpuMissile.play('cpuMissExplosion');
            // 用once确保仅执行一次销毁
            cpuMissile.once('animationcomplete', () => {
                cpuMissile.destroy();
            });
        }
    }
});

补充说明

原代码中的setTimeout仅控制keyIsDown状态,无法阻止碰撞回调的多次触发,因此对解决报错无效。上述修复方案从根源上避免了无效的回调执行和属性访问,彻底解决卡顿与报错问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:10:46