Files
5.24BuYu/Assets/MyGame/Framework/Tool/AudioManager.cs
T
2026-10-15 03:57:20 +08:00

221 lines
7.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
public enum AudioType
{
None,
BG,
FX,
}
public class AudioManager : MonoSingleton<AudioManager>
{
Dictionary<AudioType,AudioSource> dic_audioList=new Dictionary<AudioType, AudioSource> ();
public AudioMixer audioMixer;
// ⭐ 音频资源字典由热更侧 AudioResourcesData 在加载/卸载时写入、重建。
// 放在框架层是为了让 AudioManager 不反向依赖热更类型(程序集解耦)。
/// <summary>音效ID → AudioClip(默认音频 + 当前玩法音频)</summary>
public static Dictionary<int, AudioClip> ClipDic = new Dictionary<int, AudioClip>();
/// <summary>音效资源名 → 音效ID(tbaudio.json 映射)</summary>
public static Dictionary<string, int> NameToIdDic = new Dictionary<string, int>();
/// <summary>该音效ID是否已有对应 AudioClip</summary>
public bool HasClip(int audioID)
{
return ClipDic != null && ClipDic.ContainsKey(audioID);
}
protected override void Awake()
{
base.Awake();
var v = UIManager.Instance.transform.GetChild(0).GetComponents<AudioSource>();
dic_audioList.Add(AudioType.BG, v[0]);
v[0].outputAudioMixerGroup = audioMixer.FindMatchingGroups("BG")[0];
dic_audioList.Add(AudioType.FX, v[1]);
v[1].outputAudioMixerGroup = audioMixer.FindMatchingGroups("FX")[0];
int a = PlayerPrefs.GetInt("first");
if (a==0)
{
PlayerPrefs.SetFloat("slider_AudioBG",1f);
PlayerPrefs.SetFloat("slider_FX", 1f);
PlayerPrefs.SetInt("first",1);
}
float value = PlayerPrefs.GetFloat("slider_AudioBG");
audioMixer.SetFloat("BGVolume", 20.0f * Mathf.Log10(Mathf.Max(value, 0.0001f)));
value = PlayerPrefs.GetFloat("slider_FX");
audioMixer.SetFloat("FXVolume", 20.0f * Mathf.Log10(Mathf.Max(value, 0.0001f)));
dic_audioList[AudioType.BG].outputAudioMixerGroup = audioMixer.FindMatchingGroups("Master/BG")[0];
dic_audioList[AudioType.FX].outputAudioMixerGroup = audioMixer.FindMatchingGroups("Master/FX")[0];
}
public AudioSource GetAudioSource(AudioType audioType)
{
if (dic_audioList.ContainsKey(audioType))
{
return dic_audioList[audioType];
}
else
return null;
}
public void StopBG()
{
AudioType audioType = AudioType.BG;
if (dic_audioList.ContainsKey(audioType))
{
dic_audioList[audioType].Stop();
}
}
public void ChangeBG(int audioID)
{
if (audioID == 0)
return;
if (ClipDic.ContainsKey(audioID))
{
AudioClip audioClip = ClipDic[audioID];
AudioType audioType = AudioType.BG;
if (dic_audioList.ContainsKey(audioType))
{
dic_audioList[audioType].clip = audioClip;
dic_audioList[audioType].Play();
}
}
else
{
//UIManager.Instance.ShowBoardError("未找到"+audioID);
Debug.LogError("未找到音频ID: " + audioID);
}
}
public void ChangeBG(AudioClip audioClip)
{
AudioType audioType=AudioType.BG;
if (dic_audioList.ContainsKey(audioType))
{
dic_audioList[audioType].clip = audioClip;
dic_audioList[audioType].Play();
}
}
public void PlayerFX(int audioID)
{
if (audioID == 0)
return;
if (ClipDic.ContainsKey(audioID))
{
AudioClip audioClip = ClipDic[audioID];
AudioType audioType = AudioType.FX;
if (dic_audioList.ContainsKey(audioType))
{
dic_audioList[audioType].PlayOneShot(audioClip);
}
}
else
{
//UIManager.Instance.ShowBoardError("未找到"+audioID);
Debug.LogError("未找到音频ID: " + audioID);
}
}
public void PlayFX(AudioClip audioClip)
{
AudioType audioType = AudioType.FX;
if (dic_audioList.ContainsKey(audioType))
{
dic_audioList[audioType].PlayOneShot(audioClip);
}
}
private AudioSource _fxLoopSource;
/// <summary>
/// 循环音效专用 AudioSource(懒创建,与 FX 共用混音组)。
/// ⭐ 单独一条 source:Stop 只停循环音效,不会误杀 PlayOneShot 的一次性音效。
/// </summary>
private AudioSource GetFxLoopSource()
{
if (_fxLoopSource == null)
{
var fx = GetAudioSource(AudioType.FX);
GameObject host = fx != null ? fx.gameObject : UIManager.Instance.transform.GetChild(0).gameObject;
_fxLoopSource = host.AddComponent<AudioSource>();
_fxLoopSource.playOnAwake = false;
_fxLoopSource.loop = true;
if (fx != null) _fxLoopSource.outputAudioMixerGroup = fx.outputAudioMixerGroup;
}
return _fxLoopSource;
}
/// <summary>
/// 循环播放音效(如战神激光长音频)。重复调用同一条 clip 且已在播时不重头播放,只更新播放速度,
/// ⭐ 长音频用它代替逐发 PlayOneShot,避免声音重叠;pitch=2 即 2 倍速(狂暴)。
/// </summary>
public void PlayFXLoop(AudioClip audioClip, float pitch = 1f)
{
if (audioClip == null) return;
var src = GetFxLoopSource();
src.pitch = pitch > 0f ? pitch : 1f;
if (src.clip == audioClip && src.isPlaying) return; // 同一条音效已在循环 → 只变速,不重播
src.clip = audioClip;
src.loop = true;
src.Play();
}
/// <summary>停止循环音效(不影响 PlayOneShot 的一次性音效)</summary>
public void StopFXLoop()
{
if (_fxLoopSource != null && _fxLoopSource.isPlaying)
_fxLoopSource.Stop();
}
/// <summary>
/// 按音效资源名(#Audio 表 AudioResourcesPath,如 PW_Shark_Show)播放音效。
/// 名字 → ID 走 tbaudio.json 映射,表 ID 调整时无需改代码。
/// </summary>
public void PlayerFXByName(string audioName)
{
if (string.IsNullOrEmpty(audioName)) return;
if (NameToIdDic != null && NameToIdDic.TryGetValue(audioName, out int audioID))
{
PlayerFX(audioID);
}
else
{
Debug.LogWarning("未找到音频资源名: " + audioName);
}
}
public bool UpdateAudioClip(AudioType audioType,AudioClip audioClip)
{
if (dic_audioList.ContainsKey(audioType))
{
dic_audioList[audioType].clip=audioClip;
dic_audioList[audioType].Play();
return true;
}
else
return false;
}
public bool PlayOneShot(AudioType audioType, AudioClip audioClip)
{
if (dic_audioList.ContainsKey(audioType))
{
dic_audioList[audioType].PlayOneShot(audioClip);
return true;
}
else
return false;
}
}