I’m working on an ARPG game and am currently trying to fix and optimise some performance issues regarding the idle sounds of enemies when there are several of them close to the player.
The idleWalk event is associated with each enemy and is defined by parameters that indicate when the enemy is moving or not moving. The implementation is generally effective for our needs, but whenever there are multiple enemies on the screen the gameplay audio stutters.We are currently exploring potential solutions to address this issue.
We were already limiting each event instance to virtualize mode but this still wasn’t enough. Apperantly virtual voices are not as CPU-friendly as I thought. Even limiting each event instance to a maximum of 4 real instances, the virtual voices still uses a lot of CPU.
My first attempt was to limit the max voices of the mixer group the idleWalk events are, but this creates another issue that some enemies end up having their idleWalk event killed and therefore completely silent because of the ammount of loaded enemies is higher than the mixer group limit. There’s no way to setup virtual voices for mixer groups so this fixes the stutter issue but creates another.
I’d like to know if virtual voices were not designed to be used in this kind of scenario and if there’s a more optimal (and smarter) way of implementing this.
We’ve also had issues with virtual events not being enough, so we designed our own culling system based that is basically made around the max distance on the event. Maybe you need something similar?
Virtual voices are intended for this kind of scenario, but it’s worth nothing that FMOD’s virtualization system still incurs some CPU overhead - while audio itself isn’t processed, the FMOD system still processes a number of things (i.e. channel DSP clocks, event playback positions, timeline logic, automation/modulation, other API commands) to ensure that a voice/event is playing the expected audio when it becomes real. It’s difficult to make specific recommendations without seeing your project or a recorded profiler session, but from what you’ve described, I agree with @deHaan that implementing a culling system would be your best bet.
If you’re using Studio Event Emitter components to play the idleWalk events, you can try enabling the Stop Events Outside Max Distance setting. If you’re playing the event from your own code:
If idleWalk is a one shot, then adding a simple check to ensure that an instance is only played when the listener is within range should address the issue.
If idleWalk isn’t a one shot, but is retriggered via parameter, you may want to implement a slightly more complex distance check so that the event is stopped and/or released when the listener is outside the range, and then recreated and/or restarted when the the listener is back in the range.