Files
BABA_YAGA/Assets/Scripts/Audio/AudioManager.cs

130 lines
4.4 KiB
C#
Raw Normal View History

2026-04-30 17:47:29 +07:00
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
namespace Hallucinate.Audio
{
public class AudioManager : MonoBehaviour
{
public static AudioManager Instance { get; private set; }
[Header("Settings")]
[SerializeField] private AudioDatabase database;
[SerializeField] private int poolSize = 20;
[SerializeField] private AudioMixerGroup defaultGroup;
private List<AudioSource> _pool;
private int _currentIndex = 0;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
InitializePool();
if (database != null) database.Initialize();
}
2026-05-01 01:25:02 +07:00
private void Start()
{
ApplyAllVolumes();
}
2026-04-30 17:47:29 +07:00
private void InitializePool()
{
_pool = new List<AudioSource>();
for (int i = 0; i < poolSize; i++)
{
GameObject go = new GameObject($"AudioSource_{i}");
go.transform.SetParent(transform);
AudioSource source = go.AddComponent<AudioSource>();
source.playOnAwake = false;
_pool.Add(source);
}
}
2026-05-01 01:25:02 +07:00
public void ApplyAllVolumes()
{
SetVolume("MasterVolume", PlayerPrefs.GetFloat("MasterVolume", 80f));
SetVolume("MusicVolume", PlayerPrefs.GetFloat("MusicVolume", 80f));
SetVolume("VFXVolume", PlayerPrefs.GetFloat("VFXVolume", 80f));
SetVolume("PlayerVolume", PlayerPrefs.GetFloat("PlayerVolume", 80f));
SetVolume("UIVolume", PlayerPrefs.GetFloat("UIVolume", 80f));
}
public void SetVolume(string key, float volume)
{
if (defaultGroup == null || defaultGroup.audioMixer == null) return;
// Chuyển đổi từ 0-100 sang dB (-80f đến 0f hoặc 20f tùy mixer)
// Công thức: dB = 20 * log10(volume / 100)
float db = volume <= 0.001f ? -80f : Mathf.Log10(volume / 100f) * 20f;
// Đảm bảo Parameter đã được EXPOSE trong AudioMixer với tên tương ứng (MasterVolume, MusicVolume, etc.)
defaultGroup.audioMixer.SetFloat(key, db);
}
2026-04-30 17:47:29 +07:00
public void Play(string sampleName, float volumeMult = 1f, float pitchMult = 1f, Vector3? position = null)
{
if (database == null) return;
var sample = database.GetSample(sampleName);
if (sample == null || sample.Clip == null)
{
// Silence or log warning if needed
return;
}
AudioSource source = GetNextSource();
// Setup source
source.clip = sample.Clip;
source.volume = sample.DefaultVolume * volumeMult;
source.pitch = sample.DefaultPitch * pitchMult;
source.outputAudioMixerGroup = sample.MixerGroup != null ? sample.MixerGroup : defaultGroup;
if (position.HasValue)
{
source.spatialBlend = 1f; // 3D
source.transform.position = position.Value;
}
else
{
source.spatialBlend = 0f; // 2D
}
source.Play();
}
private AudioSource GetNextSource()
{
// Simple round-robin for now, can be improved to find truly "idle" sources
AudioSource source = _pool[_currentIndex];
_currentIndex = (_currentIndex + 1) % poolSize;
return source;
}
public void PlayRandom(string baseName, int variants, float volumeMult = 1f, float pitchMult = 1f)
{
int rand = UnityEngine.Random.Range(1, variants + 1);
Play($"{baseName}-{rand}", volumeMult, pitchMult);
}
// Helper for UI/Global easy access
public static void PlayGlobal(string name, float volume = 1f, float pitch = 1f)
{
if (Instance != null) Instance.Play(name, volume, pitch);
}
public static void PlayRandomGlobal(string baseName, int variants, float volume = 1f, float pitch = 1f)
{
if (Instance != null) Instance.PlayRandom(baseName, variants, volume, pitch);
}
}
}