Can't unlock audio on some devices with my own unlocking code. Babylon's unlocker works fine

I don’t understand what’s wrong with this unlocking code? It’s absolutely the same as BJS has inside the engine. I add listeners to touchend+click and … nothing. I never get a message “Audio is unlocked”.
At the startup I get “audio locked” message only.

My TypeScript code here
let isLocked = true;
engine = new Engine( canvas, true );
if ( Engine.audioEngine ) {
	Engine.audioEngine.useCustomUnlockedButton = true;
	Engine.audioEngine.onAudioLockedObservable.add( () => {
		alert( "Audio locked" );
		isLocked = true;
	} );
	Engine.audioEngine.onAudioUnlockedObservable.add( () => {
		alert( "Audio is UNlocked" );
		isLocked = false;
	} );
}

// html: <button class="button" id="unlockAudioButton">Unlock Audio</button>
const el = document.getElementById( "unlockAudioButton" );
if ( el ) {
	el.addEventListener( "click", () => {
		Engine.audioEngine?.unlock();
	}, true );
	el.addEventListener( "pointerdown", () => {
		Engine.audioEngine?.unlock();
	}, true );
	el.addEventListener( "touchstart", () => {
		Engine.audioEngine?.unlock();
	}, true );
	el.addEventListener( "touchend", () => {
		Engine.audioEngine?.unlock();
		setTimeout( () => { 
			if ( Engine.audioEngine ) {
				alert( `isLocked = ${ isLocked }` ); 
			}
		}, 3000 );
	}, true );
}

I include BabylonJS in html like this:
<script src="babylon.js"></script>

then I import it in my .ts file:
import { Engine, Scene, ..... } from "babylonjs"
BabylonJS installed with npm.

compiling it with webpack and run from the HTML page with babylon.js script included.
WebPack NOT includes babylonjs to my output.js file, I exclude it. Then I include babylon.js with a script-tag only on my web page.
Maybe something wrong with the scopes?

My code works on several iPhones, Desktop: Chrome/Firefox, but not on Android 10 (Chrome).
I always get “isLocked = true” message. So onAudioUnlockedObservable never calls on this phone. Since I see the alert “isLocked == true” that means Engine.audioEngine is supported and accessible.
Babylon’s unlocker icon works fine on that android phone.

UPD:
I’ve just implemented some super simple pure HTML+JS code without typescript and it work properly:

HTML + simple JS code here
<script src="babylon.js"></script>
...
<script>
	function onReady() {
		const canvas = document.getElementById( "canvas" );
		const engine = new BABYLON.Engine( canvas, true );
		var scene = new BABYLON.Scene(engine);

		BABYLON.Engine.audioEngine.useCustomUnlockedButton = true;
		const sound = new BABYLON.Sound( "Sound0", "assets/sounds/music.ogg", scene, () => {
			alert( "sound000 has loaded" );
		} );

		const css = ".mybtn { position: absolute; left: 150px; top: 200px; height: 100px; width: 200px; z-index: 999; }";
		const style = document.createElement( "style" );
		style.appendChild( document.createTextNode( css ) );
		document.getElementsByTagName( "head" )[ 0 ].appendChild( style );

		const btn = document.createElement( "button" );
		btn.className = "mybtn";
		btn.title = "Unlock audio";
		btn.addEventListener( "click", () => { BABYLON.Engine.audioEngine.unlock(); sound.play(); }, false );
		btn.addEventListener( "touchend", () => { BABYLON.Engine.audioEngine.unlock(); sound.play(); }, false );
		document.body.appendChild( btn );
	};
	document.addEventListener( "DOMContentLoaded", () => onReady() );
</script>

So what’s the root of my problem? Scopes? It can’t be used without “BABYLON.” prefix or what? Or when I use just “Engine” but my TypeScript code transpiles with webpack it just brokes the scope and I can’t call Engine anymore? But it’s not undefined and still accessible…

I am wondering if unlock is async the you d need to wait a bit before playing. try with a setTimeout around .play() to confirm ?

@RaananW might have some thoughts ?

1 Like

Omg, I found the issue. The problem was in my code. Besides adding “touchend” and “click” listeners which do: Engine.audioEngine?.unlock(), there were such listeners also: “touchdown”, “pointerdown” - they were blocked execution of unlock(). I think Chrome jugged such behaviour something like fake or wrong clicks for unlocking the audio so clicks worked fine but it didn’t unlock the audio system. When I removed *down events all worked fine. Omg, so much time lost to debug it… That’s insane.

5 Likes