Phaser 3场景中AJAX响应内更新场景变量失效问题咨询
核心问题
所有异常都源于两个基础问题:
- AJAX回调的
this指向错误:使用普通函数作为success/error回调时,函数内部this绑定的是jQuery AJAX的请求上下文,而非Phaser场景实例。回调中修改的this.correctToken并不是挂载在场景上的变量,因此场景的create、update生命周期中读取的变量始终是初始值,调用this.scene.start、操作类私有变量报错也都是指向错误导致的。 - Phaser的preload生命周期默认只等待内置资源加载(图片、音频等)完成,不会自动等待自定义AJAX请求结束,即使指向正确也可能出现preload执行完毕、进入create后AJAX才返回的时序问题。
可行解决方案
方案一:修正指向后直接在回调处理逻辑(最简便)
直接用箭头函数绑定回调的this指向为场景实例,请求返回后直接执行跳转逻辑,无需在生命周期中轮询判断:
class InitScene extends Phaser.Scene{ // 若使用私有变量需先声明 #correctToken = false; constructor(){ super("InitScene") } preload(){ this.Token = getParameterByName('Token')||1; const validateData = { Token: this.Token }; this.#correctToken = false; $.ajax({ url: "validateTokenAPI", type: "POST", data: JSON.stringify(validateData), headers: { "Content-Type": "application/json" }, // 箭头函数继承外层this,指向场景实例 success: (response) => { this.#correctToken = response; if(this.#correctToken) { this.scene.start("NextScene"); } }, error: () => { console.log('Token校验请求失败'); // 可自行补充失败提示逻辑 } }); } create(){ const { width, height } = this.sys.game.canvas; this.add.text(width/2, height/2,"LOADING...", {font: "28px Arial", fill: "black"}).setOrigin(0.5); } } function getParameterByName(name, url = window.location.href) { name = name.replace(/[\[\]]/g, '\\$&'); const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, ' ')); }
方案二:注册自定义加载任务,让preload等待AJAX完成
如果需要保证preload阶段完成所有校验逻辑再进入create,可以将AJAX注册为Phaser加载队列的自定义任务:
class InitScene extends Phaser.Scene{ #correctToken = false; constructor(){ super("InitScene") } preload(){ this.Token = getParameterByName('Token')||1; const validateData = { Token: this.Token }; this.#correctToken = false; // 自定义校验任务 const validateTask = (loader, callback) => { $.ajax({ url: "validateTokenAPI", type: "POST", data: JSON.stringify(validateData), headers: { "Content-Type": "application/json" }, success: (response) => { this.#correctToken = response; callback(); // 通知加载器任务完成 }, error: () => { callback(); // 失败也通知完成,避免加载卡住 } }); }; // 将任务加入预加载队列 this.load.next('tokenValidate', validateTask, this); } create(){ const { width, height } = this.sys.game.canvas; this.add.text(width/2, height/2,"LOADING...", {font: "28px Arial", fill: "black"}).setOrigin(0.5); // preload已等待AJAX完成,此处直接判断即可 if(this.#correctToken){ this.scene.start("NextScene"); } } } function getParameterByName(name, url = window.location.href) { name = name.replace(/[\[\]]/g, '\\$&'); const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, ' ')); }
内容的提问来源于stack exchange,提问作者A.J Alhorr
相关产品推荐
相关产品推荐

