294 lines
7.6 KiB
C#
294 lines
7.6 KiB
C#
|
/********************************************************************
|
||
|
文件: AudioMgr.cs
|
||
|
作者: 梦语
|
||
|
邮箱: 1982614048@qq.com
|
||
|
创建时间: 2024/03/29 17:28:19
|
||
|
最后修改: 梦语
|
||
|
最后修改时间: 2024/04/03 17:09:26
|
||
|
功能:
|
||
|
*********************************************************************/
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace Ether
|
||
|
{
|
||
|
public class AudioManager : SingletonAutoMono<AudioManager>
|
||
|
{
|
||
|
private AudioSource backGroundSource; //背景音乐Source
|
||
|
private List<AudioSource> allEffectSource = new List<AudioSource>(); //所有播放音效Source
|
||
|
private Dictionary<string, AudioClip> clipCache = new Dictionary<string, AudioClip>(); //clip缓存
|
||
|
private int releaseCount = 3; //空闲source大于这个数量时释放
|
||
|
|
||
|
/// <summary>
|
||
|
/// 全局音量
|
||
|
/// </summary>
|
||
|
[SerializeField, SetProperty("GlobalVolume"), Range(0f, 1f)]
|
||
|
private float globalVolume = 1f;
|
||
|
public float GlobalVolume
|
||
|
{
|
||
|
get => globalVolume;
|
||
|
set
|
||
|
{
|
||
|
globalVolume = value;
|
||
|
RefreshGlobalVolume();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 背景音量
|
||
|
/// </summary>
|
||
|
[SerializeField, SetProperty("BackGroundVolume"), Range(0f, 1f)]
|
||
|
private float backGroundVolume = 1f;
|
||
|
public float BackGroundVolume
|
||
|
{
|
||
|
get => backGroundVolume;
|
||
|
set
|
||
|
{
|
||
|
backGroundVolume = value;
|
||
|
RefreshBackGroundVolume();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 音效音量
|
||
|
/// </summary>
|
||
|
[SerializeField, SetProperty("EffectVolume"), Range(0f, 1f)]
|
||
|
private float effectVolume = 1f;
|
||
|
public float EffectVolume
|
||
|
{
|
||
|
get => effectVolume;
|
||
|
set
|
||
|
{
|
||
|
effectVolume = value;
|
||
|
RefreshEffectVolume();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 是否静音
|
||
|
/// </summary>
|
||
|
[SerializeField, SetProperty("IsMute")]
|
||
|
private bool isMute = false;
|
||
|
public bool IsMute
|
||
|
{
|
||
|
get => isMute;
|
||
|
set
|
||
|
{
|
||
|
isMute = value;
|
||
|
RefreshGlobalVolume();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 刷新全局音量
|
||
|
/// </summary>
|
||
|
private void RefreshGlobalVolume()
|
||
|
{
|
||
|
RefreshBackGroundVolume();
|
||
|
RefreshEffectVolume();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 刷新背景音量
|
||
|
/// </summary>
|
||
|
private void RefreshBackGroundVolume()
|
||
|
{
|
||
|
backGroundSource.volume = globalVolume * backGroundVolume;
|
||
|
backGroundSource.mute = isMute;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 刷新音效音量
|
||
|
/// </summary>
|
||
|
private void RefreshEffectVolume()
|
||
|
{
|
||
|
foreach (var source in allEffectSource)
|
||
|
{
|
||
|
source.volume = globalVolume * effectVolume;
|
||
|
source.mute = isMute;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 播放背景音乐
|
||
|
/// </summary>
|
||
|
public void PlayBgAudio(string name)
|
||
|
{
|
||
|
AudioClip clip = GetAudioClip($"Audio/{name}");
|
||
|
RefreshBackGroundVolume();
|
||
|
Play(backGroundSource, clip, true);
|
||
|
}
|
||
|
|
||
|
public bool IsPlayingBgAudio()
|
||
|
{
|
||
|
return backGroundSource.isPlaying;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 停止背景音乐
|
||
|
/// </summary>
|
||
|
public void StopBgAudio()
|
||
|
{
|
||
|
backGroundSource?.Stop();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 播放
|
||
|
/// </summary>
|
||
|
private void Play(AudioSource source, AudioClip clip, bool isLoop = false)
|
||
|
{
|
||
|
source.clip = clip;
|
||
|
source.loop = isLoop;
|
||
|
source.mute = isMute;
|
||
|
source.Play();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 播放音效
|
||
|
/// </summary>
|
||
|
public void PlayEffectAudio(string name, bool isLoop = false)
|
||
|
{
|
||
|
AudioClip clip = GetAudioClip($"Audio/{name}");
|
||
|
if (clip == null)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
AudioSource tmpSouce = GetFreeEffectSource();
|
||
|
RefreshEffectVolume();
|
||
|
Play(tmpSouce, clip, isLoop);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 停止音效
|
||
|
/// </summary>
|
||
|
/// <param name="name"></param>
|
||
|
public void StopEffectAudio(string name)
|
||
|
{
|
||
|
foreach (var source in allEffectSource)
|
||
|
{
|
||
|
if (source.clip.name == name && source.isPlaying)
|
||
|
{
|
||
|
source.Stop();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 停止所有音效
|
||
|
/// </summary>
|
||
|
public void StopAllEffectAudio()
|
||
|
{
|
||
|
foreach (var source in allEffectSource)
|
||
|
{
|
||
|
source.Stop();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 是否正在播放某个音效
|
||
|
/// </summary>
|
||
|
/// <param name="name"></param>
|
||
|
/// <returns></returns>
|
||
|
public bool IsPlayingEffectAudio(string name)
|
||
|
{
|
||
|
foreach (var source in allEffectSource)
|
||
|
{
|
||
|
if (source.clip.name == name && source.isPlaying)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 根据名字获取clip
|
||
|
/// </summary>
|
||
|
private AudioClip GetAudioClip(string name)
|
||
|
{
|
||
|
if (clipCache.ContainsKey(name))
|
||
|
{
|
||
|
return clipCache[name];
|
||
|
}
|
||
|
|
||
|
AudioClip clip = LoaderTools.LoadAsset<AudioClip>(name);
|
||
|
if (clip != null)
|
||
|
{
|
||
|
clipCache.Add(name, clip);
|
||
|
}
|
||
|
|
||
|
return clip;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 获取一个空闲的AudioSource
|
||
|
/// </summary>
|
||
|
/// <returns></returns>
|
||
|
private AudioSource GetFreeEffectSource()
|
||
|
{
|
||
|
foreach (var souce in allEffectSource)
|
||
|
{
|
||
|
if (!souce.isPlaying)
|
||
|
{
|
||
|
ReleaseSurplus();
|
||
|
return souce;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AudioSource tmpSouce = gameObject.AddComponent<AudioSource>();
|
||
|
allEffectSource.Add(tmpSouce);
|
||
|
return tmpSouce;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 释放空闲的AudioSource
|
||
|
/// </summary>
|
||
|
private void ReleaseSurplus()
|
||
|
{
|
||
|
int freeCount = 0;
|
||
|
List<AudioSource> remove = new List<AudioSource>();
|
||
|
|
||
|
foreach (var source in allEffectSource)
|
||
|
{
|
||
|
if (!source.isPlaying)
|
||
|
{
|
||
|
freeCount++;
|
||
|
|
||
|
if (freeCount > releaseCount)
|
||
|
{
|
||
|
remove.Add(source);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach (var source in remove)
|
||
|
{
|
||
|
allEffectSource.Remove(source);
|
||
|
Destroy(source);
|
||
|
}
|
||
|
|
||
|
remove.Clear();
|
||
|
}
|
||
|
|
||
|
public override void Init()
|
||
|
{
|
||
|
Clear();
|
||
|
if (backGroundSource == null)
|
||
|
{
|
||
|
backGroundSource = gameObject.AddComponent<AudioSource>();
|
||
|
}
|
||
|
RefreshGlobalVolume();
|
||
|
}
|
||
|
|
||
|
public override void Clear()
|
||
|
{
|
||
|
allEffectSource.Clear();
|
||
|
clipCache.Clear();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|