- Home /
Audio Tagging
We are in the process of setting up audio options from our start menu. We would like to be able to set the volume for Sfx, Music, and Dialogue. I thought the best way to do this would just be to tag each of the audio clips as sfx, mus, or dia, and access them through script using there tag. However, it seems that audio clips cannot be tagged in the editor. Is there another way to achieve this? What's the best way of manipulating the volume of different types of audio?
That is a really good question, I have also tried(and failed) creating a distinguish-able audio system(I never left the drawing board).
Answer by aldonaletto · Nov 17, 2011 at 02:15 AM
You could define the global Sfx, Music and Dialog volumes in static variables in the volume control script, and have a special script attached to every object that has an AudioSource, which would define the type and the volume of the sound - something like this:
1- In the volume control script (let's call it VolumeControl.js):
static var sfxVolume: float = 0.7; static var musicVolume: float = 0.3; static var dialogVolume: float = 0.8;
function OnGUI(){ // adjust the volume of each type }
2- Attach the script below to objects that have an AudioSource:
enum SoundType {Sfx, Music, Dialog} var sType: SoundType = SoundType.Sfx; // define the sound type in the Inspector
private var iniVol: float; private var gVol: float;
function Start(){ iniVol = audio.volume; // save the local volume }
function Update(){ switch (sType){ // get the correct type volume case SoundType.Sfx: gVol = VolumeControl.sfxVolume; break; case SoundType.Music: gVol = VolumeControl.musicVolume; break; case SoundType.Dialog: gVol = VolumeControl.dialogVolume; break; } audio.volume = iniVol * gVol; }
Would this not be quiet resource expensive when(perhaps) there are thousands of audioSources in the scene all updating every frame?
It would take some time, for sure, but not so much. Anyway, this could be optimized if the volume control script had a static boolean variable - say, volumeChanged - that could be set for one or two frames to tell all AudioSources to update their volumes.
Answer by rabbitfang · Nov 26, 2011 at 08:49 PM
I currently have a project that deals with many AudioSources. While I currently only have one volume level, the system I use could easily be extended to fit your purposes.
The volume control script (called VolumeControl.js
):
// Volumes stored into array as Sfx, Music, and Dialog indexed respectively
static var volumes : float[] = new float[3];
// audioSources stores a reference to each audio source in an ArrayList
// based on what volume level is controlling it (parallel array with volumes[])
static var audioSources : ArrayList[3] = new ArrayList[3];
public static function SetVolume(volumeGroup : int, volume : float) {
if (volume != volumes[volumeGroup]) {
volumes[volumeGroup] = volume;
updateVolume(volumeGroup);
}
}
//Send the new volume level to the audio sources
static function updateVolume(volumeGroup : int) {
for (var i = 0; i < audioSources[volumeGroup].Count; i++) {
var obj : GameObject = keys[i];
obj.BroadcastMessage("UpdateVolume", volumes[volumeGroup], SendMessageOptions.DontRequireReceiver);
}
}
public static function AddSource(audioSource : GameObject, volumeGroup : int) {
if (audioSources[volumeGroup] == null)
audioSources[volumeGroup] = new ArrayList();
audioSources[volumeGroup].Add(audioSource);
}
public static function GetVolume(volumeGroup : int) : float {
return volumes[volumeGroup];
}
That script might need some modifications to better suite your needs but it should work out. You will need to add a function that removes the audio sources from the ArrayList if you do delete the AudioSources.
Then this script goes into the audio sources themselves. (Borrowing an 2 ideas from aldonaletto's answer.)
enum SoundGroup {Sfx, Music, Dialog}
var sGroup : SoundGroup = SoundGroup.Sfx;
private var startVol : float;
private var groupVol : float;
function Start() {
startVol = audio.volume;
switch (sGroup) {
case SoundGroup.Sfx:
groupVolume = VolumeControl.GetVolume(0);
VolumeControl.AddSource(gameObject, 0);
break;
case SoundGroup.Music:
groupVolume = VolumeControl.GetVolume(1);
VolumeControl.AddSource(gameObject, 1);
break;
case SoundGroup.Dialog:
groupVolume = VolumeControl.GetVolume(2);
VolumeControl.AddSource(gameObject, 2);
break;
}
audio.volume = groupVolume * startVolume;
}
function UpdateVolume(volume : float) {
groupVolume = volume;
audio.volume = groupVolume * startVolume;
}
These scripts will only cause slow downs when the volume changes and there are large amounts of AudioSources in the group being updated. All you need to do is call VolumeControl.SetVolume
when the user touches the volume control. The system automatically checks to see if the volume level has changed and only updates if it has, so it is safe to call VolumeControl.SetVolume
every frame, within the OnGui()
function for instance.
This is basically the way I would do it (with some variations) but the basic principle of registering audio sources with a central manager that then controls their volumes in a sensible fashion is a good, extendible one.
Your answer
![](https://koobas.hobune.stream/wayback/20220613044552im_/https://answers.unity.com/themes/thub/images/avi.jpg)