Group and Mask
Group and masks are necessary for physical collision detection between objects. A group can be simply treated as the group a collision object is in, and a mask can be simply treated as the grouping objects that the collision object needs to collide with.
Collision Detection Principle
In Cocos Creator, collision detection is done in binary by bit, by "matching" the group value to the mask value to determine whether the condition is satisfied or not. The calculation of whether collision detection is allowed between objects is as follows:
(GroupA & MaskB) && (GroupB & MaskA)
As you can see from this formula, group A needs to be in the mask list of group B and group B needs to be in the mask list of group A in order for collision detection to occur between the two objects. How to combine the binary operation with the formula for allowing collision detection is the following part to understand. But before that, you need to configure Collision Matrix in Project Settings -> Physics -> Collision Matrix.
According to the configuration above, Cocos Creator will parse the data into the following values (shown here only for the part of the explanation).
- DEFAULT: Index value is
0
, the actual value of grouping is1<<0=1
, the binary value is0000 0001
; the actual value of mask value is1<<0=1
, the binary value is0000 0001
. - SELF_PLANE: Index value is
1
, the actual value of grouping is1<<1=2
, the binary value is0000 0010
; the actual value of mask value is(1<<3)+(1<<4)=24
, the binary value is0001 1000
. - ENEMY_BULLET: Index value is
4
, the actual value of the grouping is1<<4=16
, the binary value is0001 0000
; the actual value of the mask value is1<<1=2
, the binary value is0000 0010
.
Based on the data it is possible to do a calculation of whether there is a collision between the groups:
Does the group SELF_PLANE collide with the group DEFAULT?
The final value based on the above calculation is
0
, so there is no collision between the two groups.Whether the group SELF_PLANE collides with the group ENEMY_BULLET?
The final value based on the above calculation is greater than
0
, so there will be a collision between the two groups.
Note:
<<
The left shift operator, which is a type of bitwise operator, shifts to the left by pushing in 0 from the right and shedding the leftmost bit.s
Dynamically Set Group and Masks
Define Groups
Usually, in game development, you need to set collision-ready groups before the collision occurs and handle the related logic when the collision occurs. In Cocos Creator, all collision data is obtained as numeric values, which is not conducive to judgment during development. Therefore, it is possible to clearly know the meaning of each string of numbers by defining grouping objects or enumerations.
In can use the left shift operator (<<) to set the group or mask, and the corresponding value of either grouping object or grouping enumeration should be the same as the value defined in the collision matrix, otherwise there may be data inconsistency, which leads to judgment failure.
Way 1: Defined in an object
export const PHY_GROUP = {
DEFAULT: 1 << 0,
SELF_PLANE: 1 << 1,
ENEMY_PLANE = 1 << 2,
SELF_BULLET = 1 << 3,
ENEMY_BULLET = 1 << 4,
BULLET_PROP = 1 << 5,
};
Way 2: Defined in a enum
enum PHY_GROUP {
DEFAULT = 1 << 0,
SELF_PLANE = 1 << 1,
ENEMY_PLANE = 1 << 2,
SELF_BULLET = 1 << 3,
ENEMY_BULLET = 1 << 4,
BULLET_PROP = 1 << 5,
};
// If the enum needs to be displayed in the Inspector panel, you need to import the Enum function from the cc module and register the defined enum into the editor
Enum(PHY_GROUP);
Note: For historical reasons, the Enum function has special treatment for -1, so do not define properties with values of -1 if you are not familiar with them.
Set/Get Group
// This case uses the enumeration defined in the "Define Groups" section above
const rigid = this.getComponent(RigidBody);
// Equivalent to rigid.setGroup(1 << 1) or rigid.setGroup(1)
rigid.setGroup(PHY_GROUP.SELF_PLANE);
const group = rigid.getGroup();
Add/Remove Groups
// If the current group is not defined in the collision matrix, it can also be added dynamically
const group = 1 << 7;
const rigid = this.getComponent(RigidBody);
rigid.addGroup(group);
rigid.removeGroup(group);
Set/Get Mask
const rigid = this.getComponent(RigidBody);
const mask = (1 << 0) + (1 << 1); // Equivalent to 1 << 0 | 1 << 1
rigid.setMask(mask);
rigid.getMask();
Note: Here you need to pay attention to the priority of the operator. For example, 3 + 1 << 2 and 3 + (1 << 2) do not compute equal values, and the operator + has a higher priority than <<.
Using Masks
Masks can be defined based on grouping, e.g.
- Define a mask that detects only DEFAULT
const maskForGroup1 = PHY_GROUP.DEFAULT;
- Define a mask that detects DEFAULT and SELF_PLANE
const maskForGroup01 = PHY_GROUP.DEFAULT | PHY_GROUP.SELF_PLANE;
- Define a mask that is not detected by all groups
const maskForNone = 0;
- Define a mask that is detected by all groups
const maskForAll = 0xffffffff;
View Group or Mask in Binary
See the binary string representation by (value >>> 0).toString(2)
.