I have a client that wants their game on WebGL and supporting on mobile with default browsers which includes Safari on iOS devices. We pause the audio mixer when going to other tabs to prevent audio between them and resume when focus returns. The issue is that when going to a separate app it needs to recreate the audio context to be able to play audio again. When doing so it will restart the audio instead of resuming it.
private void OnApplicationFocus (bool focus)
{
if (RuntimeManager.StudioSystem.isValid ())
{
RuntimeManager.PauseAllEvents (!focus);
if (!focus)
{
RuntimeManager.CoreSystem.mixerSuspend ();
}
else
{
RuntimeManager.CoreSystem.mixerResume ();
//Added this to force start the audio on Safari mobile
if (hasInstance)
{
currentInstance.start ();
}
}
}
}
////....////
//setup code
currentInstance = RuntimeManager.CreateInstance(MusicEventPath);
selfHandle = GCHandle.Alloc(this, GCHandleType.Weak);
currentInstance.setUserData(GCHandle.ToIntPtr(selfHandle));
currentInstance.setCallback(MarkerCallback, EVENT_CALLBACK_TYPE.TIMELINE_MARKER);
currentInstance.start();
hasInstance = true;
//////
Could you please share the FMOD version number you are using?
One thing I noticed is that calling Studio::EventInstance::start on an Event Instance that is already playing will restart the event, which might explain why the music starts again from the beginning.
Since you are already using mixerSuspend() / mixerResume() for the WebGL suspend/resume handling, could you try triggering mixerResume() from a user interaction (such as a touch/click) after returning to Safari, rather than only from OnApplicationFocus?
Mobile browsers can require a user interaction before audio playback can resume.
Also, without the additional currentInstance.start() call, does the Event Instance still report itself as playing after returning to Safari, but with no audible output?
I mis-posted unfortunately and must say that it’s not returning audio at all when exiting and returning to the game. I just tried implementing calling
RuntimeManager.CoreSystem.mixerResume ();
in an Update loop while listening for input and there is still no audio.
We’re using Unity 2022.3.36f1 with FMOD 2.0.2.15
Additionally from a colleague I tried putting this code snippet into our both in out index.html javascript and Unity jslib which tries to resume all AudioContexts on input
(function () {
if (typeof window !== 'undefined') {
var contexts = [];
['AudioContext', 'webkitAudioContext'].forEach(function (name) {
var Orig = window[name];
if (!Orig) return;
window[name] = function (opts) { var c = new Orig(opts); contexts.push(c); return c; };
window[name].prototype = Orig.prototype;
});
function unlock() {
contexts.forEach(function (c) {
if (c.state === 'running') return;
(c.state === 'interrupted' ? c.suspend().catch(function(){}) : Promise.resolve())
.then(function () { return c.resume(); }).catch(function(){});
});
}
['touchend', 'click', 'keydown'].forEach(function (e) {
window.addEventListener(e, unlock, true);
});
document.addEventListener('visibilitychange', function () {
if (!document.hidden) unlock();
});
}
})();
How would I check this? The only feedback I get is that the browser shows a blue audio speaker showing that it should be playing audio but nothing is playing.
I believe I have been able to reproduce the same behaviour on iOS Safari. After backgrounding Safari and returning to it, FMOD still reports the audio as playing, but there is no audible output.
I have raised this with our dev team for further investigation. Unfortunately, I don’t have a workaround to suggest at the moment, but I’ll update this thread once I have more information to share.
Thank you again for bringing this to our attention.