Increasing the speed of particle emitter after scene restarts

Hi, evetyone !
Get the problem with scene.restart();
In the scene “create” function i make a particle emitter with fixed frequency. WIth each scene.restart this frequency doubles. Particlel emitter destroys at scene “shutdown” event.
Speed of patricles is normal when i destroy and then recreate the emitter, buy after shutdown it doubles.

Here is the code:

this.shape1 = new Phaser.Geom.Ellipse(0, 0, 400, 200);
this.emitter1 = this.add.particles(275, 160, 'leafgreen', {           
            blendMode: 'ADD',
            lifespan: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(5000, 10000)}},
            quantity: 1,
  	    speedX: {onEmit: function(particle, key, t, value) {return (-1)*Phaser.Math.Between(10, 40)}},
            speedY: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(10, 40)}},
			rotate: {start: Phaser.Math.Between(0, 300), end: 359},
            frequency: 150,			
	    alpha: { values: [ 0, 0.8, 0.01 ], interpolation: 'catmull', ease: Phaser.Math.Easing.Sine.Out },
            scale: { start: 0.1, end: 0.05 },
	    advance: 5000
        }).setDepth(2);
        this.emitter1.addEmitZone({ type: 'random', source: this.shape1, quantity: 64 });

At shutdown event:

this.emitter1.stop(true);
this.emitter1.destroy(true);

Same code in Phaser sandbox cause no trouble even without destroing emitter.
What could be the problem?

I’m using Phaser 3.8 and Phaser Editor 2.1.18

Thanx!

:wave:

Try removing these.

Not worked. But i noticed that sprite animations doubles too. Found on forum this:

this.events.off('update');

and put it in shutdown event and it works, but i don’t understand why. any ideas?

Which exact Phaser version is in the console, and can you show the whole scene code?

I tried version 3.85 and latest 3.86. At this moment i’m using version 3.86
Also in first boot scene in create function i launch UI scene witch shows user data, buttons, etc

this.scene.launch('uiscene').bringToTop('uiscene');

This scene is third and here is the code

class gamescene extends Phaser.Scene {
	
	constructor() {
	
		super("gamescene");
		
	}

//= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
	init() {
		// this is just for some usefull funcs, no event handlers or something here
		this.mlh = new MyLoaderHelper(this);

// does sprite objects destroys after scene restart or i should destroy them manualy ?
                this.objectsToDestroy = []; // array of sprite objects to destroy at shutdown event
		this.game.globals.currentScene = this; // this for "user interface" purpose
	}

// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

	create() {
		
		this.mlh.myConsoleDebug('create');				

		this.createEvents();
		this.createScene();

		this.generateLeafs();
		
		this.debugCamera();		

	}		

//  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
	update (time, delta) {
		if (this.controls != undefined) this.controls.update(delta); // cam controls
	}		
	
//  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
	createEvents() {
		this.mlh.myConsoleDebug('create events');
		
		this.input.off(Phaser.Input.Events.POINTER_UP).on(Phaser.Input.Events.POINTER_UP, (p) => {			
			this.scene.restart();
			//this.scene.start('gamescene'); // gamescene = this scene		// do the same effect as this.scene.restart(); //imho
		});						
		this.events.off(Phaser.Scenes.Events.SHUTDOWN).once(Phaser.Scenes.Events.SHUTDOWN, () => {
			this.mlh.myConsoleDebug('shutdown event');
			this.destroyObjects();
			this.registry.destroy();  // i found it at this forum somewhere				
			this.events.off('update'); // this helps to fix the speed increasing
		});				
		this.events.off(Phaser.Scenes.Events.DESTROY).once(Phaser.Scenes.Events.DESTROY, () => {
			this.mlh.myConsoleDebug('destroy event');
			this.destroyObjects();
			this.registry.destroy();
			this.events.off('update');
		});
	}
		
