onAdvance 是 Phaser 3.60+ 的实验性钩子,仅在 TimerEvent 被显式 advance() 时触发,适用于多阶段资源状态转换,但需手动驱动、避免跨阶段访问未就绪资源。

onAdvance 是什么,它真能用在资源状态转换上?
onAdvance 是 Phaser 3.60+ 引入的实验性钩子函数,挂载在 Phaser.Time.TimerEvent 实例上,用于在每次定时器“推进”(advance)时触发回调。它不是每帧调用,而是仅在 TimerEvent 被显式调用 advance() 或内部因时间跳跃被重调度时执行。这意味着它**不适用于常规动画或实时响应**,但特别适合多阶段、非连续、需精确控制触发时机的任务——比如按步骤加载/卸载资源、切换状态机阶段、批量提交变更等。
常见误用是把它当 update 或 onTick 用,结果发现回调根本不执行,或者只跑一次。根本原因是:TimerEvent 默认不会自动 advance;你得手动驱动它。
怎么让 onAdvance 真正跑起来并分阶段触发?
关键在于主动调用 timer.advance(),并配合 repeat 和 delay 控制节奏。一个典型多阶段资源状态转换(如:预加载 → 解析 → 初始化 → 就绪)可这样组织:
const timer = this.time.addEvent({
delay: 0,
repeat: 3, // 四个阶段:0→1→2→3,共触发 4 次(含初始)
callback: () => {},
callbackScope: this
});
timer.onAdvance = (event, step) => {
switch (step) {
case 0:
this.load.image('ui', 'assets/ui.png');
break;
case 1:
this.load.start(); // 触发实际加载
break;
case 2:
this.textures.get('ui').setFilter(Phaser.Textures.FilterMode.LINEAR);
break;
case 3:
this.scene.launch('GameScene');
break;
}
};
-
repeat: 3表示总共 advance 4 次(step 从 0 开始计数) - 必须显式调用
timer.advance()才会进入下一步;自动 advance 仅发生在时间自然流逝且 timer 处于活跃状态时(极少用于此场景) - 别依赖
delay值来划分阶段——delay只影响首次启动等待,阶段间隔由你何时调用advance()决定
为什么资源状态容易错乱?注意 load / texture / scene 的生命周期边界
Phaser 中资源状态转换失败,90% 出现在跨阶段访问未就绪对象。例如在 step 2 就去改 textures.get('ui'),但此时 load.start() 还没完成,纹理根本不存在。
-
Phaser.Loader.LoaderPlugin是异步的,load.start()返回后立即执行后续advance()会导致 race condition - 正确做法:在
load.on('complete', ...)回调里调用timer.advance(),确保上一阶段真正结束 - scene 切换前,确认前一场景已
destroy()或至少sys.shutdown(),否则纹理引用残留会导致内存泄漏 - 不要在
onAdvance里重复调用load.image()—— 同名 key 会覆盖,但旧资源不会自动释放
替代方案比 onAdvance 更稳?什么时候该放弃它
如果你的“多阶段”本质是线性依赖(B 必须等 A 完成),onAdvance 反而增加心智负担。更直接的做法是链式 Promise:
this.load.image('ui', '...').then(() =>
this.load.start()
).then(() =>
this.textures.get('ui').setFilter(...)
).then(() =>
this.scene.launch('GameScene')
);
而 onAdvance 真正有用的地方是:需要暂停、跳过、回退某阶段,或阶段间有外部信号介入(比如等待用户点击、网络响应、物理模拟收敛)。这时候它提供的是「可控的、可中断的步进器」,不是流程引擎。
最容易被忽略的一点:onAdvance 的 step 参数不会自动递增——它是 TimerEvent 内部根据 repeat 次数推算的当前索引,你无法手动设为 5 或跳到 2。所有阶段逻辑必须严格按顺序设计,中间不能插空。

















