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