Hello,
I am trying to create some basic XR program. It works by entering VR, having a groundplane and some spawned cubes and when pressing the trigger on right controller, then it spawns/creates another cube.
Very simple, but now comes my problem.
I want to play a sound when I press that trigger/create a new cube. The sound is in shoot.mp3 and that file is in the same directory as index.html. Everything is served over https.
I don’t get sound. Never mind the title saying (Local WAV. It is mp3).
Is there anybody who would be so kind to give my code a quick look ? It is very basic code, but maybe you discover why the sound doesn’t play on my quest 3?
I would be so gratefull.
Thank you in advance,
Bart (Belgium)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Babylon.js WebXR Gunshot Demo</title>
<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
canvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<!-- Babylon.js CDN -->
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<script src="https://cdn.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://cdn.babylonjs.com/webxr/babylon.webxr.min.js"></script>
<script>
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const createScene = async () => {
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(0.8, 0.9, 1.0);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
// Create ground plane (10x10 meters)
const ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 10, height: 10 }, scene);
const groundMat = new BABYLON.StandardMaterial("groundMat", scene);
groundMat.diffuseColor = new BABYLON.Color3(0.5, 0.5, 0.5);
ground.material = groundMat;
// Add 3 random cubes on the ground
for (let i = 0; i < 3; i++) {
const box = BABYLON.MeshBuilder.CreateBox("box" + i, { size: 0.3 }, scene);
box.position = new BABYLON.Vector3(
(Math.random() - 0.5) * 9,
0.15,
(Math.random() - 0.5) * 9
);
const mat = new BABYLON.StandardMaterial("mat" + i, scene);
mat.diffuseColor = new BABYLON.Color3(Math.random(), Math.random(), Math.random());
box.material = mat;
}
// 🔊 Load local shoot.mp3 (same folder as HTML file)
const gunshotSound = new BABYLON.Sound("shoot", "shoot.mp3", scene, () => {
console.log("shoot.mp3 is loaded and ready!");
}, {
volume: 1.0,
spatialSound: true,
autoplay: false,
loop: false
});
// Enable XR
const xr = await scene.createDefaultXRExperienceAsync({
floorMeshes: [ground]
});
// Attach to controllers
xr.input.onControllerAddedObservable.add(controller => {
controller.onMotionControllerInitObservable.add(mc => {
controller.pointer.isVisible = true;
// LEFT controller: red sphere
if (controller.inputSource.handedness === "left") {
const redSphere = BABYLON.MeshBuilder.CreateSphere("redSphere", { diameter: 0.1 }, scene);
const redMat = new BABYLON.StandardMaterial("redMat", scene);
redMat.diffuseColor = new BABYLON.Color3(1, 0, 0);
redSphere.material = redMat;
redSphere.parent = controller.grip || controller.pointer;
}
// RIGHT controller: blue cube + trigger + sound
if (controller.inputSource.handedness === "right") {
const blueCube = BABYLON.MeshBuilder.CreateBox("blueCube", { size: 0.1 }, scene);
const blueMat = new BABYLON.StandardMaterial("blueMat", scene);
blueMat.diffuseColor = new BABYLON.Color3(0, 0, 1);
blueCube.material = blueMat;
blueCube.parent = controller.grip || controller.pointer;
const trigger = mc.getComponent("xr-standard-trigger");
if (trigger) {
let wasPressed = false;
trigger.onButtonStateChangedObservable.add(() => {
const pressure = trigger.value;
// One-time fire logic
if (pressure > 0.5 && !wasPressed) {
wasPressed = true;
console.log("fire");
// Spawn new 50cm cube
const newCube = BABYLON.MeshBuilder.CreateBox("firedCube", { size: 0.5 }, scene);
newCube.position = new BABYLON.Vector3(
(Math.random() - 0.5) * 9,
0.25,
(Math.random() - 0.5) * 9
);
const newMat = new BABYLON.StandardMaterial("firedMat", scene);
newMat.diffuseColor = new BABYLON.Color3(Math.random(), Math.random(), Math.random());
newCube.material = newMat;
// Play gunshot sound at controller's position
if (gunshotSound.isReady()) {
gunshotSound.setPosition(controller.pointer.position);
gunshotSound.play();
} else {
console.warn("Sound not ready yet!");
}
}
// Reset trigger press state
if (pressure < 0.2 && wasPressed) {
wasPressed = false;
}
});
}
}
});
});
return scene;
};
createScene().then(scene => {
engine.runRenderLoop(() => {
scene.render();
});
});
window.addEventListener("resize", () => {
engine.resize();
});
</script>
</body>
</html>