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);
            }
        }
    }
});