Synch FMOD Machinegun event with shoot() method in unity weapon script


#1

Hi,
i am currently struggeling with how to use an FMOD machinegun event in conjunction with my unity weapon script.

First here is my current setup:

I have an FMOD machinegun event setup closely resembling to the FMOD example events. So the event consists of a loop section for the actual shot, a tail section which is tied to a release parameter and an auto-stop parameter tied to an AHDSR modulator. So the event starts in the loop section and once the release parameter is set to 1 the event transitions to the tail section and then stops by means of the auto-stop parameter. This is all working as expected. I am also able to influence RPM by adjusting the length of the loop section.

In unity i have a shoot() method which is called in dependency of a (unity) RPM-parameter. The shoot() method triggers bullet spawn, particles effects and - as one would expect - also the start of the above FMOD event.
So obviously the general logic of RPM in the FMOD event and the RPM logic in unity is a different one:

The FMOD event is only started once on “trigger down” and then plays for as long as the trigger is being pressed. Only when the trigger is being released the event transitions to the tail section and is stopped after finishing that. FMOD RPM is solely driven by the loop length.

In unity the shoot() method is being called over and over again as long as the trigger is being pressed. RPM is driven by the frequency of calls to the shoot() method.

So in order to bring those two logics together i start to play the FMOD event once when the trigger is pressed down and the first shoot() method is called. On the subsequent calls to shot() (while trigger keeps being pressed) i leave the FMOD event alone and let it keep playing. On “triggerRelease” i stop the FMOD event.

As a result there is no “real” synch between gunshot sounds from FMOD and the number of calls to the shoot() method. This is somewhat not too tragic since when going “fullauto” the player can not really tell whether the number of heard gunshots matches the number of lets say recoil kicks from the gun. However this is only true for fullauto fire. The problem shows when the player triggers only a single gunshot (shoot()-method wise) but he will hear two gunshots from the FMOD event. This gets more and more obvious as the weapons RPM raises since for some reason it is still possible to click fast enough in order to only trigger one shoot() method but the FMOD event will already play the loop two times.

So since i am obviously not the first one trying to go down this route i would be really grateful for some insights on how this can be achieved.

On a sidenote: I also tried an alternative way by differentiating between the length of button presses. So on “buttondown” i started to count the time and after a certain amount of delay i started an FMOD full auto event. If the button wasn’t pressed down long enough (button was pressed only for an amount of time < delay and then released) i played an FMOD single shot event. However the delay was always noticable, you could tell that the sound started a little bit too late. So this didnt lead to any success.

So again, any best practices on this would be appreciated.

Cheers!


#2

Having a looping event like a machine gun sync up to animation isn’t best practice. Even if you manage to sync up the animation and the looping event exactly, if your game dips in frame rate whilst firing it could fall out of sync again as the game engine and FMOD run on separate threads.

Instead, it would be better to call a one shot gun firing event for each time the gun actually fires in your animation. This way the frequency the gun shot event is played will always line up with the firing of the machine gun. Take a look at the documentation for Unity and UE4 if you are using those game engines:

https://www.fmod.com/resources/documentation-api?page=content/generated/engine_new_unity/timeline.html#/

https://www.fmod.com/resources/documentation-api?page=content/generated/engine_ue4/sequencer.html#/


#3

Thank you for your help so far. Lets say i manage to create a single shot event that chains up with a separate event for a tail Sound and this constellation sounds as accurate as my looping event. So far so good. But how do the two approaches compare in terms of performance? As far as i understand it for the looping approach i would need to instantiate only one fmod event for each full auto action, no matter How high the RPM count goes. For your approach wouldnt i need to create one instance for each individual shot? Depending on the weapons RPM this might easily go above 10 instance per second. Or am i misunderstanding something?


#4

As long as you are correctly releasing your event instances (call EventInstance::release() after starting the one-shot gun fire event) then there shouldn’t be too much to worry about. Whilst you are correct that one event instance looping 10 times for 1 second would “perform” better than creating and releasing 10 separate event instances, the actual performance difference is so minute that you would not be able to tell. The benefit of having the sound sync up to your animations far outweighs the “increased” performance from using a looping event.


#5

All right, thanks again! In the meantime i implemented this approach by using the PlayOneShot method (i am using Unity btw). So each time the shoot() method is called i do a PlayOneShotAttached for the single shot event. On trigger release i do a PlayOneShotAttached for the tail event.
While in principle this sounds ok i’m now having the problem which i wanted to circumvent at all costs: The RPM rate now totally depends on the ingame FPS. This leads to noticable inconsistency of the timing of the gun shots. Over time you can clearly hear the RPM go up and slow slightly. And i am not talking about severe frame drops, just what i call “regular” variation in FPS. This is also the reason why i tried to go down the looping way of doing it. In my opinion a slight variation in gunshot frequency can very well be accepted in terms of visuals / actual bullet count and effects but not in terms of audio, since the player will notice the latter one very easily.
I thought there was some kind of best practice on this since many games manage to keep consistent gun sounds even if their FPS varies by some degree (which i think is true for each and every game) .Like i said i am not talking about severe frame drops here. Obviously sound will fall apart when FPS drop to like 5 or so, and i am totally fine with that.
P.S. Am i guessing right that PlayOneShot releases the instance all by itself or do i have to release it manually? And is there a best practice to pool FMOD instances in unity or is this handled by FMOD internally already?
So any more ideas on this and also alternative approaches are very much appreciated.
Thank you!


#6

Unfortunately this is a trade off you need to make. You can either have a looping event that might not sync up with the animation, or a single shot event that syncs perfectly with the animation but can fluctuate with the frame rate. It depends which you think is more important.

Yes, PlayOneShot() will create the event instance, play it, and immediately release it. There’s no real best practice - as long as you are properly releasing event instances FMOD will take care of cleaning these up at each System::update().