Phaser.js中this.gameState未识别,报Cannot read properties of undefined错误
问题描述
我在Glitch平台复刻Phaser实验室的瓦片切比雪夫距离实验,参考Stack Overflow方案用Phaser.gameState存储需多处更新的变量,但控制台报错:Cannot read properties of undefined (reading 'gameState')。调整this上下文后问题依旧,以下是初始代码和更新后代码:
初始代码
import Phaser from "../lib/phaser.js"; export default class Game extends Phaser.Scene { constructor() { super("game1"); } preload() { this.load.image( "Tileset", "https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/pixil-frame-0%20(17).png?v=1675985219390" ); this.load.tilemapTiledJSON( "map", "https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/Map.tmj?v=1675985261369" ); this.load.spritesheet( "player", "https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/pixil-frame-0%20(13).png?v=1675904194091", { frameWidth: 32, frameHeight: 32 } ); } create() { this.gameState = { map: "", cursors: "", }; this.gameState.map = this.make.tilemap({ key: "map" }); this.tiles = this.gameState.map.addTilesetImage("tileSet", "Tileset"); this.worldLayer = this.gameState.map.createLayer( "Block Layer", this.tiles, 0, 0 ); this.player = this.physics.add.sprite(0, 0, "player", 1); this.cameras.main.setBounds( 0, 0, this.gameState.map.widthInPixels, this.gameState.map.heightInPixels ); this.cameras.main.startFollow(this.player); this.gameState.cursors = this.input.keyboard.createCursorKeys(); } update() { function updateMap() { console.log(this.gameState) var origin = this.gameState.map.getTileAtWorldXY( this.player.x, this.player.y ); this.gameState.map.forEachTile(function (tile) { var dist = Phaser.Math.Distance.Chebyshev( origin.x, origin.y, tile.x, tile.y ); tile.setAlpha(1 - 0.1 * dist); }, this); } if (this.gameState.cursors.left.isDown) { this.player.setVelocityX(-50); this.player.anims.play("left", true); } else if (this.gameState.cursors.right.isDown) { this.player.setVelocityX(50); this.player.anims.play("right", true); } else if (this.gameState.cursors.up.isDown) { this.player.setVelocityY(-50); } else if (this.gameState.cursors.down.isDown) { this.player.setVelocityY(-50); } else { this.player.setVelocityX(0); } updateMap(); } }
更新后代码(将updateMap函数外置)
import Phaser from "../lib/phaser.js"; export default class Game extends Phaser.Scene { constructor() { super("game1"); } preload() { this.load.image( "Tileset", "https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/pixil-frame-0%20(17).png?v=1675985219390" ); this.load.tilemapTiledJSON( "map", "https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/Map.tmj?v=1675985261369" ); this.load.spritesheet( "player", "https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/pixil-frame-0%20(13).png?v=1675904194091", { frameWidth: 32, frameHeight: 32 } ); } create() { this.gameState = { map: "", cursors: "", }; this.gameState.map = this.make.tilemap({ key: "map" }); this.tiles = this.gameState.map.addTilesetImage("tileSet", "Tileset"); this.worldLayer = this.gameState.map.createLayer( "Block Layer", this.tiles, 0, 0 ); this.player = this.physics.add.sprite(0, 0, "player", 1); this.cameras.main.setBounds( 0, 0, this.gameState.map.widthInPixels, this.gameState.map.heightInPixels ); this.cameras.main.startFollow(this.player); this.gameState.cursors = this.input.keyboard.createCursorKeys(); } update() { if (this.gameState.cursors.left.isDown) { this.player.setVelocityX(-50); this.player.anims.play("left", true); } else if (this.gameState.cursors.right.isDown) { this.player.setVelocityX(50); this.player.anims.play("right", true); } else if (this.gameState.cursors.up.isDown) { this.player.setVelocityY(-50); } else if (this.gameState.cursors.down.isDown) { this.player.setVelocityY(-50); } else { this.player.setVelocityX(0); } updateMap(); } } function updateMap() { console.log(this.gameState); var origin = this.gameState.map.getTileAtWorldXY( this.player.x, this.player.y ); this.gameState.map.forEachTile(function (tile) { var dist = Phaser.Math.Distance.Chebyshev( origin.x, origin.y, tile.x, tile.y ); tile.setAlpha(1 - 0.1 * dist); }, this); }
问题解决
报错核心原因是updateMap函数的this上下文未指向当前Scene实例,导致无法访问this.gameState,以下是三种修复方案:
方案1:将updateMap定义为类方法
把updateMap改成Scene类的成员方法,调用时this会自动绑定到Scene实例:
import Phaser from "../lib/phaser.js"; export default class Game extends Phaser.Scene { constructor() { super("game1"); } preload() { // 原有代码不变 } create() { // 原有代码不变 } // 定义为类方法 updateMap() { console.log(this.gameState); var origin = this.gameState.map.getTileAtWorldXY( this.player.x, this.player.y ); this.gameState.map.forEachTile(function (tile) { var dist = Phaser.Math.Distance.Chebyshev( origin.x, origin.y, tile.x, tile.y ); tile.setAlpha(1 - 0.1 * dist); }, this); } update() { // 原有输入控制代码不变 // 调用类方法 this.updateMap(); } }
方案2:调用时绑定this
若保留独立函数,调用时用bind或箭头函数绑定上下文:
在update方法里修改调用逻辑:
// 用bind绑定当前Scene的this updateMap.bind(this)(); // 或用箭头函数包裹 (() => updateMap.call(this))();
方案3:用箭头函数定义updateMap
箭头函数会继承外部作用域的this,若在update内部定义函数,改成箭头函数即可:
update() { const updateMap = () => { console.log(this.gameState); // 原有updateMap代码不变 }; // 原有输入控制代码不变 updateMap(); }
额外注意:代码中向下移动的setVelocityY写为-50,会导致上下移动方向反转,建议改为50。
内容的提问来源于stack exchange,提问作者Vatsa Pandey
相关产品推荐
相关产品推荐

