using System; using System.Collections; using System.Threading; using System.Threading.Tasks; using UnityEngine; namespace Stary.Evo.AudioCore { public class VoicePlayer : AbstractAudio { private AudioSourcePool audioSourcePool; private AudioSource currentSource; private Coroutine myCoroutine; private CancellationTokenSource cancelTokenSource; public VoicePlayer(AudioSourcePool audioSourcePool) { this.audioSourcePool = audioSourcePool; } /// /// 播放语音 /// /// {[clip:音频], [volume:音量], /// [onComplete:回调行为], [delayOnCompleteTime:延迟回调执行的时间], /// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置], /// [audio3DMaxDistance:3D音频最大距离]} public override void Play(AudioData audioData) { // 停止当前正在播放的语音与旧协程,或旧异步 Stop(); audioData = AudioDataInitialize(audioData); if (myCoroutine != null) { CoroutineHelper.Instance.StopCoroutine(myCoroutine); myCoroutine = null; } currentSource = audioSourcePool.GetAudioSource("Voice"); if (currentSource == null) return; currentSource.clip = audioData.clip; currentSource.volume = audioData.volume; // 设置2D与3D音频 if (audioData.is3DAudio) { currentSource.transform.position = audioData.audio3DPosition; currentSource.spatialBlend = 1; currentSource.minDistance = 1f; if (audioData.audio3DMaxDistance != 0) { currentSource.maxDistance = audioData.audio3DMaxDistance; } else { // 默认3D最大距离为3米 currentSource.maxDistance = 3f; } } else { currentSource.transform.position = Vector3.zero; currentSource.spatialBlend = 0; currentSource.minDistance = 1f; currentSource.maxDistance = 500f; } currentSource.Play(); // 使用协程处理延迟和回调 myCoroutine = CoroutineHelper.Instance.StartCoroutine(PlayVoiceCoroutine(currentSource, audioData.delayOnCompleteTime, audioData.onComplete)); } /// /// 停止语音 /// /// /// {[无可使用变量]} public override void Stop() { // 停止当前协程 if (currentSource != null && currentSource.isPlaying) { currentSource.Stop(); audioSourcePool.ReturnAudioSource("Voice", currentSource.gameObject); currentSource = null; if (myCoroutine != null) { CoroutineHelper.Instance.StopCoroutine(myCoroutine); myCoroutine = null; } } // 停掉异步任务 if (cancelTokenSource != null && cancelTokenSource.IsCancellationRequested) { cancelTokenSource .Cancel(); cancelTokenSource.Dispose(); cancelTokenSource = null; } } /// /// 异步播放语音 /// /// {[clip:音频], [volume:音量], /// [onComplete:回调行为], [delayOnCompleteTime:延迟回调执行的时间], /// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置], /// [audio3DMaxDistance:3D音频最大距离], /// [cancellationToken:异步取消令牌]} public async Task PlayAsync(AudioData audioData) { // 停止当前正在播放的语音与旧协程,或旧异步 Stop(); audioData = AudioDataInitialize(audioData); currentSource = audioSourcePool.GetAudioSource("Voice"); if (currentSource == null) return; currentSource.clip = audioData.clip; currentSource.volume = audioData.volume; // 设置2D与3D音频 if (audioData.is3DAudio) { currentSource.transform.position = audioData.audio3DPosition; currentSource.spatialBlend = 1; currentSource.minDistance = 1f; if (audioData.audio3DMaxDistance != 0) { currentSource.maxDistance = audioData.audio3DMaxDistance; } else { // 默认3D最大距离为3米 currentSource.maxDistance = 3f; } } else { currentSource.transform.position = Vector3.zero; currentSource.spatialBlend = 0; currentSource.minDistance = 1f; currentSource.maxDistance = 500f; } currentSource.Play(); await Task.Delay(TimeSpan.FromSeconds(audioData.clip.length), audioData.cancellationToken); } /// /// 播放语音的协程 /// /// /// /// /// private IEnumerator PlayVoiceCoroutine(AudioSource source, float delayOnComplete, System.Action onComplete) { yield return new WaitForSeconds(source.clip.length + delayOnComplete); audioSourcePool.ReturnAudioSource("Voice", source.gameObject); onComplete?.Invoke(); currentSource = null; myCoroutine = null; } } }