Performance Optimization

Optimize physics for better performance:

// Configure physics engine for performance
const physicsEngine = scene.getPhysicsEngine();

// Set physics timestep (smaller = more accurate but slower)
physicsEngine.setTimeStep(1/60);

// Enable sub-stepping for more stable simulation
physicsEngine.setSubTimeStep(2); // 2 sub-steps per frame

// Performance techniques

// 1. Use simpler collision shapes
// Sphere and box impostors are much faster than mesh impostors
const complexMesh = BABYLON.MeshBuilder.CreateTorusKnot("complex", {}, scene);
complexMesh.position.y = 5;

// Use a bounding box instead of exact mesh shape
const boundingInfo = complexMesh.getBoundingInfo();
const dimensions = boundingInfo.boundingBox.extendSize.scale(2);
complexMesh.physicsImpostor = new BABYLON.PhysicsImpostor(
    complexMesh,
    BABYLON.PhysicsImpostor.BoxImpostor,
    { mass: 1, friction: 0.5, restitution: 0.3 },
    scene
);

// 2. Use sleep states for static objects
ground.physicsImpostor.sleep(); // Put a static object to sleep

// 3. Group small objects into compound objects
const smallObjectsParent = new BABYLON.Mesh("smallObjects", scene);
for (let i = 0; i < 10; i++) {
    const small = BABYLON.MeshBuilder.CreateBox(`small${i}`, {size: 0.2}, scene);
    small.position.x = i * 0.3 - 1.5;
    small.position.y = 2;
    small.parent = smallObjectsParent;
}

// Treat them as one physics object
smallObjectsParent.physicsImpostor = new BABYLON.PhysicsImpostor(
    smallObjectsParent,
    BABYLON.PhysicsImpostor.BoxImpostor,
    { mass: 2, friction: 0.5 },
    scene
);

// 4. Disable physics for distant objects
// Create a function to check distance from camera
const maxPhysicsDistance = 50; // Maximum distance for active physics

scene.onBeforeRenderObservable.add(() => {
    // Get active camera position
    const cameraPosition = scene.activeCamera.position;
    
    // Check all physics objects
    for (const mesh of scene.meshes) {
        if (mesh.physicsImpostor) {
            const distance = BABYLON.Vector3.Distance(mesh.position, cameraPosition);
            
            // Enable/disable physics based on distance
            if (distance > maxPhysicsDistance) {
                if (!mesh.physicsImpostor.isDisposed) {
                    // Store current state before disabling
                    mesh._physicsEnabled = false;
                    mesh._linearVelocity = mesh.physicsImpostor.getLinearVelocity().clone();
                    mesh._angularVelocity = mesh.physicsImpostor.getAngularVelocity().clone();
                    mesh.physicsImpostor.sleep(); // Put to sleep to reduce computation
                }
            } else if (mesh.hasOwnProperty("_physicsEnabled") && mesh._physicsEnabled === false) {
                // Re-enable physics and restore velocity
                mesh._physicsEnabled = true;
                mesh.physicsImpostor.wakeUp();
                if (mesh._linearVelocity) {
                    mesh.physicsImpostor.setLinearVelocity(mesh._linearVelocity);
                }
                if (mesh._angularVelocity) {
                    mesh.physicsImpostor.setAngularVelocity(mesh._angularVelocity);
                }
            }
        }
    }
});