Hi, just migrating from Phasaer 2 to Phaser 3 and making the first game in it. I am also finding my way how to handle sounds in convenient way.
Here is approach I am now implementing:
1] AudioSprites - all sounds in the game are in single audiosprite. All sounds are single asset with single load request:
this.load.audioSprite("Sfx", "sound/Sfx.json");
… notice, that I load only .json file and not any .ogg/m4a/mp3… It is because Sfx.json has the right format with all files in resources property (be careful about paths!) and Phaser will read it and load the right file:
{
"resources": [
"sound\\Sfx.ogg",
"sound\\Sfx.m4a"
],
"spritemap": {
"truck": {
"start": 0,
"end": 2.940702947845805,
"loop": false
},
"click": {
"start": 4,
"end": 4.108684807256235,
"loop": false
},
:
:
:
}
}
2] Sound manager is global for game, not specific to single scene. You can add audiosprite like this and access it in any scene:
const sfx = this.sound.addAudioSprite("Sfx");
… of course, you have to keep the reference somewhere. With single reference, you can play any of the sounds inside audiosprite like this:
sfx.play("click");
3] now, the problem is that I can’t play single audiosprite multiple times - if you want to play “click” while “truck” is playing, it will stop the “truck” sound. Also, it would mean, that you need extra audiosprite for each button in your case, which would not be great.
To solve this, I am creating global object AudioUtils. It creates some number (8-10 should be enough, but it is possible to configure it) of audiosprite sounds (…addAudioSprite()) - lets call them slots => any of them can play any sound (because all sounds are in single audiosprite). When the game needs to play specific sound, I call AudioUtils.playSound(“click”). It then looks for free (not playing) slot, takes it, starts playing the sound and marks the time it started to play. If no slot is free I take the longest playing one.
4] … and yes, of course, you can check if sound is ON/OFF at single place with this.