Saltar al contenido principal

Sistema de audio

El sistema de audio de OpenMon es un motor 2D basado en pooling de AudioSource sobre el AudioMixer de Unity. Está dividido en dos capas: Foundation (OpenMon.Foundation.Audio) provee el motor genérico de reproducción, y Core (OpenMon.MCE.Audio) agrega configuración de volumen y persistencia específica del juego.

La sección de sonido de la pantalla de opciones

Tres buses independientes (global, música y efectos), y el global multiplica a los otros dos en lugar de reemplazarlos, por eso silenciar la música no apaga el golpe de una batalla.

Arquitectura​

ClaseCapaPropósito
AudioManagerFoundationSingleton que posee un pool de AudioSource y reproduce/para/fadea clips
AudioLibraryFoundationScriptableObject que registra cada AudioClip con su AudioMixerGroup
AudioReferenceFoundationStruct serializable liviana que referencia un clip por nombre
AudioSettingsManagerCoreLee/escribe preferencias de volumen y las aplica al mixer
AudioConfigurationCoreClase de datos serializable con niveles Master, Music y FX
AudioInstallerFoundationScriptableObjectInstaller de Zenject que bindea IAudioManager e IAudioLibrary
AudioSettingsInstallerCoreInstaller de Zenject que bindea AudioSettingsManager y el AudioMixer

AudioManager​

AudioManager es un singleton (Singleton<AudioManager>) que implementa IAudioManager. Administra un pool dinámico de componentes AudioSource en su propio GameObject. Al reproducir, reusa una fuente libre del pool o crea una nueva si es necesario.

Reproducir audio​

// One-shot simple
AudioManager.Instance.PlayAudio(miAudioReference);

// BGM en loop con fade-in
AudioManager.Instance.PlayAudio(bgmReference, loop: true, fadeTime: 1.5f);

// Pitch y volumen personalizados
AudioManager.Instance.PlayAudio(sfxReference, pitch: 1.2f, volume: 0.8f);

Cada llamada resuelve el AudioReference a través de la AudioLibrary, obtiene el clip y su mixer group, y los asigna a un AudioSource del pool. Cuando fadeTime > 0, el manager ejecuta una corrutina que interpola el volumen de 0 al target durante la duración especificada.

Detener audio​

// Parada instantánea
AudioManager.Instance.StopAudio(bgmReference);

// Fade out en 2 segundos, luego para
AudioManager.Instance.StopAudio(bgmReference, fadeTime: 2f);

// Parada de emergencia (ej. abortar batalla)
AudioManager.Instance.StopAllAudios();

Silenciar / Reactivar global​

Estas corrutinas operan sobre el parámetro MasterVolume del AudioMixer, permitiendo silenciar todo el output sin detener fuentes individuales. Útil para transiciones de escena y pantallas de pausa.

// Silenciar el bus master en 1 segundo
StartCoroutine(AudioManager.Instance.MuteAllAudios(fadeTime: 1f));

// Restaurar al volumen anterior
StartCoroutine(AudioManager.Instance.UnmuteAllAudios(fadeTime: 1f));

Ciclo de vida del pool​

El pool se auto-administra. Cada frame, CheckAudioSourceAvailability() escanea todas las fuentes. Cualquier fuente que haya terminado de reproducir se marca como disponible y se limpia su referencia al clip. Si ningún otro fuente está usando ese clip, se notifica a la librería vía FreeAudioAsset() para permitir descarga futura basada en addressables.

AudioLibrary​

AudioLibrary es un ScriptableObject (crear via OpenMon > Audio > Audio Library) que funciona como registro central de audio. Almacena un SerializableDictionary<AudioClip, AudioMixerGroup> que mapea cada clip del juego al mixer group por el que debe reproducirse (BGM, SFX, ME, etc.).

AudioLibrary (ScriptableObject)
+-- "battle_bgm_01" -> BGM MixerGroup
+-- "ui_confirm" -> SFX MixerGroup
+-- "level_up_jingle" -> ME MixerGroup
+-- "cry_001" -> SFX MixerGroup
...

En tiempo de edición, la librería cachea listas planas de nombres, referencias a clips y mixer groups para búsqueda O(n) por nombre. El comando Cache Audio References del menú contextual reconstruye estos caches al agregar o quitar clips.

