首页
/ Phaser游戏引擎中TimerEvent延迟设置为0导致的无限循环问题解析

Phaser游戏引擎中TimerEvent延迟设置为0导致的无限循环问题解析

2025-05-03 20:55:35作者:戚魁泉Nursing

问题背景

在Phaser 3.86.0版本中,当开发者创建一个TimerEvent定时器事件时,如果将delay参数设置为0且repeat参数设置为-1(表示无限重复),会导致浏览器标签页陷入无限循环而卡死。这个问题在Phaser 3.60版本之前并不存在,因为早期版本中delay为0被用作"每帧运行"的特殊处理方式。

技术原理分析

Phaser的定时器系统由Clock和TimerEvent两个核心类组成。Clock负责管理所有TimerEvent的更新,而TimerEvent则封装了具体的定时逻辑。

在Phaser 3.60版本后,引擎对定时器逻辑进行了修改,新增了确保回调函数平均每隔delay时间执行一次的逻辑。当delay为0时,系统会在每一帧更新时计算剩余时间,由于delay为0,remainder总是大于等于0,导致while循环条件始终成立,从而形成无限循环。

问题重现

以下代码可以重现该问题:

export default class TimerEventDelayIssue extends Phaser.Scene {
  create() {
    this.time.addEvent({
      delay: 0,
      callback: () => console.log('timer事件回调'),
      repeat: -1
    });
  }
}

执行这段代码会导致浏览器标签页完全卡死,因为回调函数被无限次执行。

解决方案

Phaser开发团队已经修复了这个问题,解决方案主要包含两个方面:

  1. 在Clock.js的update循环中增加了对delay值的检查,只有当delay大于0时才执行循环调用逻辑
  2. 移除了TimerEvent.js中关于delay为0的特殊处理,因为现在它已成为有效配置

修复后的核心逻辑如下:

if (remainder >= event.delay && event.delay > 0) {
  while ((remainder >= event.delay) && (event.repeatCount > 0)) {
    if (event.callback) {
      event.callback.apply(event.callbackScope, event.args);
    }
    remainder -= event.delay;
    event.repeatCount--;
  }
}

开发者建议

对于需要使用每帧执行回调的场景,开发者可以考虑以下替代方案:

  1. 使用Scene的update钩子函数
  2. 设置一个非常小的delay值(如1ms)而不是0
  3. 等待包含此修复的Phaser新版本发布

这个修复已经合并到master分支,将在下一个版本中发布。开发者可以关注Phaser的更新日志,及时获取最新稳定版本。

登录后查看全文
热门项目推荐
相关项目推荐