using System; using Cysharp.Threading.Tasks; using UnityEngine; using Object = UnityEngine.Object; namespace Stary.Evo.AudioCore { public class MusicPlayer : AbstractAudio, IDisposable { private GameObject poolObject; private AudioSource audioSource1; private AudioSource audioSource2; private AudioSource currentAudioSource; private Coroutine myCoroutine; public MusicPlayer(IResources resources) : base(resources) { poolObject = GameObject.Find(GetType().Name); if (poolObject == null) { // 如果不存在,创建一个新对象 poolObject = new GameObject(GetType().Name); } CreatAudioSource("audioSource1", out audioSource1); CreatAudioSource("audioSource2", out audioSource2); } /// /// 播放背景音乐 /// /// {[clip:音频], [volume:音量], [fadeDuration:自然过渡时间], /// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置], [audio3DMaxDistance:3D音频最大距离]} public override async void Play(AudioData audioData) { if (Resources == null) { Debug.LogError("AudioCoreManager: Resources is null, please initialize it first."); return; } audioData = Initialize(audioData); if (!string.IsNullOrEmpty(audioData.packageName) && !string.IsNullOrEmpty(audioData.assetName)) { var clip = await Resources.LoadAssetAsync(audioData.packageName, audioData.assetName); if (clip == null) { Debug.LogErrorFormat($"从资源包【{audioData.packageName}】加载音频片段【{audioData.assetName}】失败"); } else { audioData.clip = clip; } } if (audioData.clip == null) { Debug.LogError("播放的音效音频片段为空"); return; } if (audioSource1 != null && audioSource1.isPlaying == false) { audioSource1.clip = audioData.clip; audioSource1.volume = audioData.volume; audioSource1.loop = true; // 设置2D与3D音频 if (audioData.is3DAudio) { audioSource1.transform.position = audioData.audio3DPosition; audioSource1.spatialBlend = 1; audioSource1.minDistance = 1f; if (audioData.audio3DMaxDistance != 0) { audioSource1.maxDistance = audioData.audio3DMaxDistance; } else { // 默认3D最大距离为3米 audioSource1.maxDistance = 3f; } } else { audioSource1.transform.position = Vector3.zero; audioSource1.spatialBlend = 0; audioSource1.minDistance = 1f; audioSource1.maxDistance = 500f; } currentAudioSource = audioSource1; currentAudioSource.Play(); FadeMusic(audioSource1, audioData.fadeDuration, audioSource2); } else if (audioSource2 != null && audioSource2.isPlaying == false) { audioSource2.clip = audioData.clip; audioSource2.volume = audioData.volume; audioSource2.loop = true; // 设置2D与3D音频 if (audioData.is3DAudio) { audioSource2.transform.position = audioData.audio3DPosition; audioSource2.spatialBlend = 1; audioSource2.minDistance = 1f; if (audioData.audio3DMaxDistance != 0) { audioSource2.maxDistance = audioData.audio3DMaxDistance; } else { // 默认3D最大距离为3米 audioSource2.maxDistance = 3f; } } else { audioSource2.transform.position = Vector3.zero; audioSource2.spatialBlend = 0; audioSource2.minDistance = 1f; audioSource2.maxDistance = 500f; } currentAudioSource = audioSource2; currentAudioSource.Play(); FadeMusic(audioSource2, audioData.fadeDuration, audioSource1); } else { Debug.LogWarning("UnityEvo:已同时存在两个背景乐在切换"); } } public override UniTask PlayAsync(AudioData audioData) { return UniTask.CompletedTask; } public override void StopAll() { FadeAllMusic(0); } public override AudioSource GetAudioSource() { return currentAudioSource; } /// /// 关闭背景音乐 /// /// {[fadeDuration:自然过渡时间]} public override void Stop() { FadeAllMusic(0f); } /// /// 设置自然过渡到指定音量 /// /// /// /// public async UniTask SetMusicVolume(float fadeDuration, float targetVolume) { float startVolume = currentAudioSource.volume; while (!Mathf.Approximately(currentAudioSource.volume, targetVolume)) { if (currentAudioSource.volume > targetVolume) { currentAudioSource.volume -= (startVolume - targetVolume) * Time.deltaTime / fadeDuration; } else { currentAudioSource.volume += (targetVolume - startVolume) * Time.deltaTime / fadeDuration; } if (Mathf.Abs(currentAudioSource.volume - targetVolume) < 0.01f) { currentAudioSource.volume = targetVolume; } await UniTask.Yield(); } } /// /// 切换音频 /// /// 播放的音频 /// 变化时间 /// 停止的音频 /// private void FadeMusic(AudioSource source1, float fadeDuration, AudioSource source2 = null) { FadeInMusic(source1, fadeDuration); FadeOutMusic(source2, fadeDuration); } public void FadeAllMusic(float fadeDuration) { currentAudioSource = null; FadeOutMusic(audioSource1, fadeDuration); FadeOutMusic(audioSource2, fadeDuration); } /// /// 创建一个新的AudioSource对象 /// /// private void CreatAudioSource(string name, out AudioSource source) { source = new GameObject(name).AddComponent(); source.gameObject.transform.SetParent(poolObject.transform); source.transform.SetParent(poolObject.transform); // 将新对象作为当前对象的子对象 source.playOnAwake = false; // 添加 AudioSource 组件并禁用自动播放 } public void Dispose() { FadeAllMusic(0f); Object.Destroy(audioSource1.gameObject); Object.Destroy(audioSource2.gameObject); audioSource1 = null; audioSource2 = null; } } }