	//  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
	createScene(){
		let padd = 80; // road padding
		this.bg1 = this.add.sprite(0, 0, 's1bg1').setOrigin(0,0).setDepth(opt.DEPTH_BACKGROUND+2);
		let k = this.game.config.height/(this.bg1.height - padd);			
		this.bg1.setScale(k);		
		
		this.bg2 = this.add.sprite(0, 0, 's1bg2').setOrigin(0,0).setDepth(opt.DEPTH_BACKGROUND);
		this.bg2.setScale(k);		
		
		let ray = this.add.sprite(665, 120, 'ray').setOrigin(0.5,0.05).setDepth(opt.DEPTH_BACKGROUND+3).setBlendMode(Phaser.BlendModes.ADD).setAlpha(0.2).setScale(1.2);


		this.mlh.tweenAlpha(ray, 0.2, 0.8, 5000, Phaser.Math.Easing.Sine.Out, -1, true);
		this.mlh.tweenAngle(ray, 7, -7, 12000, Phaser.Math.Easing.Sine.InOut, -1, true)
		
		let ray2 = this.add.sprite(1200, 125, 'ray2').setOrigin(0,0).setDepth(opt.DEPTH_BACKGROUND+3).setBlendMode(Phaser.BlendModes.ADD).setAlpha(0.5).setScale(1);

		this.mlh.tweenAlpha(ray2, 0.1, 0.6, 7000, Phaser.Math.Easing.Sine.Out, -1, true);
		this.mlh.tweenAngle(ray2, ray2.angle, 10, 12000, Phaser.Math.Easing.Sine.InOut, -1, true);				
		
		this.tweens.add({
		    targets: lamp2, // this is ARRAY		    
		    alpha: { from: 0.1, to: 0.7 },
			ease: Phaser.Math.Easing.Bounce.Out,		    
		    duration: 500,
		    repeat: -1,
			yoyo: true,
			repeatDelay: 3000		    		
		});
			
				
		Phaser.Utils.Array.Add(this.objectsToDestroy, [this.bg1, this.bg2, ray, ray2]);
		
		this.sceneWidth = this.bg1.width*k;
		this.sceneHeight = this.bg1.height*k;
		
		this.cameras.main.setBounds(0, 0, this.sceneWidth, this.sceneHeight);
		this.physics.world.setBounds(0, 0, this.sceneWidth, this.sceneHeight);
	}



