This is a question that is asked numerous times: can parameters be set when calling the PlayOneShot
helper method of the FMOD Unity integration? Indeed, this can be done by slightly modifying the source code of the FMOD integration.
Let’s look at the PlayOneShot
methods in RuntimeManager.cs:
public static void PlayOneShot(string path, Vector3 position = new Vector3())
{
try
{
PlayOneShot(PathToGUID(path), position);
}
catch (EventNotFoundException)
{
Debug.LogWarning("[FMOD] Event not found: " + path);
}
}
public static void PlayOneShot(Guid guid, Vector3 position = new Vector3())
{
var instance = CreateInstance(guid);
instance.set3DAttributes(RuntimeUtils.To3DAttributes(position));
instance.start();
instance.release();
}
The first method takes the string you provide as the path argument, i.e. "event:/example"
, converts the string to a Guid and passes it to the second PlayOneShot
method. The actual playback takes place there. In the second method a new EventInstance is created, started and released immediately so that when the instance finishes playing it is freed from memory. This is particularly useful for one-shot fire and forget, so you don’t have to handle instances manually for every single sound you want to play in Unity.
Overloading the PlayOneShot method in the RuntimeManager class
Method Overloading in C# can be used to play a one-shot sound and set a specific parameter. Simply put, it means methods can have the same name but different parameters for example. You can duplicate both methods and add a string parameter and a float parameter to both methods like this to achieve our desired behaviour:
public static void PlayOneShot(string path, string parameterName, float parameterValue, Vector3 position = new Vector3())
{
try
{
PlayOneShot(PathToGUID(path), parameterName, parameterValue, position);
}
catch (EventNotFoundException)
{
Debug.LogWarning("[FMOD] Event not found: " + path);
}
}
public static void PlayOneShot(Guid guid, string parameterName, float parameterValue, Vector3 position = new Vector3())
{
var instance = CreateInstance(guid);
instance.set3DAttributes(RuntimeUtils.To3DAttributes(position));
instance.setParameterByName(parameterName, parameterValue);
instance.start();
instance.release();
}
Before starting the instance we add EventInstance.SetParameterByName
to the second method, so that the parameter of the instance is set based on our parameter name and value arguments. Now we can still call FMODUnity.RuntimeManager.PlayOneShot("event:/example");
for our normal sounds and pass a string and a float variable to the method when we need to set a parameter before playing the sound: FMODUnity.RuntimeManager.PlayOneShot("event:/example", "TestParameter", 2f);
. If you wish to use this for 3D sounds, follow the same procedure for PlayOneShotAttached
.
PlayOneShot with Parameters in your own helper class
Another way to play one shots with parameters is to create a static method in a helper class. This is especially useful if you plan to update the official FMOD for Unity integration. By using this method you won’t have to update the official FMOD for Unity integration source code each time you update the integration:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class AudioHelper
{
public static void PlayOneShotWithParameters(string fmodEvent, Vector3 position, params(string name, float value)[] parameters) {
FMOD.Studio.EventInstance instance = FMODUnity.RuntimeManager.CreateInstance(fmodEvent);
foreach(var (name, value) in parameters)
{
instance.setParameterByName(name, value);
}
instance.set3DAttributes(position.To3DAttributes());
instance.start();
instance.release();
}
}
Here we are using the params keyword to pass a variable number of arguments to the method. We group the parameter name and value in a tuple to have a neater syntax. Playing one shots with this method would look like this:
AudioHelper.PlayOneShotWithParameters("event:/example", this.transform.position, ("Parameter1", 1.0f), ("Parameter2", 0.0f));