Collision enter - exit event?

Is there any way to trigger a collision enter and exit callback? I want to trigger a sound when a user overlaps a gameobject. But I only want the sound to trigger when the user first overlaps the gameobject. As it stands now the sound is being triggered multiple times because the overlap method is being called for as long as the user is overlapping the gameobject (if that makes sense!).

Maybe you want to set a flag of some sort inside the collision callback and reset it at the end of the scene’s update method or as soon as the sounds ends.

1 Like

6 Likes

I was trying to do the same but instead of adding a dynamic Body to the zone, I was adding a StaticBody. My code wasn’t working and after hours of searching i found that the StaticBodies don’t have an update() method that reset the touching and wasTouching flags. So once an overlap was triggered, the touching and wasTouching objects will keep the left/right/up/down flags set to true, even when the StaticBody is not colliding/overlapping anymore.

Is this the intended behaviour or is this a bug? :thinking:

It is intended that static bodies never update. Maybe the docs should say “Never use these properties”. I think they’re kept for compatibility with the dynamic bodies.

1 Like

My answer comes quite late, but this might be useful anyway…
I faced almost the same issue considering continuous collision detection which triggered multiple detection while only one is useful.
To solve that issue, when I first enter the collision callback function (the very first time the collision is detected), I disable the body of one object.

Considering my object is a laser fired by a spaceship, I do that:

// The collision callback function
function laserEnemyCollide(enemy, laser)
{
laser.disableBody(false, false);

}

When the body is disabled, then there is no more collision detection triggers.

At some point, I need to re-enable the laser if I want that Phaser detects again the collisions so when I spawn a new laser fire, then I re-enable the body:

// the ‘fire()’ function is called when player presses spacebar key to fire a new laser beam
fire(x, y)
{
this.body.reset(x, y);
this.body.setEnable(true);

}

And it solved my issue! I have only one call to my collision detection function while there might be multiple detections.

Hi, I was facing the same question; Having had to deal with similar needs in other engines (box2D, chipmunk) I must say your approach is just perfect. No ghost collision remaining, no undispatched “detach” events lost in the manifold. Just clever. Thanks!

Hopefully I’m missing something in the Phaser docs somewhere, as I’ve come up with a very bad solution to this problem which nonetheless seems to be the best one.

In my game I have “portals”. When the player collides with one of these portals, I only want the collision to register once. When the player stops colliding with the portal, I want to reset the collision so that the collision can be triggered again when the player re-enters.

Here’s a code-dump of how I’ve solved this in my project:

In create

const enterPortal = (player, portal) => {
  if (!player.collidingEditPortal) {
    console.log("portal");
    player.collidingEditPortal = portal;
  }
};

this.physics.add.overlap(
  this.player,
  this.portals,
  enterPortal,
  null,
  this
);

In update:

this.portals.children.entries.forEach(portal => {
      if (this.player.collidingEditPortal) {
        if (
          this.player.collidingEditPortal === portal &&
          this.player.body.touching.none
        ) {
          this.player.collidingEditPortal = null;
        }
      }
    });

So when the player first collides with a portal, “portal” is logged in the console only once. The player needs to leave and re-enter for the “portal” to log again.

It works - but is very messy. If anyone could show me a better way to do this, please do! (It would be great if Phaser had an onCollisionEnd callback… but alas!!)