播放背景音乐、播放提示音、播放音效。成组播放、声音源复用、音量控制、音效播放位置等等。
写差不多了,发现不是自己想要的风格。没完善呢就过时的感觉。先放着吧。。。
#if UNITY_EDITOR
//#define Sirenix_OdinInspector
#endif
#if Sirenix_OdinInspector
using Sirenix.OdinInspector;
#endif
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
///
/// 声音管理器
/// (目前不保证稳定,出现问题可尝试"try{}catch{AudioManager.ForceReset();}")
///
public class AudioManager :
#if Sirenix_OdinInspector
SerializedMonoBehaviour
#else
MonoBehaviour
#endif
{
public static AudioManager Instance
{
get
{
CreatAudioManager();
return instance;
}
}
#if Sirenix_OdinInspector
#elif UNITY_EDITOR
[Header("注意!不要在面板上修改任何值!面板仅为方便观察"),Space(10)]
#endif
public const int ID_WHEN_NULL = -1;
#region 设置项
///
/// 读取默认配置
///
private void LoadConfig()
{
MuteSound = PlayerPrefs.GetInt("MuteSound") > 0 ? true : false;
SoundVolume = PlayerPrefs.GetFloat("SoundVolume");
MuteMusic = PlayerPrefs.GetInt("MuteMusic") > 0 ? true : false;
MusicVolume = PlayerPrefs.GetFloat("MuteSound");
}
private void SaveConfig()
{
PlayerPrefs.SetInt("MuteSound", MuteSound ? 1 : 0);
PlayerPrefs.SetFloat("SoundVolume", SoundVolume);
PlayerPrefs.SetInt("MuteSound", MuteMusic ? 1 : 0);
PlayerPrefs.SetFloat("MuteSound", MusicVolume);
PlayerPrefs.Save();
}
///
/// 音效静音
///
public bool MuteSound
{
get
{
return muteSound;
}
set
{
if (muteSound == value)
return;
needSave = true;
saveTime = 0;
muteSound = value;
if (!muteSound)
return;
for (int i = 0; i < playingAudio.Count; i++)
{
if (playingAudio != null
&& !playingAudio[i].IsMusic)
{
playingAudio[i].Stop(0, true);
}
}
}
}
///
/// 音效音量
///
public float SoundVolume
{
get
{
return soundVolume;
}
set
{
if (soundVolume == value)
return;
needSave = true;
saveTime = 0;
soundVolume = value;
}
}
///
/// 背景音乐静音
///
public bool MuteMusic
{
get
{
return muteMusic;
}
set
{
if (muteMusic == value)
return;
needSave = true;
saveTime = 0;
muteMusic = value;
if (!muteMusic)
return;
for (int i = 0; i < playingAudio.Count; i++)
{
if (playingAudio != null
&& playingAudio[i].IsMusic)
{
playingAudio[i].Stop(2, false);
}
}
}
}
///
/// 背景音乐声音大小
///
public float MusicVolume
{
get
{
return musicVolume;
}
set
{
if (musicVolume == value)
return;
needSave = true;
saveTime = 0;
musicVolume = value;
}
}
#endregion 设置项
#region 全局工具
public void Init()
{
idPointer = 0;
AudioControllerDic.Clear();
LoadConfig();
OnInit();
//PerLoad();
}
///
/// 重置
///
public void ForceReset()
{
while (sourceCachePool.Count > 0)
{
sourceCachePool.Dequeue().Release();
}
playingMusic = null;
playingBGSound = null;
for (int i = 0; i < playingAudio.Count; i++)
{
if (playingAudio[i] != null)
playingAudio[i].Release();
}
playingAudio.Clear();
audioClipPool.Clear();
poolTotalCount = 0;
audioTotalCount = 0;
recordTimes = 0;
lastRecordTime = 0;
Init();
}
///
/// 停止所有声音
///
public void StopAll()
{
for (int i = 0; i < playingAudio.Count; i++)
{
if (playingAudio[i] != null)
{
playingAudio[i].Stop(1, false);
}
}
}
///
/// 让某声音控制器停止播放
///
/// 声音控制器ID
/// 过渡时间
/// 是否等待播放完成
public void StopAudio(int id, float transitionTime = 0, bool waitFinished = false)
{
if (id == ID_WHEN_NULL)
return;
if (!AudioControllerDic.ContainsKey(id))
return;
if (AudioControllerDic[id] == null)
return;
AudioControllerDic[id].Stop(transitionTime, waitFinished);
}
#endregion 全局工具
#region 背景音乐相关接口
///
/// 播放背景音乐
///
/// 音频文件名
/// 过渡时间
/// 声音控制器ID
public int PlayBackGroundMusic(string clipName, float transitionTime = 1)
{
if (MuteMusic)
return ID_WHEN_NULL;
if (clipName == null)
return ID_WHEN_NULL;
if (IsPlayingBGM(clipName))
return playingMusic.ID;
if (transitionTime < 0)
transitionTime = 0;
if (playingMusic != null)
playingMusic.Stop(transitionTime, false);
playingMusic = GetController();
playingMusic.SetMusic(transitionTime, false, true, GetClip(clipName));
return playingMusic.ID;
}
///
/// 是否正在播放
///
///
public bool IsPlayingBGM()
{
if (MuteMusic)
return false;
if (playingMusic == null)
return false;
return playingMusic.IsPlaying();
}
///
/// 是否正在播放背景音乐
///
///
public bool IsPlayingBGM(string clipName)
{
if (MuteMusic)
return false;
if (playingMusic == null)
return false;
return playingMusic.IsPlaying(clipName);
}
///
/// 停止播放
///
/// 是否等待播放完成再停止
public void StopBGM(bool waitEnd = false)
{
if (playingMusic == null)
return;
playingMusic.Stop(2, waitEnd);
}
///
/// 得到当前正在播放的背景音乐
///
///
public string GetCurrBGM()
{
if (MuteMusic)
return null;
if (playingMusic == null)
return null;
if (!playingMusic.IsPlaying())
return null;
if (playingMusic.audioClips == null)
return null;
if (playingMusic.CurrIdex >= playingMusic.audioClips.Length)
return playingMusic.audioClips[0].name;
return playingMusic.audioClips[playingMusic.CurrIdex].name;
}
///
/// 加入背景音乐播放队列
///
///
///
public void PlayQueuedBGM(string clipName, float transitionTime = 0)
{
if (MuteMusic)
return;
/* */
}
#endregion 背景音乐相关接口
#region 音效相关接口
///
/// 是否正在播放背景音效
///
///
public bool IsPlayingRandomSound()
{
if (MuteSound)
return false;
if (playingBGSound == null)
return false;
return playingBGSound.IsPlaying();
}
///
/// 得到当前正在播放的背景音效
///
///
public string[] GetCurrRandomSound()
{
if (MuteSound)
return null;
if (playingBGSound == null)
return null;
if (!playingBGSound.IsPlaying())
return null;
if (playingBGSound.audioClips == null)
return null;
string[] tmp = new string[playingBGSound.audioClips.Length];
for (int i = 0; i < tmp.Length; i++)
{
if (playingBGSound.audioClips[i] != null)
tmp[i] = playingBGSound.audioClips[i].name;
}
return tmp;
}
///
/// 播放随机背景音效(2D)
/// 随机间隔随机播放音效
///
/// 声音片段名,为null不播放
/// 最小播放间隔
/// 最大播放间隔
/// 声音控制器ID
public int PlayRandomSound(string[] clipNames, float minInterval, float maxInterval)
{
if (MuteSound)
return ID_WHEN_NULL;
if (playingBGSound != null)
{
playingBGSound.Stop(0, true);
}
if (clipNames == null || clipNames.Length == 0)
{
playingBGSound = null;
return ID_WHEN_NULL;
}
playingBGSound = GetController();
playingBGSound.SetSound(null, Vector3.zero, 0, true, 1, true, 1, GetClip(clipNames));
playingBGSound.SetInterval(minInterval, maxInterval);
return playingBGSound.ID;
}
///
/// 播放一个2D音效
/// 用于播放提示音等
///
public int PlaySound(string clipName, float volume = 1)
{
if (MuteSound)
return ID_WHEN_NULL;
if (clipName == null)
return ID_WHEN_NULL;
AudioController audioController = GetController();
audioController.SetSound(null, Vector3.zero, 0, true, 1, true, volume, GetClip(clipName));
return audioController.ID;
}
public int PlaySound(string clipName, Transform target, Vector3 pos, float volume = 1, float pitch = 1)
{
if (MuteSound)
return ID_WHEN_NULL;
if (clipName == null)
return ID_WHEN_NULL;
AudioController audioController = GetController();
audioController.SetSound(target, pos, 1, false, pitch, false, volume, GetClip(clipName));
return audioController.ID;
}
public int PlaySound(string[] clipName, Transform target, Vector3 pos, float length = 0, bool random = false, float volume = 1, float pitch = 1)
{
if (MuteSound)
return ID_WHEN_NULL;
if (clipName == null)
return ID_WHEN_NULL;
AudioController audioController = GetController();
audioController.SetSound(target, pos, 1, random, pitch, false, volume, GetClip(clipName));
if (length > 0)
audioController.SetRemainingLength(length, 0);
return audioController.ID;
}
#endregion 音效相关接口
#region 私有成员
private bool muteSound = false;
private float soundVolume = 1;
private bool muteMusic = false;
private float musicVolume = 1;
private float saveTime = 0;
private bool needSave = false;
#if Sirenix_OdinInspector
[SerializeField, ReadOnly]
#else
[SerializeField]
#endif
private Dictionary AudioControllerDic = new Dictionary();
private static AudioManager instance;
private static void CreatAudioManager()
{
if (instance == null)
{
AudioManager[] audioManagers = FindObjectsOfType();
if (audioManagers != null && audioManagers.Length > 0)
{
instance = audioManagers[0];
DontDestroyOnLoad(instance.gameObject);
if (audioManagers.Length > 1)
{
Debug.Log("场景中存在多余的AudioManager");
}
}
else
{
GameObject obj = new GameObject("AudioManager");
DontDestroyOnLoad(obj);
instance = obj.AddComponent();
}
}
}
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
OnAwake();
}
#region 生命周期
private void OnAwake()
{
}
private void OnInit()
{
}
private void Update()
{
//驱动AudioController
for (int i = 0; i < playingAudio.Count; i++)
{
if (playingAudio[i] == null)
continue;
//更新
playingAudio[i].OnUpdate(Time.deltaTime);
//判断更新结果
if (playingAudio[i].IsDestroyed)
{
playingAudio[i] = null;
continue;
}
if (playingAudio[i].IsPlayFinished ||
playingAudio[i].IsReleased)
{
Lose(playingAudio[i]);
}
}
//缓存池
UpdateCache(Time.deltaTime);
//延迟保存配置项
if (needSave)
{
saveTime += Time.deltaTime;
if (saveTime > 10)
{
SaveConfig();
needSave = false;
saveTime = 0;
}
}
}
#endregion 生命周期
#region 缓存池
/*
* 作用是创建AudioSource、AudioClip,回收AudioSource、AudioClip,减少实例和销毁频率
* 如果缓存了过多的对象,要定时清理
*/
#if Sirenix_OdinInspector
[SerializeField, ReadOnly]
#elif UNITY_EDITOR
[SerializeField]
#endif
private AudioController playingMusic;//不会有两个背景音乐同时播放
#if Sirenix_OdinInspector
[SerializeField, ReadOnly]
#elif UNITY_EDITOR
[SerializeField]
#endif
private AudioController playingBGSound;
#if Sirenix_OdinInspector
[SerializeField, ReadOnly]
#elif UNITY_EDITOR
[SerializeField]
#endif
private readonly Dictionary audioClipPool = new Dictionary();
private readonly List playingAudio = new List();
private readonly Queue sourceCachePool = new Queue();
///
/// 预加载
///
private void PerLoad()
{
for (int i = 0; i < 5; i++)
{
Lose(CreatAudioController());
}
}
private uint poolTotalCount = 0;
private uint audioTotalCount = 0;
private uint recordTimes = 0;
private float lastRecordTime = 0;
private int idPointer = 0;
///
/// 这样会不会增多GC?
///
///
private void UpdateCache(float deltaTime)
{
if (Time.realtimeSinceStartup - lastRecordTime < 20)
return;
lastRecordTime = Time.realtimeSinceStartup;
recordTimes++;
poolTotalCount += (uint)sourceCachePool.Count;
poolTotalCount += (uint)playingAudio.Count;
if (sourceCachePool.Count > poolTotalCount / recordTimes * 1.25f)
{
int n = sourceCachePool.Count / 4;
for (int i = 0; i < n; i++)
{
sourceCachePool.Dequeue().Release();
}
}
if (playingAudio.Count > audioTotalCount / recordTimes * 1.25f)
{
playingAudio.RemoveAll((AudioController a) => { return a == null; });
}
if (recordTimes > 15)
{
poolTotalCount = 0;
audioTotalCount = 0;
recordTimes = 0;
}
}
private AudioController AddPlayingAudioList(AudioController audioController)
{
if (playingAudio.Contains(audioController))
return audioController;
for (int i = 0; i < playingAudio.Count; i++)
{
if (playingAudio == null)
{
playingAudio[i] = audioController;
return audioController;
}
}
playingAudio.Add(audioController);
return audioController;
}
private AudioController GetController()
{
if (sourceCachePool.Count == 0)
{
return AddPlayingAudioList(CreatAudioController());
}
AudioController audioController;
for (int i = 0; i < sourceCachePool.Count; i++)
{
audioController = sourceCachePool.Dequeue();
if (audioController.IsReleased)//可用?
{
return AddPlayingAudioList(audioController);
}
sourceCachePool.Enqueue(audioController);
}
return AddPlayingAudioList(CreatAudioController());
}
private void Lose(AudioController audioController)
{
if (playingAudio.Contains(audioController))
playingAudio.Remove(audioController);
if (audioController == null ||
audioController.IsDestroyed)
return;
if (!sourceCachePool.Contains(audioController))
sourceCachePool.Enqueue(audioController);
audioController.SetDisable();
}
private AudioClip GetClip(string cname)
{
if (cname == null)
return null;
//存在
if (audioClipPool.ContainsKey(cname) &&
audioClipPool[cname] != null)
{
return audioClipPool[cname];
}
//创建成功
if (CreatAudioClip(cname))
{
return audioClipPool[cname];
}
//创建失败
return null;
}
private AudioClip[] GetClip(string[] names)
{
if (names == null)
return null;
//AudioClip[] audioClips = new AudioClip[names.Length];
Queue audioClips = new Queue();
AudioClip audioClip;
for (int i = 0; i < names.Length; i++)
{
audioClip = GetClip(names[i]);
if (audioClip != null)
audioClips.Enqueue(GetClip(names[i]));
}
if (audioClips.Count == 0)
return null;
return audioClips.ToArray();
}
//private void Lose(AudioClip audioClip)
//{
// audioClipPool.Remove(audioClip.name);
// Resources.UnloadAsset(audioClip);
//}
///
/// 读取音频文件,改变读取方式可修改这里
///
///
/// 是否读取成功
private bool CreatAudioClip(string name)
{
AudioClip audioClip = Resources.Load(name);
if (audioClip == null)
{
Debug.LogError("读取音频资源失败:" + name);
return false;
}
if (audioClipPool.ContainsKey(name))
audioClipPool[name] = audioClip;
else
audioClipPool.Add(name, audioClip);
return true;
}
///
/// 默认属性模板,改默认属性在这里
/// 特性在AudioController.SetXXX()
///
///
private AudioController CreatAudioController()
{
return new AudioController(this);
}
#endregion 缓存池
///
/// 保存必要信息,以及自主控制声音播放
/// 若以后有多种行为可改为接口编程
///
[System.Serializable]
private class AudioController
{
///
/// 声音控制器ID
///
internal readonly int ID;
///
/// 目标声音源组建
///
#if Sirenix_OdinInspector
[SerializeField, ReadOnly, GUIColor("BGC")]
#elif UNITY_EDITOR
[SerializeField]
#endif
private AudioSource audioSource;
///
/// 是否正在播放,用于面板显示
///
#if Sirenix_OdinInspector
#elif UNITY_EDITOR
[SerializeField]
#endif
private bool playing = false;
#if UNITY_EDITOR
///
/// 用于限制面板显示播放进度的最大值和最小值
///
private float maxProgress = 1;
///
/// 播放进度,用于面板显示
///
#endif
#if Sirenix_OdinInspector
private Color BGC { get { return playing ? Color.green : Color.red; } set { } }
[SerializeField, ReadOnly, PropertyRange(0, "maxProgress"), GUIColor("BGC")]
private float progress = 0;
#elif UNITY_EDITOR
[SerializeField]
private float progress = 0;
#endif
///
/// 当前音频片段结束时间
///
private float endTime;
///
/// 定时停止播放
///
private float stopTime = 0;
///
/// 待播音频
///
internal AudioClip[] audioClips { get; private set; }
///
/// 追随目标
///
private Transform target;
///
/// 坐标及偏移
///
private Vector3 pos;
///
/// 是否随机
///
private bool random = false;
///
/// 是否循环
///
private bool loop = false;
///
/// 为真这逐渐停止播放
///
private bool stoping = false;
///
/// 渐入渐出用的
///
private float volumescale = 0;
#region AudioSource属性
internal float minDistance
{
get { return audioSource.minDistance; }
set { audioSource.minDistance = value; }
}
internal float maxDistance
{
get { return audioSource.maxDistance; }
set { audioSource.maxDistance = value; }
}
internal float spatialBlend
{
get { return audioSource.spatialBlend; }
set { audioSource.spatialBlend = value; }
}
internal float pitch
{
get { return audioSource.pitch; }
set { audioSource.pitch = value; }
}
internal bool mute
{
get { return audioSource.mute; }
set { audioSource.mute = value; }
}
#endregion AudioSource属性
internal AudioController(AudioManager audioManager)
{
ID = audioManager.idPointer++;
audioManager.AudioControllerDic.Add(ID, this);
IsPlayFinished = false;
IsDestroyed = false;
audioSource = new GameObject("AudioPlayer").AddComponent();
audioSource.transform.SetParent(instance.transform, false);
audioSource.playOnAwake = false;
audioSource.loop = false;
}
///
/// 当前正在播放的几个音频
///
internal int CurrIdex { get; private set; }
///
/// 是否播放完成
///
internal bool IsPlayFinished { get; private set; }
///
/// 是否被销毁
///
internal bool IsDestroyed { get; private set; }
///
/// 是背景音乐还是音效
///
internal bool IsMusic { get; private set; }
///
/// 是否不再使用(不再播放,没有渐变,不需要再更新。可以重新利用了)
///
internal bool IsReleased { get; private set; }
///
/// 过渡时间
///
internal float TransitionTime { get; private set; }
///
/// 音量参数,不是实际音量,是传入的音量
///
internal float Volume { get; private set; }
///
/// 最小随机间隔
///
internal float MinInterval { get; private set; }
///
/// 最大随机间隔
///
internal float MaxInterval { get; private set; }
///
/// 开始播放的时间
///
internal float StartTime { get; private set; }
///
/// 播放背景音乐(背景音乐模板)
///
///
///
internal void SetMusic(float transitionTime, bool random, bool loop, params AudioClip[] audioClips)
{
//判断这些音频是否可用
if (audioClips == null || audioClips.Length == 0 || audioClips[0] == null)
{
audioSource.Stop();
IsPlayFinished = true;
IsReleased = true;
return;
}
//初始化数值
stopTime = 0;
IsPlayFinished = false;
IsReleased = false;
target = null;
volumescale = 0;
Volume = 1;
StartTime = Time.realtimeSinceStartup;
IsMusic = true;
audioSource.loop = true;
loop = true;
stoping = false;
pitch = 1;
audioSource.spatialBlend = 0;
audioSource.loop = true;
pos = Vector3.zero;
CurrIdex = 0;
#if UNITY_EDITOR
//面板显示进度
endTime = 0;
for (int i = 0; i < audioClips.Length; i++)
{
if (audioClips[i] != null)
{
endTime += audioClips[i].length;
}
}
#if Sirenix_OdinInspector
maxProgress = endTime;
#endif
#endif
//赋值
TransitionTime = transitionTime;
if (audioClips.Length > 1)
this.random = random;
else
this.random = false;
if (random)
this.loop = true;
else
this.loop = loop;
this.audioClips = audioClips;
Play();
}
///
/// 播放音效(音效模板)
///
/// 音效跟谁目标
/// 偏移或世界坐标
/// 2D或3D声音(0~1)
/// 是否随机播放,若随机,则一定循环
/// 音调
/// 是否循环,若随机,则一定循环
/// 音频文件
internal void SetSound(Transform target, Vector3 pos, float space3d, bool random, float pitch, bool loop, float volume, params AudioClip[] audioClips)
{
//判断这些音频是否可用
if (audioClips == null || audioClips.Length == 0 || audioClips[0] == null)
{
audioSource.Stop();
IsPlayFinished = true;
IsReleased = true;
return;
}
//初始化数值
SetInterval(0, 0);
stopTime = 0;
IsPlayFinished = false;
IsReleased = false;
volumescale = 0;
stoping = false;
TransitionTime = 0;
IsMusic = false;
CurrIdex = -1;
StartTime = Time.realtimeSinceStartup;
this.target = target;
this.pos = pos;
audioSource.loop = false;
#if UNITY_EDITOR
//面板显示进度
endTime = 0;
for (int i = 0; i < audioClips.Length; i++)
{
if (audioClips[i] != null)
{
endTime += audioClips[i].length;
}
}
#if Sirenix_OdinInspector
maxProgress = endTime;
#endif
#endif
//赋值
this.audioClips = audioClips;
if (audioClips.Length > 1)
this.random = random;
else
this.random = false;
if (random)
this.loop = true;
else
this.loop = loop;
this.pitch = pitch;
audioSource.spatialBlend = space3d;
Volume = volume;
//位置信息
if (target == null)
{
audioSource.transform.position = pos;
}
else
{
if (pos == Vector3.zero)
{
this.pos = Vector3.zero;
audioSource.transform.position = target.position;
}
else
{
this.pos = new Vector3(pos.x * target.lossyScale.x, pos.y * target.lossyScale.y, pos.z * target.lossyScale.z);
audioSource.transform.position = target.TransformPoint(this.pos);
}
}
}
///
/// 播放多段音频时,设置随机间隔
///
/// 最小间隔
/// 最大间隔
internal void SetInterval(float minInterval, float maxInterval)
{
MinInterval = minInterval;
MaxInterval = maxInterval;
}
///
/// 重设audioClips
/// 参数为空时不生效
///
///
internal void SetAudioClips(params AudioClip[] audioClips)
{
if (audioClips == null || audioClips.Length == 0 || audioClips[0] == null)
return;
this.audioClips = audioClips;
}
///
/// 如果后续添加其他模板
/// (说好的对拓展开放,对修改关闭呢。。。这妥妥的相反)
/// (有需要可以修改一下,把这些内容放到派生类,只是初值不同)
///
internal void SetOther()
{
//never use 警报
#if UNITY_EDITOR
if (playing || progress == 0 || maxProgress == 0) { }
#endif
}
///
/// 禁用,准备回收
///
internal void SetDisable()
{
audioClips = null;
target = null;
pos = Vector3.zero;
IsReleased = true;
if (audioSource != null)
{
//if (audioSource.transform != instance.transform)
{
audioSource.Stop();
audioSource.transform.SetParent(instance.transform);
audioSource.transform.localPosition = Vector3.zero;
audioSource.gameObject.SetActive(false);
return;
}
//audioSource.enabled = false;
}
}
internal void OnUpdate(float deltaTime)
{
//检查是否可用,不可用标记销毁
if (!IsValid())
{
IsDestroyed = true;
Release();
playing = false;
return;
}
#if UNITY_EDITOR
//面板显示进度
progress = Time.realtimeSinceStartup - StartTime;
if (random)
{
progress = audioSource.time;
}
if (random || stopTime > 0)
{
if (progress > maxProgress)
{
progress = maxProgress;
}
}
else if (loop)
{
progress = audioSource.time;
if (progress > maxProgress)
{
progress -= maxProgress;
}
}
#if !Sirenix_OdinInspector
progress /= maxProgress;
#endif
#endif
//跟随目标移动,而不作为目标的子物体,防止随目标一起销毁
if (target != null)
{
if (pos == Vector3.zero)
{
audioSource.transform.position = target.position;
}
else
{
audioSource.transform.position = target.TransformPoint(pos);
}
}
//渐出
if (stoping)
{
if (TransitionTime == 0 ||
volumescale <= 0)
{
volumescale = 0;
audioSource.volume = 0;
IsPlayFinished = true;
return;
}
audioSource.volume = Volume * (IsMusic ? instance.MusicVolume : instance.SoundVolume) * volumescale;
volumescale -= deltaTime / TransitionTime;
return;
}
//定时停止播放
if (stopTime > 0 && Time.time > stopTime)
{
Stop(TransitionTime, false);
}
//音量过渡
if (TransitionTime == 0 ||
volumescale >= 1)
{
volumescale = 1;
}
else
{
volumescale += deltaTime / TransitionTime;
}
audioSource.volume = Volume * (IsMusic ? instance.MusicVolume : instance.SoundVolume) * volumescale;
//播放完成不需要切换音频
if (IsPlayFinished || (IsMusic && loop))
return;
//检查播放进度,播放下一个音频,或标记为播放完成
//暂时没有排除audioClips数组中有空指针的情况
if (Time.realtimeSinceStartup >= endTime)
{
if (random)//随机顺序
{
CurrIdex = Random.Range(0, audioClips.Length);
Play();
return;
}
CurrIdex++;
if (CurrIdex < audioClips.Length)//顺序
{
Play();
return;
}
if (loop)//顺序循环
{
CurrIdex = 0;
Play();
return;
}
//顺序不循环==完成播放
IsPlayFinished = true;
playing = false;
}
}
///
/// 播放
///
private void Play()
{
if (CurrIdex >= audioClips.Length || audioClips[CurrIdex] == null)
{
//audioSource.Stop();
return;
}
playing = true;
audioSource.gameObject.SetActive(true);
audioSource.clip = audioClips[CurrIdex];
if (MinInterval == MaxInterval)
{
endTime = Time.realtimeSinceStartup + audioClips[CurrIdex].length + MinInterval;
}
else
{
endTime = Time.realtimeSinceStartup + audioClips[CurrIdex].length + Random.Range(MinInterval, MaxInterval);
}
audioSource.Play();
#if Sirenix_OdinInspector
//面板显示进度
if (stopTime <= 0)
{
if (random)
{
maxProgress = audioClips[CurrIdex].length;
}
}
#elif UNITY_EDITOR
maxProgress = 1;
#endif
}
///
/// 停止播放
///
/// 渐出时间
/// 是否等待播放完成,若等待完成则没有渐出效果
internal void Stop(float transitionTime, bool waitFinished)
{
playing = false;
TransitionTime = transitionTime;
if (waitFinished)
{
CurrIdex = audioClips.Length;
audioSource.loop = false;
endTime = Time.realtimeSinceStartup + (audioSource.clip.length - audioSource.time % audioSource.clip.length);
loop = false;
}
else
{
stoping = true;
}
}
///
/// 设置剩余长度
///
///
internal void SetRemainingLength(float l, float transitionTime)
{
TransitionTime = transitionTime;
stopTime = Time.time + l;
#if Sirenix_OdinInspector
maxProgress = Time.realtimeSinceStartup + l - StartTime;
#endif
loop = true;
}
///
/// 检查是否有效
///
///
private bool IsValid()
{
if (IsDestroyed)
return false;
if (audioSource == null)
return false;
return true;
}
///
/// 释放资源,准备销毁
///
internal void Release()
{
playing = false;
IsDestroyed = true;
if (audioSource != null /*&&
audioSource.transform != instance.transform*/)
{
Destroy(audioSource.gameObject);
}
if (instance.AudioControllerDic.ContainsKey(ID))
instance.AudioControllerDic.Remove(ID);
target = null;
audioClips = null;
}
///
/// 是否正在播放
///
///
internal bool IsPlaying()
{
return !IsDestroyed &&
!stoping &&
!IsPlayFinished &&
audioSource.isPlaying;
}
///
/// 是否正在播放某段音频
///
///
///
internal bool IsPlaying(string clipName)
{
return !IsDestroyed &&
!stoping &&
!IsPlayFinished &&
clipName.EndsWith(audioSource.clip.name) &&
audioSource.isPlaying;
}
}
#endregion 私有成员
}