Now you may be thinking, “wait a minute I can do random playback of sound inside FMOD, using a multi instrument or a scatter instrument, what’s the point in this?” Well you’re not wrong and for many cases this would be a great way of doing this. But sometimes you might want to play the event randomly for one reason or another.
My reason that I had was wanting a multi instrument to randomly playback but to randomise the number of times the sounds inside the multi instrument playback.
So why not try coding something within Unity?
Firstly we need access to the FMOD Studio Event Emitter which is placed on the game object in Unity. This allows us to control the playback. We’re basically adding extra functionality to this component.
public StudioEventEmitter studioEventEmitter;
We need a timer which when it ends, plays back the event in the event emitter.
private void Timer()
{
if (timeRemaining > 0)
{
timeRemaining -= Time.deltaTime;
}
else
{
isTimerComplete = true;
}
}
This is then updated in the built in Unity update function.
private void Update()
{
if (isTimerComplete)
{
RepeatOrOneShot();
ResetTimer();
}
else
{
Timer();
}
}
When the timer is completed, a method is then run to see if the event will repeat or be a one shot and then do so accordingly.
private void RepeatOrOneShot()
{
if (isRepeating == true)
{
StartCoroutine(PlayRepeatingFMODEventEmitter());
}
else
{
PlayFMODEventEmitter();
}
}
IEnumerator PlayRepeatingFMODEventEmitter()
{
for (int i = 0; i < numberOfRepeats; i++)
{
PlayFMODEventEmitter();
yield return new WaitForSeconds(timeBetweenRepeats);
}
}
Once that method has run we then need to reset the timer along with randomising the time remaining for the timer and number of repeats within a set range (this is also done in the built in Start method):
private void RandomizeTimer()
{
timeRemaining = Random.Range(minTimeRandom, maxTimeRandom);
}
private void RandomizeRepeats()
{
numberOfRepeats = Random.Range(minRepeatsRandom, maxRepeatsRandom);
}
And that’s it! We can now set some variables in the inspector to how we want the event to play back.
This could be expanded in many ways such as: randomise the time between the repeats according to a min and max value. Randomly adjust a parameter or attenuation values.
Thanks for reading and below is the full code for you to take a look at. I hope this posts helps! Please let me know if you notice any bugs, improvements, or any questions.
Full code (click to expand)
using UnityEngine;
using FMODUnity;
using System.Collections;
public class FMODRandomPlayback : MonoBehaviour
{
[Header("FMOD Event")]
public StudioEventEmitter studioEventEmitter;
[Header("Timer Remaining Time")]
[SerializeField] private float timeRemaining;
[Header("Timer min and max random time")]
public float minTimeRandom;
public float maxTimeRandom;
private bool isTimerComplete;
[Header("Repeating after timer complete")]
public bool isRepeating;
public float minRepeatsRandom;
public float maxRepeatsRandom;
private float numberOfRepeats;
public float timeBetweenRepeats;
private void Start()
{
RandomizeTimer();
if (isRepeating)
{
RandomizeRepeats();
}
}
private void Update()
{
if (isTimerComplete)
{
RepeatOrOneShot();
ResetTimer();
}
else
{
Timer();
}
}
private void RepeatOrOneShot()
{
if (isRepeating == true)
{
StartCoroutine(PlayRepeatingFMODEventEmitter());
}
else
{
PlayFMODEventEmitter();
}
}
IEnumerator PlayRepeatingFMODEventEmitter()
{
for (int i = 0; i < numberOfRepeats; i++)
{
PlayFMODEventEmitter();
yield return new WaitForSeconds(timeBetweenRepeats);
}
}
private void Timer()
{
if (timeRemaining > 0)
{
timeRemaining -= Time.deltaTime;
}
else
{
isTimerComplete = true;
}
}
private void ResetTimer()
{
if (isRepeating == true)
{
RandomizeRepeats();
RandomizeTimer();
}
else
{
RandomizeTimer();
}
isTimerComplete = false;
}
private void RandomizeTimer()
{
timeRemaining = Random.Range(minTimeRandom, maxTimeRandom);
}
private void RandomizeRepeats()
{
numberOfRepeats = Random.Range(minRepeatsRandom, maxRepeatsRandom);
}
private void PlayFMODEventEmitter()
{
studioEventEmitter.Play();
}
}