Collision callback firing multiple times

I’m creating an rpg/jrpg using Phaser 3. When the hero collides with a monster, from a group, I’m switching/starting a battle scene for turn based combat:

this.physics.add.collider(this.player, this.spawns, this.onMeetEnemy, false, this);

onMeetEnemy(player, monster) {        
    this.cameras.main.shake(300);   this.cameras.main.on('camerashakecomplete', () => {
      this.scene.start('Battle', {player: this.player, monster: monster});
    });
  }

The collisions happen and the battle scene is started. But, the battle scene is created multiple times, like 8-9 times. I understand why, because they are still colliding. So how do I get the collision callback function to fire only once and commence battle? My best guess is set a variable that says we’re fighting, don’t execute onMeetEnemy anymore until further notice. Also should I be starting or switching to Battle?

Hope I was clear enough and thank you for the help.

EDIT: I have changed meetEnemy() to:

onMeetEnemy(player, monster) {        
    this.cameras.main.shake(300);
    this.cameras.main.on('camerashakecomplete', () => {
      if(!this.isFighting){
        this.isFighting = true;
        // start battle
        //this.scene.switch('Battle', {player: this.player, monster: monster});
        this.scene.start('Battle', {player: this.player, monster: monster});
      }
    });
  }

Seems to work, but is this the best/ most common way to do this?

This way is fine - I do similar things.
You could also disable the body, or (I’m a bit less sure as I don’t know which physics you’re working with) remove the listener (so something like this.physics.remove.collider…)

The only thing you’d need to be careful of is if you return to the scene - just making sure you’ve reset everything. With the way you’re doing it, it’s really easy to reset this.isFighting.

1 Like

I will check into disabling the body and removing the listener. I am using arcade physics right now. I did read some stuff about removing the listener, but if the hero flees, I may still need it, but I suppose I could recreate it as needed. Thank you for pointing me in the right direction.

Looks like processCallback in the collide function may be the way to do it the phaser way.

processCallback, the fourth parameter of the collider function, is the correct answer, I believe. Thanks to charlie_says’ answer I went in search of and found: how-to-disable-collision-for-body. And here is my final collider that fires once until the variable inBattleScene is reset.

in Game scene create method:

this.inBattleScene = false;

this.physics.add.collider(
  this.player, 
  this.spawns, 
  this.onMeetEnemy, // collision stuff, launch battle scene
  this.enterBattleScene // should this collider fire? must return true or false
);

then create functions outside create:

enterBattleScene(){
  if (!this.inBattleScene) {
    this.inBattleScene = true;
    return true;  
  }  
  return false;
}

onMeetEnemy(player, monster) {        
  this.cameras.main.shake(300);
  this.cameras.main.on('camerashakecomplete', () => {
    this.scene.start('Battle', {player: this.player, monster: monster});
  });
}