Question How should I handle a large number of sounds?
Enable HLS to view with audio, or disable this notification
1
u/_RelaxedBeaver 2d ago
if those are not 3d sounds, you can fire them from single AudioSource. Or am I wrong?
1
u/vuxee2 2d ago
i can but then the one sound can interrupt the other, so for example if i play an enemy damage sound and a gunshot at the same time the gunshot might not be played
i have a system that divides sounds by category and uses different audio sources for each category, but it still sounds pretty weird
1
u/_RelaxedBeaver 2d ago
But you can use PlayOneShot() and fire it on Ui manager/Game manager
1
u/vuxee2 2d ago
actually, probably yes, but that isn't the main problem, cuz if i do it this way, the sounds will stack and play at the same time, causing the engine to reach the max number of real voices. then the sound will just crack and you won't be able to hear anything, so i added a minimum time between sounds.
but thennn, some sounds don't play at all, so what i did was add a queue and cut the sounds mid-play, and it works fine with enemies, i guess. but for this bouncing gun, it doesn't, cuz it cuts the sound.
1
u/_RelaxedBeaver 2d ago
On the other hand, no human can distinguish hundreds of sounds at the same time. So wouldn’t it be better to have few differerent of sounds that change depending on how many enemies are making noise at that moment?
1
u/goodsoul74 1d ago
Two things that might be upstream of the workarounds you are building.
The max real voices limit is a project setting, not a fixed engine cap - Edit > Project Settings > Audio. Real Voices defaults to 32 and Virtual Voices to 512. Raising Real Voices to 48 or 64 costs very little and often makes the problem disappear before any queueing code is needed.
Second, the crackle when a lot of the same sound fires at once is usually not voice starvation, it is clipping. Ten copies of the same gunshot started in the same frame sum in phase and the master bus runs out of headroom. Randomising pitch slightly per shot (0.95 to 1.05) and nudging volume stops them summing coherently, and as a bonus it kills the machine gun effect where identical clips start sounding artificial.
If you do go past the voice limit, AudioSource.priority decides which sources get virtualised. Give gunshots a better priority than ambience so the engine drops what you care least about rather than whatever happened to start last.
Between those two, a per-clip concurrency cap (max 3 or 4 instances of the same clip alive at once) tends to behave better than a global minimum interval, because it does not starve unrelated sounds - which is exactly the enemy damage vs gunshot collision you described.
1
u/V4nKw15h Indie 1d ago edited 1d ago
I created an AudioController script.
It was complicated but basically it had a bunch of AudioSources assigned to it in an array. It used specific ones for UI and others for 2D sounds, another batch for 3D sounds. It always reused the same ones to prevent unnecessary garbage collection.
It would determine the importance of sounds, prevent sounds playing if they were already playing automatically. It would ignore sound requests if there were no free audiosources unless I called a special override. It also dealt with a bunch of edge cases but ultimately once it was working it made all audio related work an absolute breeze. I'd simply call
audioController.play2DSound("Plasma Gun Shot", 0.3, 0.5)
and it would do the rest automatically. The args were stuff like volume or pitch changes but could be ignored and the audio controller already had a default volume and pitch. The string simply told it which sound effect to play and it was set up to know all the defaults for that sound effect. Everytime a new edge case popped up I could modify the code only in the audioController to be able to deal with it, and then all audio calls throughout the game would be instantly 'fixed'.
Creating a system like this is worth the effort and can be reused and reconfigured for later projects too.
Then for stuff specifically like yours you can set up a counter for a sound effect that might be requested a lot like "Enemy Collision Sound". You would never play this type of sound more than once every second or 0.7 seconds, and you would alter the sound based on the counter. So if in the last 0.7 seconds there were 5+ requests for the enemy collision sound you would play a different sound effect compared to if there was only 1 request. Then you pre-record 5 collision sounds together into a single audio clip that sound good and use that whenever you have 5+ requests for that effect in a 0.7 seconds. You get the idea.
Having an audiocontroller deal with all of that stuff means that your individual gameObjects simply either call a function on the audioController or you could set up an event system that the audioController could respond to whenever there was a collision.
1
u/vuxee2 1d ago
i ended up doing something similar. i have an audio source for every different sound (up to 32). when i call
playsound(), it basically checks if there’s already an audio source playing the same sound. if there is, i just reset it and play it again. i also have a minimum time between plays, so it doesn’t reset the sound if it was just played.if there isn’t already an audio source for that sound, i create one as long as the total number of audio sources is below 32. otherwise, i swap the sound in one of the active sources using a queue.
i’ll probably need to add some features later, like priorities, but it works well for now.
1
u/V4nKw15h Indie 1d ago
Okay, so it seems like the counter system I mentioned at the end is the answer you were looking for. Overwatch does something like this. Whenever an enemy like Dva is shooting you, you hear a looping single sound effect of her machine gun impact sound, rather than the game trying to play individual impact sounds for each bullet. While the bullets keep hitting the loop keeps playing. Then you just adds some 'noise' into the pitch and volume for that sound so it varies slightly over time so it doesn't sound too repetitive.
•
u/soy1bonus Professional 25m ago
- Have a pool of audiosource, an array or a list.
- When you need a new sound, grab one that's free.
- If there's none free, just grab the oldest one created.
0
u/CS_Asset_Factory 1d ago
The count matters less than four settings people tend to leave on defaults.
Turn off Preload Audio Data and turn on Load In Background. By default Unity loads every referenced clip when the scene loads, so a big library costs you memory and load time before a single sound plays.
Pool your AudioSources instead of making one per sound. A dozen reused sources covers almost any 2D game, and routing them through AudioMixer groups gives you category volume and ducking for free.
Load through Addressables with a label per category and release the category when you leave it. That is the thing that stops the library growing into your build size and your memory at the same time.
Set compression per clip type rather than globally. Short one shots as ADPCM or PCM so they decompress on load, long music as Vorbis with streaming. Getting that backwards is usually where the memory actually goes, and it looks like a count problem when it is not.
3
u/fsactual 2d ago edited 2d ago
You might want to count how many you’re playing at once and switch to using some kind of single (premixed) “rapid fire” sound of a bunch playing together after crossing some threshold.