240 lines
7.4 KiB
C#
240 lines
7.4 KiB
C#
using System.Text;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Audio;
|
|
public class SoundManager : MonoBehaviour
|
|
{
|
|
[Header("Источники")]
|
|
[SerializeField] private AudioSource MusicSrc;
|
|
[SerializeField] private AudioSource UiSrc;
|
|
[SerializeField] private AudioSource ReplicasSrc;
|
|
|
|
|
|
[Header("Микшер")]
|
|
[SerializeField] private AudioMixer mixer;
|
|
|
|
[Header("Группы")]
|
|
|
|
[SerializeField] private AudioMixerGroup MasterGroup;
|
|
[SerializeField] private AudioMixerGroup MenuGroup;
|
|
[SerializeField] private AudioMixerGroup UiGroup;
|
|
[SerializeField] private AudioMixerGroup MusicGroup;
|
|
[SerializeField] private AudioMixerGroup GameplayGroup;
|
|
[SerializeField] private AudioMixerGroup SfxGroup;
|
|
[SerializeField] private AudioMixerGroup ReplicasGroup;
|
|
[SerializeField] private AudioMixerGroup EnvironmentGroup;
|
|
|
|
|
|
const string GAMEPLAY_VOLUME = "GameplayVolume";
|
|
const string MASTER_VOLUME = "MasterVolume";
|
|
const string MENU_VOLUME = "MenuVolume";
|
|
|
|
private static SoundManager instance;
|
|
|
|
public static bool Initialized { get; private set; } = false;
|
|
|
|
|
|
|
|
public void Initialize()
|
|
{
|
|
if (Initialized)
|
|
{
|
|
Debug.LogWarning("Trying to initialize initialized SoundManager");
|
|
return;
|
|
}
|
|
instance = this;
|
|
|
|
//Подтянуть настройки
|
|
PullSettings();
|
|
SettingsManager.SettingsSaved += PullSettings;
|
|
|
|
//Валидация ссылок
|
|
var validationResult = ValidateReferences();
|
|
if (!validationResult.OK)
|
|
{
|
|
Initialized = false;
|
|
Debug.LogError(validationResult.Message, instance);
|
|
return;
|
|
}
|
|
|
|
//Установка каналов
|
|
MusicSrc.outputAudioMixerGroup = MusicGroup;
|
|
UiSrc.outputAudioMixerGroup = UiGroup;
|
|
ReplicasSrc.outputAudioMixerGroup = ReplicasGroup;
|
|
|
|
|
|
|
|
|
|
Initialized = true;
|
|
DontDestroyOnLoad(gameObject);
|
|
|
|
}
|
|
|
|
public static void PlayMusic()
|
|
{
|
|
if (CheckInitialized())
|
|
instance.MusicSrc.Play();
|
|
}
|
|
public static void StopMusic()
|
|
{
|
|
if (CheckInitialized())
|
|
instance.MusicSrc.Stop();
|
|
}
|
|
|
|
public static void PlayUi(AudioClip clip)
|
|
{
|
|
if (CheckInitialized())
|
|
{
|
|
if (clip == null)
|
|
{
|
|
Debug.Log("UI clip to play is null");
|
|
return;
|
|
}
|
|
instance.UiSrc.PlayOneShot(clip);
|
|
}
|
|
}
|
|
|
|
public static void PlayReplica(AudioClip clip)
|
|
{
|
|
if (CheckInitialized())
|
|
{
|
|
if (clip == null)
|
|
{
|
|
Debug.Log("Replica clip to play is null");
|
|
return;
|
|
}
|
|
instance.ReplicasSrc.PlayOneShot(clip);
|
|
}
|
|
}
|
|
|
|
//Перегрузка для рандомного выбора из списка
|
|
public static void PlayReplica(List<AudioClip> clips)
|
|
{
|
|
if (CheckInitialized())
|
|
{
|
|
if (clips == null || clips.Count == 0)
|
|
{
|
|
Debug.Log("Replica clip to play is null or count is 0");
|
|
return;
|
|
}
|
|
var clip = clips[Random.Range(0, clips.Count)];
|
|
instance.ReplicasSrc.PlayOneShot(clip);
|
|
}
|
|
}
|
|
|
|
|
|
public static void AssignSourceToChannel(AudioSource source, MixerChannel channel)
|
|
{
|
|
if (CheckInitialized())
|
|
{
|
|
if (source == null)
|
|
{
|
|
Debug.LogError("Source to assign is null");
|
|
return;
|
|
}
|
|
|
|
source.outputAudioMixerGroup = ChannelFromEnum(channel);
|
|
}
|
|
}
|
|
|
|
private static AudioMixerGroup ChannelFromEnum(MixerChannel channel)
|
|
{
|
|
return channel switch
|
|
{
|
|
MixerChannel.Master => instance.MasterGroup,
|
|
MixerChannel.Menu => instance.MenuGroup,
|
|
MixerChannel.UI => instance.UiGroup,
|
|
MixerChannel.Music => instance.MusicGroup,
|
|
MixerChannel.Gameplay => instance.GameplayGroup,
|
|
MixerChannel.SFX => instance.SfxGroup,
|
|
MixerChannel.Replicas => instance.ReplicasGroup,
|
|
MixerChannel.Environment => instance.EnvironmentGroup,
|
|
_ => instance.MasterGroup,
|
|
};
|
|
}
|
|
|
|
private static bool CheckInitialized()
|
|
{
|
|
if (Initialized) return true;
|
|
|
|
Debug.LogError("Trying use non initialized sound manager");
|
|
return false;
|
|
}
|
|
|
|
private static (bool OK, string Message) ValidateReferences()
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine("[Sound Manager Validation]");
|
|
|
|
bool hasErrors = false;
|
|
|
|
if (instance.MusicSrc == null) { sb.AppendLine("MusicSrc is not assigned!"); hasErrors = true; }
|
|
if (instance.UiSrc == null) { sb.AppendLine("UiSrc is not assigned!"); hasErrors = true; }
|
|
if (instance.ReplicasSrc == null) { sb.AppendLine("ReplicasSrc is not assigned!"); hasErrors = true; }
|
|
|
|
if (instance.mixer == null) { sb.AppendLine("AudioMixer is not assigned!"); hasErrors = true; }
|
|
|
|
if (instance.MasterGroup == null) { sb.AppendLine("MasterGroup is not assigned!"); hasErrors = true; }
|
|
if (instance.MenuGroup == null) { sb.AppendLine("MenuGroup is not assigned!"); hasErrors = true; }
|
|
if (instance.UiGroup == null) { sb.AppendLine("UiGroup is not assigned!"); hasErrors = true; }
|
|
if (instance.MusicGroup == null) { sb.AppendLine("MusicGroup is not assigned!"); hasErrors = true; }
|
|
if (instance.GameplayGroup == null) { sb.AppendLine("GameplayGroup is not assigned!"); hasErrors = true; }
|
|
if (instance.SfxGroup == null) { sb.AppendLine("SfxGroup is not assigned!"); hasErrors = true; }
|
|
if (instance.ReplicasGroup == null) { sb.AppendLine("ReplicasGroup is not assigned!"); hasErrors = true; }
|
|
if (instance.EnvironmentGroup == null) { sb.AppendLine("EnvironmentGroup is not assigned!"); hasErrors = true; }
|
|
|
|
if (hasErrors)
|
|
{
|
|
sb.AppendLine("Please assign all missing references in the inspector!");
|
|
}
|
|
return (!hasErrors, sb.ToString());
|
|
}
|
|
|
|
private void PullSettings()
|
|
{
|
|
SetMixerVolume(MASTER_VOLUME, SettingsManager.GetFloat(SettingKey.MasterVolume));
|
|
SetMixerVolume(GAMEPLAY_VOLUME, SettingsManager.GetFloat(SettingKey.GameVolume));
|
|
SetMixerVolume(MENU_VOLUME, SettingsManager.GetFloat(SettingKey.MenuVolume));
|
|
}
|
|
private void SetMixerVolume(string parameterName, float value)
|
|
{
|
|
if (mixer == null)
|
|
{
|
|
Debug.LogError("Master mixer is not assigned!");
|
|
return;
|
|
}
|
|
|
|
// Конвертируем линейное значение (0-1) в децибелы
|
|
// -80dB это практически тишина (минимальное значение)
|
|
// 0dB это максимальная громкость
|
|
float dB;
|
|
|
|
if (value <= 0.001f)
|
|
{
|
|
dB = -80f; // Полная тишина
|
|
}
|
|
else
|
|
{
|
|
dB = Mathf.Log10(value) * 20f;
|
|
// Ограничиваем минимальным значением -80dB
|
|
dB = Mathf.Max(dB, -80f);
|
|
}
|
|
|
|
mixer.SetFloat(parameterName, dB);
|
|
}
|
|
|
|
public enum MixerChannel
|
|
{
|
|
Master,
|
|
|
|
Menu,
|
|
UI,
|
|
Music,
|
|
|
|
Gameplay,
|
|
SFX,
|
|
Replicas,
|
|
Environment
|
|
}
|
|
}
|