Utilidad de editor​

El pipeline del importer puede registrar clips automáticamente:

audioLibrary.AddAudioIfItsNotIn(clip, mixerGroup);

AudioReference​

AudioReference es un struct serializable simple con un solo campo string Audio. Coincide con el nombre del clip registrado en la AudioLibrary. Esto desacopla los datos serializados de escenas/prefabs de referencias directas a clips, permitiendo reorganizar archivos de audio sin romper referencias del inspector.

[Serializable]
public struct AudioReference
{
public string Audio; // Debe coincidir con un nombre en AudioLibrary
}

Usá campos AudioReference en tus MonoBehaviours, ScriptableObjects o nodos de CommandGraph para referenciar audio por nombre.

AudioSettingsManager​

AudioSettingsManager es el controlador de volumen específico del juego. Lee AudioConfiguration del sistema de configuración persistente y aplica tres niveles al AudioMixer:

  • MasterVolume — volumen general del juego
  • MusicVolume — volumen del grupo BGM
  • FXVolume — volumen de efectos de sonido y jingles

Conversión de volumen​

La percepción humana del volumen es logarítmica. El sistema usa AudioUtils para convertir entre el rango lineal 0-1 de los sliders y la escala en decibelios que espera el AudioMixer de Unity:

float db = AudioUtils.LinearVolumeToLogarithmicVolume(0.5f); // ~ -6 dB
float linear = AudioUtils.LogarithmicVolumeToLinearVolume(-6f); // ~ 0.5

Persistir configuración​

Las preferencias de volumen se guardan via el sistema IConfigurationManager. Cuando el jugador ajusta un slider en la pantalla de opciones, la UI llama a:

audioSettingsManager.SetAudioConfiguration(new AudioConfiguration
{
MasterVolume = masterSlider.value,
MusicVolume = musicSlider.value,
FXVolume = fxSlider.value
});

Esto escribe la configuración a disco y aplica los nuevos valores al mixer inmediatamente. Al iniciar, AudioSettingsManager.Construct() se llama via inyección Zenject y aplica la configuración guardada en el siguiente frame.

Setup de inyección de dependencias​

Ambos installers son ScriptableObjectInstaller de Zenject agregados al SceneContext de la escena:

  1. AudioInstaller — bindea IAudioManager (desde AudioManager.Instance), IAudioLibrary (desde el asset AudioLibrary), y el AudioMixer.
  2. AudioSettingsInstaller — bindea AudioSettingsManager como singleton lazy e inyecta el AudioMixer.
SceneContext
+-- AudioInstaller (referencia al asset AudioLibrary + AudioMixer)
+-- AudioSettingsInstaller (referencia al AudioMixer)

Usar audio en CommandGraph​

La reproducción de audio se puede disparar desde scripts de eventos de NPC (CommandGraph). La categoría Sounds tiene los nodos: PlayMusic (una pista como música del mundo, por encima de la propia del mapa), StopMusic (la desvanece), SaveMusic y RestoreSceneMusic (conservan una pista tras una batalla, o vuelven a la del propio mapa), PlaySound, PlayMonsterCry y WaitForAudio (detiene el grafo hasta que termina un jingle). Los nodos referencian clips via campos AudioReference, que se resuelven a través de la misma AudioLibrary en runtime. Para llenar la biblioteca con los clips que ya hay en tu proyecto, usa Tools > MCE > Audio > Populate Audio Library.

Resumen​

Si querés...Usá...
Reproducir un efecto de sonidoAudioManager.Instance.PlayAudio(ref)
Poner música de fondo en loopAudioManager.Instance.PlayAudio(ref, loop: true)
Crossfade a un nuevo BGMDetener el anterior con fadeTime, reproducir el nuevo con fadeTime
Silenciar durante carga de escenaMuteAllAudios(fadeTime) / UnmuteAllAudios(fadeTime)
Registrar un clip nuevoAgregalo al asset AudioLibrary y asignale un mixer group
Ajustar volumen del jugadorAudioSettingsManager.SetAudioConfiguration(config)
Convertir slider a dBAudioUtils.LinearVolumeToLogarithmicVolume(value)