Collision Detection & Events

Respond to physics collisions in your scene:

// Add collision event handler
sphere.physicsImpostor.onCollideEvent = (collider, collidedWith) => {
    // collider is the sphere's impostor
    // collidedWith is the other object's impostor
    
    // Change material on collision
    const material = sphere.material;
    material.diffuseColor = new BABYLON.Color3(1, 0, 0); // Turn red
    
    // Reset color after delay
    setTimeout(() => {
        material.diffuseColor = new BABYLON.Color3(1, 1, 1); // Back to white
    }, 500);
    
    // Play sound on collision
    const impactVelocity = collider.getLinearVelocity().length();
    if (impactVelocity > 1) {
        const collisionSound = new BABYLON.Sound(
            "collision",
            "sounds/collision.mp3",
            scene,
            null,
            { volume: Math.min(impactVelocity / 10, 1) }
        );
        collisionSound.play();
    }
};

Create non-solid volumes that detect when objects enter them:

// Create a trigger zone
const triggerZone = BABYLON.MeshBuilder.CreateBox("trigger", {
    width: 10,
    height: 5,
    depth: 10
}, scene);
triggerZone.position.y = 2.5;
triggerZone.visibility = 0.2; // Semi-transparent
triggerZone.material = new BABYLON.StandardMaterial("triggerMat", scene);
triggerZone.material.diffuseColor = new BABYLON.Color3(0, 1, 0); // Green
triggerZone.material.alpha = 0.2;

// Make it a trigger volume (non-solid)
triggerZone.physicsImpostor = new BABYLON.PhysicsImpostor(
    triggerZone,
    BABYLON.PhysicsImpostor.BoxImpostor,
    { mass: 0, isTrigger: true },
    scene
);

// Track objects in the trigger zone
const objectsInZone = new Set();

// Handle collisions with the trigger
triggerZone.physicsImpostor.onCollideEvent = (collider, collidedWith) => {
    // Get the mesh associated with the colliding impostor
    const collidingMesh = collidedWith.object;
    
    // Track object entering the zone
    if (!objectsInZone.has(collidingMesh)) {
        objectsInZone.add(collidingMesh);
        console.log(`${collidingMesh.name} entered the trigger zone!`);
        
        // Change trigger color
        triggerZone.material.diffuseColor = new BABYLON.Color3(1, 0, 0);
    }
};

// Check if objects have left the zone
scene.onBeforeRenderObservable.add(() => {
    for (const obj of objectsInZone) {
        // Check if still intersecting
        if (!triggerZone.intersectsMesh(obj)) {
            objectsInZone.delete(obj);
            console.log(`${obj.name} left the trigger zone!`);
            
            // Change back to green if empty
            if (objectsInZone.size === 0) {
                triggerZone.material.diffuseColor = new BABYLON.Color3(0, 1, 0);
            }
        }
    }
});

Use raycasting to detect physics objects:

// Cast a ray through the physics world
const origin = new BABYLON.Vector3(0, 10, -10);
const direction = new BABYLON.Vector3(0, -1, 1).normalize();
const length = 20;
const raycastResult = scene.getPhysicsEngine().raycast(
    origin,
    direction,
    length
);

// Check if we hit something
if (raycastResult.hasHit) {
    console.log(`Hit object: ${raycastResult.body.object.name}`);
    console.log(`Hit point: ${raycastResult.hitPointWorld}`);
    console.log(`Hit normal: ${raycastResult.hitNormalWorld}`);
    console.log(`Hit distance: ${raycastResult.hitDistance}`);
}

// Visualize the ray
const rayHelper = new BABYLON.RayHelper(new BABYLON.Ray(origin, direction, length));
rayHelper.show(scene);

// Interactive raycasting with mouse click
scene.onPointerDown = (evt, pickResult) => {
    if (pickResult.hit) {
        // Cast ray from camera through click point
        const ray = scene.createPickingRay(
            scene.pointerX,
            scene.pointerY,
            BABYLON.Matrix.Identity(),
            camera
        );
        
        const raycastResult = scene.getPhysicsEngine().raycast(
            ray.origin,
            ray.direction,
            100
        );
        
        if (raycastResult.hasHit) {
            // Apply force at hit point
            const hitBody = raycastResult.body;
            const hitPoint = raycastResult.hitPointWorld;
            const force = ray.direction.scale(50); // Force strength
            
            hitBody.applyForce(force, hitPoint);
        }
    }
};