Collision Groups

Collision groups are a way for you to tell a game physics engine how to categorize colliders so that it can determine which colliders can collide with each other.

By assigning collision groups to a collider, as well as defining the other collision groups it can interact with, you can fully control what elements of your game do and do not interact with one another.

Collision Group Technicals

If you're familiar with game engines and collision groups, here's a technical breakdown of how HYTOPIA's collision groups operate.

Collision groups are used to determine which objects collide and generate collision and contact force events.

The automatically assigned default collision groups work great for most entity and block interactions, but you may want to create your own for more complex scenarios.

Additionally, a collider can belong to an interact with multiple collision groups.

15 collision groups exist. Collision groups use pairwise filtering using bit masks.

This filtering method is based on two 16-bit values:

  • The belongsTo groups (the 16 left-most bits of `self.0`).

  • The collidesWith mask (the 16 right-most bits of `self.0`).

An interaction is allowed between two filters `a` and `b` two conditions are met simultaneously:

  • The belongsTo groups of `a` has at least one bit set to `1` in common with the collidesWith mask of `b`.

  • The belongsTo groups of `b` has at least one bit set to `1` in common with the collidesWith mask of `a`.

In other words, interactions are allowed between two filter if the following condition is met:

((a >> 16) & b) != 0 && ((b >> 16) & a) != 0

Collision Groups

Below is a table of each available collision group and an explanation of its purpose. These groups can be accessed through the CollisionGroup enum, here.

Name
Group Value
Purpose

BLOCK

1 << 0

Default group assigned to blocks.

ENTITY

1 << 1

Default group assigned to entity colliders

ENTITY_SENSOR

1 << 2

Default group assigned to entity sensor colliders

PLAYER

1 << 3

Unused by default, but reserved for common player assignment & collider differentiation from regular entities.

GROUP_1

1 << 4

An unused collision group, available for any use.

GROUP_2

1 << 5

An unused collision group, available for any use.

GROUP_3

1 << 6

An unused collision group, available for any use.

GROUP_4

1 << 7

An unused collision group, available for any use.

GROUP_5

1 << 8

An unused collision group, available for any use.

GROUP_6

1 << 9

An unused collision group, available for any use.

GROUP_7

1 << 10

An unused collision group, available for any use.

GROUP_8

1 << 11

An unused collision group, available for any use.

GROUP_9

1 << 12

An unused collision group, available for any use.

GROUP_10

1 << 13

An unused collision group, available for any use.

GROUP_11

1 << 14

An unused collision group, available for any use.

GROUP_12

1 << 15

An unused collision group, available for any use.

ALL

0xFFFF

A special collision group equivalent to all collision groups.

No Player Collision Example

Here's a practical example of using collision groups. In some games, you may want to make it so that players do not collide with other players, and instead pass through each other.

We can do this with collision groups!

world.onPlayerJoin = player => {
  const playerEntity = new PlayerEntity({
    player,
    name: 'Player',
    modelUri: 'models/player.gltf',
    modelLoopedAnimations: ['idle'],
    modelScale: 0.5,
  });

  // Spawn the player entity first, so it has it's
  // default colliders automatically created.
  playerEntity.spawn(world, { x: 0, y: 1, z: 0 });
  
  // Prevent solid colliders (hitbox) from colliding with other Players
  playerEntity.setCollisionGroupsForSolidColliders({
    belongsTo: [ CollisionGroup.PLAYER ],
    collidesWith: [
      CollisionGroup.BLOCK, 
      CollisionGroup.ENTITY, 
      CollisionGroup.ENTITY_SENSOR
    ],
  });
  
  // Prevent sensor colliders from registering intersections
  // with other players. We do this to prevent things like sensor
  // colliders (such as ground sensor) from registering a ground contact
  // if is jumping through an entity or other player.
  playerEntity.setCollisionGroupsForSensorColliders({
    belongsTo: [ CollisionGroup.ENTITY_SENSOR ],
    collidesWith: [
      CollisionGroup.BLOCK,
      CollisionGroup.ENTITY
    ],
  });
}

Last updated