Maximum Collision Categories in Matter.js
In Matter.js, the maximum number of unique collision categories you can define is 32. This limit is governed by the underlying bitmask system that the physics engine uses to process collision filtering, combined with JavaScript's 32-bit integer constraints during bitwise operations. This article covers why this 32-category ceiling exists, how collision filtering works with bitmasks, and practical alternatives if your simulation requires more complex interaction rules.
Why the Limit Is 32 Categories
Matter.js relies on bitwise operations to efficiently calculate
whether two bodies should collide. The properties responsible for this
are collisionFilter.category and
collisionFilter.mask.
In JavaScript, bitwise operators (such as AND
(&) and OR (|)) treat their
operands as a sequence of 32 bits, regardless of JavaScript's standard
64-bit floating-point numeric type. Because a bitmask assigns one unique
binary bit to represent each collision category, there are exactly 32
available bit positions:
- Category 1:
0x0001(\(2^0\)) - Category 2:
0x0002(\(2^1\)) - Category 3:
0x0004(\(2^2\)) - ...
- Category 31:
0x40000000(\(2^{30}\)) - Category 32:
0x80000000(\(2^{31}\))
Attempting to define a 33rd category using \(2^{32}\) overflows the 32-bit integer boundary, wrapping the value and causing unexpected collisions.
How Matter.js Determines Collisions
For two bodies, Body A and Body B, to collide, two conditions must evaluate to true:
(bodyA.collisionFilter.category & bodyB.collisionFilter.mask) !== 0 &&
(bodyB.collisionFilter.category & bodyA.collisionFilter.mask) !== 0category: Defines what category the body belongs to (typically a single bit flag).mask: Defines which categories the body can collide with (a combination of bit flags combined with the bitwise OR|operator).group: An optional higher-priority rule. If both bodies share the same positive group ID, they always collide; if they share the same negative group ID, they never collide.
Workarounds for More Than 32 Interaction Types
If a project requires more than 32 distinct interaction states, relying strictly on bitmask categories is not sufficient. Common approaches to handle larger scale interaction models include:
- Leverage
collisionFilter.group: Use signed group integers for strict non-colliding or always-colliding rules among groups of objects to free up bit categories. - Filter with Collision Events: Set broad categories
and use the
collisionStartorcollisionActiveevents to cancel or apply custom response logic manually when specific bodies touch. - Dynamic Category Reassignment: If all 32 categories
are not active simultaneously across all objects, reassign
categoryandmaskvalues dynamically based on object proximity or current game state.