using UnityEngine; using UnityEngine.Audio; using YooAsset; namespace TEngine { /// /// 音频代理辅助器。 /// public class AudioAgent { private int _instanceId; private AudioSource _source; private AudioData _audioData; private IAudioModule _audioModule; private IResourceModule _resourceModule; private Transform _transform; private float _volume = 1.0f; private float _duration; private float _fadeoutTimer; private const float FADEOUT_DURATION = 0.2f; private bool _inPool; /// /// 音频代理辅助器运行时状态。 /// AudioAgentRuntimeState _audioAgentRuntimeState = AudioAgentRuntimeState.None; /// /// 音频代理加载请求。 /// class LoadRequest { /// /// 音频代理辅助器加载路径。 /// public string Path; /// /// 是否异步。 /// public bool BAsync; /// /// 是否池化。 /// public bool BInPool; } /// /// 音频代理加载请求。 /// LoadRequest _pendingLoad = null; /// /// AudioSource实例化Id /// public int InstanceId => _instanceId; /// /// 资源操作句柄。 /// public AudioData AudioData => _audioData; /// /// 音频代理辅助器音频大小。 /// public float Volume { set { if (_source != null) { _volume = value; _source.volume = _volume; } } get => _volume; } /// /// 音频代理辅助器当前是否空闲。 /// public bool IsFree { get { if (_source != null) { return _audioAgentRuntimeState == AudioAgentRuntimeState.End; } else { return true; } } } /// /// 音频代理辅助器播放秒数。 /// public float Duration => _duration; /// /// 音频代理辅助器当前音频长度。 /// public float Length { get { if (_source != null && _source.clip != null) { return _source.clip.length; } return 0; } } /// /// 音频代理辅助器实例位置。 /// public Vector3 Position { get => _transform.position; set => _transform.position = value; } /// /// 音频代理辅助器是否循环。 /// public bool IsLoop { get { if (_source != null) { return _source.loop; } else { return false; } } set { if (_source != null) { _source.loop = value; } } } /// /// 音频代理辅助器是否正在播放。 /// internal bool IsPlaying { get { if (_source != null && _source.isPlaying) { return true; } else { return false; } } } /// /// 音频代理辅助器获取当前声源。 /// /// public AudioSource AudioResource() { return _source; } /// /// 创建音频代理辅助器。 /// /// 生效路径。 /// 是否异步。 /// 音频轨道(类别)。 /// 是否池化。 /// 音频代理辅助器。 public static AudioAgent Create(string path, bool bAsync, AudioCategory audioCategory, bool bInPool = false) { AudioAgent audioAgent = new AudioAgent(); audioAgent.Init(audioCategory); audioAgent.Load(path, bAsync, bInPool); return audioAgent; } /// /// 初始化音频代理辅助器。 /// /// 音频轨道(类别)。 /// 音频代理辅助器编号。 public void Init(AudioCategory audioCategory, int index = 0) { _audioModule = ModuleSystem.GetModule(); _resourceModule = ModuleSystem.GetModule(); GameObject host = new GameObject(Utility.Text.Format("Audio Agent Helper - {0} - {1}", audioCategory.AudioMixerGroup.name, index)); host.transform.SetParent(audioCategory.InstanceRoot); host.transform.localPosition = Vector3.zero; _transform = host.transform; _source = host.AddComponent(); _source.playOnAwake = false; AudioMixerGroup[] audioMixerGroups = audioCategory.AudioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}/{1}", audioCategory.AudioMixerGroup.name, $"{audioCategory.AudioMixerGroup.name} - {index}")); _source.outputAudioMixerGroup = audioMixerGroups.Length > 0 ? audioMixerGroups[0] : audioCategory.AudioMixerGroup; _source.rolloffMode = audioCategory.AudioGroupConfig.audioRolloffMode; _source.minDistance = audioCategory.AudioGroupConfig.minDistance; _source.maxDistance = audioCategory.AudioGroupConfig.maxDistance; _instanceId = _source.GetInstanceID(); } /// /// 加载音频代理辅助器。 /// /// 资源路径。 /// 是否异步。 /// 是否池化。 public void Load(string path, bool bAsync, bool bInPool = false) { _inPool = bInPool; if (_audioAgentRuntimeState == AudioAgentRuntimeState.None || _audioAgentRuntimeState == AudioAgentRuntimeState.End) { _duration = 0; if (!string.IsNullOrEmpty(path)) { if (bInPool && _audioModule.AudioClipPool.TryGetValue(path, out var operationHandle)) { OnAssetLoadComplete(operationHandle); return; } if (bAsync) { _audioAgentRuntimeState = AudioAgentRuntimeState.Loading; AssetHandle handle = _resourceModule.LoadAssetAsyncHandle(path); handle.Completed += OnAssetLoadComplete; } else { AssetHandle handle = _resourceModule.LoadAssetSyncHandle(path); OnAssetLoadComplete(handle); } } } else { _pendingLoad = new LoadRequest { Path = path, BAsync = bAsync, BInPool = bInPool }; if (_audioAgentRuntimeState == AudioAgentRuntimeState.Playing) { Stop(true); } } } /// /// 停止播放音频代理辅助器。 /// /// 是否渐出。 public void Stop(bool fadeout = false) { if (_source != null) { if (fadeout) { _fadeoutTimer = FADEOUT_DURATION; _audioAgentRuntimeState = AudioAgentRuntimeState.FadingOut; } else { _source.Stop(); _audioAgentRuntimeState = AudioAgentRuntimeState.End; } } } /// /// 暂停音频代理辅助器。 /// public void Pause() { if (_source != null) { _source.Pause(); } } /// /// 取消暂停音频代理辅助器。 /// public void UnPause() { if (_source != null) { _source.UnPause(); } } /// /// 资源加载完成。 /// /// 资源操作句柄。 void OnAssetLoadComplete(AssetHandle handle) { if (handle != null) { if (_inPool) { _audioModule.AudioClipPool.TryAdd(handle.GetAssetInfo().Address, handle); } } if (_pendingLoad != null) { if (!_inPool && handle != null) { handle.Dispose(); } _audioAgentRuntimeState = AudioAgentRuntimeState.End; string path = _pendingLoad.Path; bool bAsync = _pendingLoad.BAsync; bool bInPool = _pendingLoad.BInPool; _pendingLoad = null; Load(path, bAsync, bInPool); } else if (handle != null) { if (_audioData != null) { AudioData.DeAlloc(_audioData); _audioData = null; } _audioData = AudioData.Alloc(handle, _inPool); _source.clip = handle.AssetObject as AudioClip; if (_source.clip != null) { _source.Play(); _audioAgentRuntimeState = AudioAgentRuntimeState.Playing; } else { _audioAgentRuntimeState = AudioAgentRuntimeState.End; } } else { _audioAgentRuntimeState = AudioAgentRuntimeState.End; } } /// /// 轮询音频代理辅助器。 /// /// 逻辑流逝时间,以秒为单位。 public void Update(float elapseSeconds) { if (_audioAgentRuntimeState == AudioAgentRuntimeState.Playing) { if (!_source.isPlaying) { _audioAgentRuntimeState = AudioAgentRuntimeState.End; } } else if (_audioAgentRuntimeState == AudioAgentRuntimeState.FadingOut) { if (_fadeoutTimer > 0f) { _fadeoutTimer -= elapseSeconds; _source.volume = _volume * _fadeoutTimer / FADEOUT_DURATION; } else { Stop(); if (_pendingLoad != null) { string path = _pendingLoad.Path; bool bAsync = _pendingLoad.BAsync; bool bInPool = _pendingLoad.BInPool; _pendingLoad = null; Load(path, bAsync, bInPool); } _source.volume = _volume; } } _duration += elapseSeconds; } /// /// 销毁音频代理辅助器。 /// public void Destroy() { if (_transform != null) { Object.Destroy(_transform.gameObject); } if (_audioData != null) { AudioData.DeAlloc(_audioData); } } } }