Best Practice for Using AudioEngine in React

Hi everyone,

I’m using Babylon.js inside a React application, and I want to properly use the AudioEngine—especially considering browser autoplay restrictions and the fact that audioEngine.unlockAsync() must be called on a user interaction.

Here are some details:

  • I initialize the Babylon scene inside a useEffect, and I want to create sounds (some should play only after collisions or triggers).

  • However, calling CreateAudioEngineAsync() and using unlockAsync() causes issues if it’s not done on a user gesture (like onClick).

  • I also noticed that sometimes the audio won’t play or throws an error unless the engine is unlocked.

:red_question_mark: What is the best practice or pattern to:

  1. Set up the AudioEngine in a React-friendly way (maybe via context or hook)?

  2. Ensure unlockAsync() is only triggered after a user gesture (and how to detect that)?

  3. Play certain sounds later (e.g., after collision), even if they are initialized earlier?

Here’s a simplified version of what I tried:

const initScene = async () => {
const audioEngine = await CreateAudioEngineAsync();
await audioEngine.unlockAsync(); // 🔴 Causes issue if not in user interaction
};

Any example patterns, custom hooks, or tips would be really appreciated!

Thanks :folded_hands:

cc @docEdub

I’m not a React expert, but a context looks like it should work if the AudioEngine and created sounds are persisted. Here’s an article that may be helpful: Sharing Audio in React with useContext - DEV Community.

When calling unlockAsync() you should get a warning if the audio engine doesn’t unlock, not an error. Is that what you meant? Anyway, any onClick handler will do the trick. Just get the audio engine from the context in the click handler and call audioEngine.unlockAsync() .

This should work for playing sounds, too. Add created sounds to the context, making sure they’re persisted with useRef or similar, then access the context later and call the sound’s play function.

Also note that there is a click handler already built into the new audio engine which should work automatically. You can add an observer to the audioEngine.onStateChangedObservableto know when the audio engine is unlocked, or you can check the audio engine’s state property before playing a sound. If the audio engine state is not ”running” then don’t play the sound since the browser will block it anyway.

Try that out and if you’re still stuck I’ll try and throw together an example React app, but it wil be mostly AI generated since don’t know much React.

1 Like