removeInteractive() error when called in pointerover event's handler
Version
- Phaser Version: 3.60.0-beta.18
- Operating system: MacOS 13.x
- Browser: Chrome 109
Description
Calling removeInteractive on a game object after a pointover event results in the following error. calling disableInteractive before calling remove, sometimes helps. It might take as many as 10 to 20 events to get the error.
Uncaught TypeError: Cannot read properties of undefined (reading 'cursor')
at InputManager.resetCursor (3.60.0-beta.18.js:96605:31)
at InputPlugin.disable (3.60.0-beta.18.js:98115:25)
at InputPlugin.clear (3.60.0-beta.18.js:98031:14)
at InputPlugin.preUpdate (3.60.0-beta.18.js:97769:22)
at EventEmitter.emit (3.60.0-beta.18.js:220:33)
at Systems.step (3.60.0-beta.18.js:186633:16)
at SceneManager.update (3.60.0-beta.18.js:183875:21)
at Game.step (3.60.0-beta.18.js:16986:20)
at TimeStep.step (3.60.0-beta.18.js:17991:14)
at step (3.60.0-beta.18.js:30961:19)
Example Test Code
class Bat extends Phaser.GameObjects.Container
{
constructor (scene, x, y)
{
super(scene, x, y);
const body = scene.add.image(0, 0, 'assets', 'Body02_01');
const wing1 = scene.add.image(-50, 10, 'assets', 'Wing02_01').setOrigin(1, 0.5);
const wing2 = scene.add.image(50, 10, 'assets', 'Wing02_02').setOrigin(0, 0.5);
this.add([ wing2, body, wing1 ]);
this.body = body;
this.wing1 = wing1;
this.wing2 = wing2;
scene.add.existing(this);
body.setInteractive(new Phaser.Geom.Circle(170, 170, 100), Phaser.Geom.Circle.Contains);
body.once('pointerover', () => this.kill());
this.fly();
}
fly ()
{
const y = this.y - (Phaser.Math.Between(150, 280));
this.scene.tweens.add({
targets: this,
y,
ease: 'sine.inout',
yoyo: true,
repeat: -1,
duration: Phaser.Math.Between(900, 1200)
});
this.scene.tweens.add({
targets: this.wing1,
angle: { start: -20, to: 20 },
ease: 'sine.inout',
yoyo: true,
repeat: -1,
duration: 200
});
this.scene.tweens.add({
targets: this.wing2,
angle: { start: 20, to: -20 },
ease: 'sine.inout',
yoyo: true,
repeat: -1,
duration: 200
});
}
kill ()
{
this.body.removeInteractive()
this.scene.tweens.killTweensOf([ this, this.wing1, this.wing2 ]);
this.wing1.setAngle(20);
this.wing2.setAngle(-20);
this.body.setFrame('Body02_02');
this.scene.tweens.chain({
targets: this,
tweens: [
{
y: '-=100',
angle: 270,
scale: 0.3,
duration: 500
},
{
angle: 180,
y: 800,
ease: 'power1',
duration: 500
}
],
onComplete: () => {
const x = Phaser.Math.Between(100, 700);
const y = Phaser.Math.Between(300, 500);
const scale = Phaser.Math.FloatBetween(0.4, 1);
new Bat(this.scene, x, y).setScale(scale);
this.destroy();
}
});
}
}
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.image('bg', 'assets/skies/spooky.png');
this.load.atlas('assets', 'assets/atlas/tweenparts.png', 'assets/atlas/tweenparts.json');
}
create ()
{
this.add.image(400, 300, 'bg');
new Bat(this, 600, 300).setScale(0.4);
new Bat(this, 180, 400).setScale(0.7);
new Bat(this, 440, 500);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Additional Information
Need anything additional from me to reproduce?
Still having this issue with 3.60.0 and Chrome 112. Here is a less complex example. It might take a couple dozen times to get the error, but usually i'll see it after 3 or 4:
class Example extends Phaser.Scene
{
preload ()
{
this.load.image('eye', 'assets/pics/lance-overdose-loader-eye.png');
}
create ()
{
const sprite = this.add.sprite(400, 300, 'eye').setInteractive();
sprite.on('pointerover', function (event)
{
sprite.removeInteractive();
setTimeout(()=>{
sprite.setInteractive()
this.setTint(0xffffff)
}, 300)
this.setTint(0xff0000);
});
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Adding {useHandCursor: true} to the setInteractive config with the above example helps visualize the issue.
Thank you for submitting this issue. We have fixed this and the fix has been pushed to the master branch. It will be part of the next release. If you get time to build and test it for yourself we would appreciate that.