/*
* author: mark joshwel
* date: 29/5/2024
* description: audio manager for handling audio in the game
*/
using System;
using UnityEngine;
///
/// singleton class for handling audio in the game
///
public class AudioManager : MonoBehaviour
{
///
/// enum for available audio channels in the game
///
public enum AudioChannel
{
Music,
SoundEffects
}
///
/// singleton pattern: define instance field for accessing the singleton elsewhere
///
public static AudioManager Instance;
///
/// music audio source
///
[SerializeField] private AudioSource musicSource;
///
/// sound effects (sfx) audio source
///
[SerializeField] private AudioSource sfxSource;
///
/// music source default volume
///
[SerializeField] private float musicSourceDefaultVolume = 0.6f;
///
/// sound effects (sfx) source default volume
///
[SerializeField] private float sfxSourceDefaultVolume = 0.6f;
///
/// enforces singleton behaviour; sets doesn't destroy on load and checks for multiple instances
///
private void Awake()
{
// check if instance hasn't been set yet
if (Instance == null)
{
Debug.Log("awake as singleton instance, setting self as the forever-alive instance");
Instance = this;
DontDestroyOnLoad(gameObject);
}
// check if instance is already set and it's not this instance
else if (Instance != null && Instance != this)
{
Debug.Log("awake as non-singleton instance, destroying self");
Destroy(gameObject);
}
}
///
/// function to set default volumes for the audio sources
///
public void Start()
{
// set the default volume for the music source
musicSource.volume = musicSourceDefaultVolume;
// set the default volume for the sfx source
sfxSource.volume = sfxSourceDefaultVolume;
}
///
/// plays the audio clip once on a given channel
///
/// the audio clip to play
/// the audio channel to play the clip on
public void PlayClipOnChannel(AudioClip clip, AudioChannel channel)
{
switch (channel)
{
case AudioChannel.Music:
musicSource.PlayOneShot(clip);
break;
case AudioChannel.SoundEffects:
sfxSource.PlayOneShot(clip);
break;
default:
Debug.LogError($"invalid channel '{channel}'");
break;
}
}
///
/// gets the volume of a given audio channel
///
/// the AudioManager.AudioChannel to get the volume of
/// volume float value of the channel, from 0.0f-1.0f
public float GetChannelVolume(AudioChannel channel)
{
switch (channel)
{
case AudioChannel.Music:
return musicSource.volume;
case AudioChannel.SoundEffects:
return sfxSource.volume;
default:
Debug.LogError($"invalid channel '{channel}'");
return 0f;
}
}
///
/// sets the pure volume value of a given audio channel
///
/// volume float value for the channel, from 0.0f-1.0f
/// the AudioManager.AudioChannel to set the volume of
public void SetChannelVolumeReal(float volume, AudioChannel channel)
{
switch (channel)
{
case AudioChannel.Music:
musicSource.volume = Math.Min(volume, 1.0f);
break;
case AudioChannel.SoundEffects:
sfxSource.volume = Math.Min(volume, 1.0f);
break;
default:
Debug.LogError($"invalid channel '{channel}'");
break;
}
}
///
/// sets the volume value of a given audio channel based on a logarithmic scale
/// for human perception (e.g. 0.5f is half volume, 0.1f is very quiet)
///
/// volume float value for the channel, from 0.0f-1.0f
/// the AudioManager.AudioChannel to set the volume of
public void SetChannelVolumeLog(float volume, AudioChannel channel)
{
switch (channel)
{
case AudioChannel.Music:
musicSource.volume = Mathf.Log10(Mathf.Max(volume, 0.0001f)) * 20;
break;
case AudioChannel.SoundEffects:
sfxSource.volume = Mathf.Log10(Mathf.Max(volume, 0.0001f)) * 20;
break;
default:
Debug.LogError($"invalid channel '{channel}'");
break;
}
}
}