Phaser 3中isPlaying动画属性异常致游戏崩溃问题求助
解决Phaser 3中导弹碰撞动画导致的
isPlaying未定义报错问题 问题根源
报错Uncaught TypeError: Cannot read properties of undefined (reading 'isPlaying')的核心原因:
- 碰撞回调会多次触发——导弹与平台接触的连续帧中,Phaser会重复调用碰撞回调
- 即使第一帧回调已经触发爆炸动画并标记导弹销毁,后续帧的回调仍会执行,此时导弹精灵可能已进入销毁流程,
anims属性被Phaser清理为undefined - 原代码的
missile &&判断只能确保精灵本身未被完全销毁,但无法保证anims属性仍有效
修复方案
从避免重复触发回调、增强安全判断、防止重复绑定事件三个维度修复:
保存碰撞器实例,触发后立即销毁
创建碰撞器时将其赋值给变量,回调触发后直接销毁碰撞器,避免后续重复触发回调。增强安全判断,先检查
anims属性存在
在访问anims.isPlaying前,先判断missile.anims是否存在,避免访问undefined属性。用
once绑定动画完成事件
替换on为once,确保动画完成事件只执行一次销毁操作,避免多次绑定导致的异常。添加自定义状态标记,避免重复处理
给导弹精灵添加自定义属性(如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
相关产品推荐
相关产品推荐

