Collision detection

Collision detection serves the essential purpose of determining when and how objects within the game world interact with each other. It plays a crucial role in creating realistic and engaging gameplay experiences.

  1. Prevent moving through objects: Collision detection is necessary to ensure that the player or other objects don't move through other objects, walls or the ground. If any object is given a collision shape, it will by prevent other objects with a collision object from intersecting with it.

  2. Physics simulation: In some games, physics simulations are used to create realistic movement and interactions. Collision detection is a key component of these simulations, allowing objects to bounce, slide, or respond to forces naturally.

  3. Triggers and Events: Collision detection can be used to trigger events or scripts when specific conditions are met. For example, walking into a specific area might trigger a cutscene or the activation of a hidden pathway.

Creating collision shapes

For the physics engine to know the shape of objects, the shape of the object needs to be provided using specific primitives. The graphical representation of an object that is rendered is often not the same as the physical representation.

As almost all objects in a scene will have need to have some physical shape defined, configuring these manually via code or in the editor could be very time consuming. Instead, this should be integrated in the asset creation pipeline. Any imported 3D model will have a collision shape generated automatically that best fits the 3D model. However, this may not be appropriate for your game play. In this case you can design the collision shapes in your 3D modeling tool and export these together with your model using specific naming conventions.

A physical shape can be supplied when creating a mesh programmatically using the MeshComponent. Instead of providing just a THREE.Mesh object, you can instead pass in a PhysicalShapeMesh which in addition to taking a geometry and material can take a shape object that describes the physical shape.

The following collision shapes can be used

  • BoxCollisionShape

  • PlaneCollisionShape

  • SphereCollisionShape

  • CylinderCollisionShape

  • ConvexPolyhedronCollisionShape

  • TrimeshCollisionShape

  • MeshCollisionShape

  • CapsuleCollisionShape

Detecting actor collisions

In the example code below, we are creating two actors both with a mesh component to give them a visible geometry and a collision shape. Using the physics system, we can create a subscription on collisions with actors of a specific type. Every time the ball actor hits a target actor, the collision event will happen. When this even happen you could for example increase a player's score or trigger some other action in your game.

@Actor()
class Ball extends BaseActor {
    private physicsSystem = inject(PhysicsSystem)
    private mesh = attach(MeshComponent, {
      mass: 1,
      bodyType: PhysicsBodyType.dynamic,
      object: new PhysicalShapeMesh(
          new SphereGeometry(.2, 20, 10),
          new MeshStandardMaterial({ color: 0xeff542 }),
          new SphereCollisionShape(.2))
    })
    
    onInit() {
      this.physicsSystem.onCollisionWithActorType(this, Target)
        .subscribe(other => {
          console.log('Hit target actor', other)
        })
    }
}

@Actor()
class Target extends BaseActor {
    private mesh = attach(MeshComponent, {
      bodyType: PhysicsBodyType.static,
      continousCollisionDetection: true,
      object: new PhysicalShapeMesh(
        new BoxGeometry(1, 1, 0.1),
        new MeshStandardMaterial({ color: 0xeff542 }),
        new BoxCollisionShape(new Vector3(1, 1, 0.1)))
    })
}

Collision events

You can subscribe to collision events on the physics system.

  • onBeginContact - When the actor starts getting contact with any surface

  • onEndContact - When the actor stops having contact with a surface

  • onHasContactChanged - When the actor either has contact with any surface or not in contact with anything changes.

  • onCollisionWithActor - When the actor collides with another specific actor.

  • onCollisionWithActorType - When the actor collides with any actor of a specific class.

  • onBeginOverlapWithActorType - When the actor starts overlapping with another actor for a specific class. This is useful for trigger volumes.

  • onEndOverlapWithActorType - When the actor stop overlapping with another actor for a specific class. This is useful for trigger volumes.

  • onBeginOverlapWithActor - When the actor starts overlapping with another specific actor. This is useful for trigger volumes.

  • onEndOverlapWithActor - When the actor stops overlapping with another specific actor. This is useful for trigger volumes.

Last updated