	//  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
	generateLeafs(){
		
		this.mlh.myConsoleDebug('generateLeafs');				
		
		// left green tree
		this.shape1 = new Phaser.Geom.Ellipse(0, 0, 400, 200);

//#####  this emitters 1,2,3,... has the double speed effect

        this.emitter1 = this.add.particles(275, 160, 'leafgreen', {           
            blendMode: 'ADD',
            lifespan: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(7000, 10000)}},
            quantity: 1,
			speedX: {onEmit: function(particle, key, t, value) {return (-1)*Phaser.Math.Between(10, 30)}},
            speedY: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(10, 40)}},
			rotate: {start: Phaser.Math.Between(0, 300), end: 359},
            frequency: 150,
			//alpha: {start: 0.8, end: 0.01},
			alpha: { values: [ 0, 0.8, 0.01 ], interpolation: 'catmull', ease: Phaser.Math.Easing.Sine.Out },
            scale: { start: 0.1, end: 0.05 },
			advance: 5000
        }).setDepth(opt.DEPTH_BACKGROUND+2);
        this.emitter1.addEmitZone({ type: 'random', source: this.shape1, quantity: 64 });

		// center green tree
		this.shape2 = new Phaser.Geom.Ellipse(0, 0, 300, 180);
        this.emitter2 = this.add.particles(800, 170, 'leafgreen', {           
            blendMode: 'ADD',
            lifespan: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(5000, 10000)}},
            quantity: 1,
			speedX: {onEmit: function(particle, key, t, value) {return (-1)*Phaser.Math.Between(10, 40)}},
            speedY: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(10, 40)}},
			rotate: {start: Phaser.Math.Between(0, 300), end: 359},
            frequency: 150,
			//alpha: {start: 0.8, end: 0.01},
			alpha: { values: [ 0, 0.8, 0.01 ], interpolation: 'catmull', ease: Phaser.Math.Easing.Sine.Out },
            scale: { start: 0.1, end: 0.05 },
			advance: 5000
        }).setDepth(opt.DEPTH_BACKGROUND+2);
        this.emitter2.addEmitZone({ type: 'random', source: this.shape2, quantity: 64 });

		// right green tree
		this.shape3 = new Phaser.Geom.Ellipse(0, 0, 260, 120);
        this.emitter3 = this.add.particles(1550, 160, 'leafgreen', {           
            blendMode: 'ADD',
            lifespan: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(5000, 10000)}},
            quantity: 1,
			speedX: {onEmit: function(particle, key, t, value) {return (-1)*Phaser.Math.Between(10, 40)}},
            speedY: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(10, 40)}},
			rotate: {start: Phaser.Math.Between(0, 300), end: 359},
            frequency: 150,
			//alpha: {start: 0.8, end: 0.01},
			alpha: { values: [ 0, 0.8, 0.01 ], interpolation: 'catmull', ease: Phaser.Math.Easing.Sine.Out },
            scale: { start: 0.1, end: 0.05 },
			advance: 5000
        }).setDepth(opt.DEPTH_BACKGROUND+2);
        this.emitter3.addEmitZone({ type: 'random', source: this.shape3, quantity: 50 });

		// right green tree
		this.shape4 = new Phaser.Geom.Ellipse(0, 0, 100, 70);
        this.emitter4 = this.add.particles(560, 270, 'leaforange', {           
            //blendMode: 'ADD',
            lifespan: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(5000, 10000)}},
            quantity: 1,
			speedX: {onEmit: function(particle, key, t, value) {return (-1)*Phaser.Math.Between(10, 40)}},
            speedY: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(10, 40)}},
			rotate: {start: Phaser.Math.Between(0, 300), end: 359},
            frequency: 200,
			//alpha: {start: 0.8, end: 0.01},
			alpha: { values: [ 0, 0.8, 0.01 ], interpolation: 'catmull', ease: Phaser.Math.Easing.Sine.Out },
            scale: { start: 0.08, end: 0.01 },
			advance: 2000
        }).setDepth(opt.DEPTH_BACKGROUND+2);
        this.emitter4.addEmitZone({ type: 'random', source: this.shape4, quantity: 35 });

		// red tree
		this.shape5 = new Phaser.Geom.Ellipse(0, 0, 100, 70);
        this.emitter5 = this.add.particles(800, 310, 'leaforangedark', {           
            //blendMode: 'ADD',
            lifespan: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(3000, 5000)}},
            quantity: 1,
			speedX: {onEmit: function(particle, key, t, value) {return (-1)*Phaser.Math.Between(10, 40)}},
            speedY: {onEmit: function(particle, key, t, value) {return Phaser.Math.Between(10, 40)}},
			rotate: {start: Phaser.Math.Between(0, 300), end: 359},
            frequency: 250,
			//alpha: {start: 0.8, end: 0.01},
			alpha: { values: [ 0, 0.8, 0.01 ], interpolation: 'catmull', ease: Phaser.Math.Easing.Sine.Out },
            scale: { start: 0.1, end: 0.02 },
			advance: 1500
        }).setDepth(opt.DEPTH_BACKGROUND+2);
        this.emitter5.addEmitZone({ type: 'random', source: this.shape5, quantity: 30 });

		Phaser.Utils.Array.Add(this.objectsToDestroy, [this.emitter1, this.emitter2, this.emitter3, this.emitter4, this.emitter5]);
	}
	

	
	//  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
	destroyObjects(){				
		
// removing this.emitter1.stop(true) has no effect as i wrote earlier
		if (this.emitter1 != undefined) this.emitter1.stop(true);
		if (this.emitter2 != undefined) this.emitter2.stop(true);
		if (this.emitter3 != undefined)	this.emitter3.stop(true);
		if (this.emitter4 != undefined) this.emitter4.stop(true);
		if (this.emitter5 != undefined) this.emitter5.stop(true);
		if (this.smoke != undefined)    this.smoke.stop(true);
		
                // is this correct way to destroy shape? do i need to destroy it?
		this.shape1.setEmpty(); this.shape1 = undefined;		
		this.shape2.setEmpty(); this.shape2 = undefined;
		this.shape3.setEmpty(); this.shape3 = undefined;
		this.shape4.setEmpty(); this.shape4 = undefined;
		this.shape5.setEmpty(); this.shape5 = undefined;
				
		if (this.objectsToDestroy != undefined && this.objectsToDestroy.length > 0) {
			
			this.mlh.myConsoleDebug('objectsToDestroy length: ' + this.objectsToDestroy.length);			
			Phaser.Utils.Array.RemoveBetween(this.objectsToDestroy, 0, this.objectsToDestroy.length, (item) => {
				if (item != undefined) {					
					this.tweens.killTweensOf(item);
					item.destroy(true);
					item = undefined;
				}
			}, this);
						
			this.objectsToDestroy = undefined;
			this.sceneInitialized = false;
			
		} else this.mlh.myConsoleDebug('#destroyObjects: no objects to destroy');
		
		this.mlh = null; // how to destroy class instance correctly?
		this.cursors = null;		
	}
		
		
	//  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * 
	debugCamera() {
				
		if (this.game.globals.isDebug) {
			this.mlh.myConsoleDebug('debugCamera');
			this.cursors = this.input.keyboard.createCursorKeys();
			const controlConfig = {
	            camera: this.cameras.main,
	            left: this.cursors.left,
	            right: this.cursors.right,
	            up: this.cursors.up,
	            down: this.cursors.down,
	            zoomIn: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q),
	            zoomOut: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E),
	            acceleration: 0.03,
	            drag: 0.001,
	            maxSpeed: 1.0
	        };
	
	        this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);
		}
	}	
		
}

Remove these:

The first one is causing the double-update problem because it doesn’t let the scene shut down.

Then remove these:

Because the scene still needs to update after restarting.

Game objects on the scene update list or display list are destroyed automatically when the scene stops or restarts. You don’t have to do anything with those.

You probably don’t want to destroy the game registry because it’s unusable after that. But also, if you’ve never put data in there then there’s nothing to remove, so just ignore it.

God damn, brilliantly. It works! Greatly thanx!
My bad! I thought that the code

this.events.off(Phaser.Scenes.Events.SHUTDOWN).once(Phaser.Scenes.Events.SHUTDOWN, () => { ... });

turn off and then turn on (for 1 fire) event handler.