Hello, I’m using Phaser’s Arcade Physics and working with collision categories. My goal is to control how different units (players and enemies) collide in various scenarios. Specifically, I want to:
- Enable collisions between all units (players vs. players, enemies vs. enemies, and players vs. enemies) by default.
- Disable collisions between friendly units (e.g., player vs. player or enemy vs. enemy) when specific units are “firing” or performing certain actions.
- Restore friendly collisions when the units return to a different state (e.g., melee combat).
Here’s how I currently have everything set up:
Scene Setup
In the scene constructor, I define collision categories using this.physics.nextCategory()
:
this.categories = {
enemy: this.physics.nextCategory(),
player: this.physics.nextCategory(),
};
I also create Arcade Physics groups for the different unit types:
context.physicsGroups = {
enemyGroups: context.physics.add.group(),
playerGroups: context.physics.add.group(),
enemyBaseZones: context.physics.add.group(),
playerBaseZones: context.physics.add.group(),
arrows: context.physics.add.group(),
};
Then, I add colliders for different scenarios:
context.physics.add.collider(
context.physicsGroups.playerGroups,
context.physicsGroups.enemyGroups,
handleOpponentCollision,
undefined,
context
);
context.physics.add.collider(
context.physicsGroups.enemyGroups,
context.physicsGroups.enemyGroups,
handleFriendlyCollision,
undefined,
context
);
context.physics.add.collider(
context.physicsGroups.playerGroups,
context.physicsGroups.playerGroups,
handleFriendlyCollision,
undefined,
context
);
In the constructor for each unit, I assign the collision category dynamically based on the unit’s side (player or enemy):
if (this.info.unitSide === "enemy") {
this.body.setCollisionCategory(this.scene.categories.enemy);
} else {
this.body.setCollisionCategory(this.scene.categories.player);
}
console.log(this.body.collisionCategory); // Verifying category assignment
// By default, allow collisions with both categories
this.body.setCollidesWith([this.scene.categories.enemy, this.scene.categories.player]);
When the unit enters a “firing” state, I disable friendly collisions:
this.body.removeCollidesWith(
this.info.unitSide === "enemy" ? this.scene.categories.enemy : this.scene.categories.player
);
When the unit returns to melee combat, I restore collisions with friendly units:
this.body.setCollidesWith([this.scene.categories.enemy, this.scene.categories.player]);
The Problem
While testing, I noticed that enemy units (Category X) and player units (Category Y) no longer collide with each other. They completely ignore each other, even though the categories are set correctly.
Here are some additional details:
- Enemy units have a collision category
X
and player units have categoryY
. - I’ve verified the categories are being assigned correctly by logging
this.body.collisionCategory
. - When collisions stop, neither
handleOpponentCollision
norhandleFriendlyCollision
callbacks are triggered.
My Understanding of the Problem
From the Phaser documentation, Arcade Physics supports setCollisionCategory()
, setCollidesWith()
, addCollidesWith()
, and removeCollidesWith()
. And I don’t want to use Matter physics.
However, something is causing the collisions to break entirely, and I can’t figure out why.
My Question
- Is there something I’m missing in how Arcade Physics handles collision categories?
- Are there known limitations or specific configurations required to make these methods work with Arcade Physics?
- Does this approach look correct, or should I manage this differently?
Any guidance would be greatly appreciated. Thank you!