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