From 4519a3bad0f84a9d4a5fe3b60732fe7648749f99 Mon Sep 17 00:00:00 2001 From: ALEXTANG <574809918@qq.com> Date: Thu, 6 Apr 2023 20:32:55 +0800 Subject: [PATCH] AudioModule AudioModule --- Assets/Scenes/main.unity | 20 +- .../Runtime/GameFramework/Audio/AudioAgent.cs | 179 ++++++++++++++---- .../GameFramework/Audio/AudioCategory.cs | 54 +++++- .../GameFramework/Audio/AudioGroupConfig.cs | 9 + .../GameFramework/Audio/AudioModule.cs | 40 +--- 5 files changed, 217 insertions(+), 85 deletions(-) diff --git a/Assets/Scenes/main.unity b/Assets/Scenes/main.unity index 2336b3ff..5e873aae 100644 --- a/Assets/Scenes/main.unity +++ b/Assets/Scenes/main.unity @@ -171,24 +171,36 @@ MonoBehaviour: m_AudioGroupConfigs: - m_Name: Music m_Mute: 0 - m_Volume: 1 + m_Volume: 0.5 m_AgentHelperCount: 1 AudioType: 2 + audioRolloffMode: 1 + minDistance: 15 + maxDistance: 50 - m_Name: Sound m_Mute: 0 - m_Volume: 1 + m_Volume: 0.5 m_AgentHelperCount: 4 AudioType: 0 + audioRolloffMode: 0 + minDistance: 1 + maxDistance: 500 - m_Name: UISound m_Mute: 0 - m_Volume: 1 + m_Volume: 0.5 m_AgentHelperCount: 4 AudioType: 1 + audioRolloffMode: 0 + minDistance: 1 + maxDistance: 500 - m_Name: Voice m_Mute: 0 - m_Volume: 1 + m_Volume: 0.5 m_AgentHelperCount: 1 AudioType: 3 + audioRolloffMode: 0 + minDistance: 1 + maxDistance: 500 --- !u!1 &43232119 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/TEngine/Runtime/GameFramework/Audio/AudioAgent.cs b/Assets/TEngine/Runtime/GameFramework/Audio/AudioAgent.cs index 819b99e3..8c003432 100644 --- a/Assets/TEngine/Runtime/GameFramework/Audio/AudioAgent.cs +++ b/Assets/TEngine/Runtime/GameFramework/Audio/AudioAgent.cs @@ -5,42 +5,80 @@ using YooAsset; namespace TEngine { /// - /// 声音代理辅助器。 + /// 音频代理辅助器。 /// public class AudioAgent { private AudioModule _audioModule; - private int _id = 0; - public AssetOperationHandle assetOperationHandle = null; - private AudioSource _source = null; - Transform _transform = null; + private int _id; + private AudioSource _source; + private AssetOperationHandle _assetOperationHandle; + private Transform _transform; float _volume = 1.0f; - float _duration = 0; - float _fadeoutTimer = 0f; - const float FadeoutDuration = 0.2f; - private bool _inPool = false; + float _duration; + private float _fadeoutTimer; + private const float FadeoutDuration = 0.2f; + private bool _inPool; - enum State + /// + /// 音频代理辅助器运行时状态枚举。 + /// + enum RuntimeState { + /// + /// 无状态。 + /// None, + /// + /// 加载中状态。 + /// Loading, + /// + /// 播放中状态。 + /// Playing, + /// + /// 渐渐消失状态。 + /// FadingOut, + /// + /// 结束状态。 + /// End, }; - State _state = State.None; + /// + /// 音频代理辅助器运行时状态。 + /// + RuntimeState _runtimeState = RuntimeState.None; + /// + /// 音频代理加载请求。 + /// class LoadRequest { - public string path; - public bool bAsync; + public string Path; + public bool BAsync; } + /// + /// 音频代理加载请求。 + /// LoadRequest _pendingLoad = null; + /// + /// AudioSource实例化Id + /// public int ID => _id; + /// + /// 资源操作句柄。 + /// + public AssetOperationHandle assetOperationHandle => _assetOperationHandle; + + /// + /// 音频代理辅助器音频大小。 + /// public float Volume { set @@ -54,13 +92,16 @@ namespace TEngine get => _volume; } - public bool IsFinish + /// + /// 音频代理辅助器当前是否空闲。 + /// + public bool IsFree { get { if (_source != null) { - return _state == State.End; + return _runtimeState == RuntimeState.End; } else { @@ -69,8 +110,14 @@ namespace TEngine } } + /// + /// 音频代理辅助器播放秒数。 + /// public float Duration => _duration; + /// + /// 音频代理辅助器当前音频长度。 + /// public float Length { get @@ -84,12 +131,18 @@ namespace TEngine } } + /// + /// 音频代理辅助器实例位置。 + /// public Vector3 Position { get => _transform.position; set => _transform.position = value; } + /// + /// 音频代理辅助器是否循环。 + /// public bool IsLoop { get @@ -112,6 +165,9 @@ namespace TEngine } } + /// + /// 音频代理辅助器是否正在播放。 + /// internal bool IsPlaying { get @@ -127,11 +183,23 @@ namespace TEngine } } + /// + /// 音频代理辅助器获取当前声源。 + /// + /// public AudioSource AudioResource() { return _source; } + /// + /// 创建音频代理辅助器。 + /// + /// 生效路径。 + /// 是否异步。 + /// 音频轨道(类别)。 + /// 是否池化。 + /// 音频代理辅助器。 public static AudioAgent Create(string path, bool bAsync, AudioCategory audioCategory, bool bInPool = false) { AudioAgent audioAgent = new AudioAgent(); @@ -140,9 +208,14 @@ namespace TEngine return audioAgent; } + /// + /// 初始化音频代理辅助器。 + /// + /// 音频轨道(类别)。 + /// 音频代理辅助器编号。 public void Init(AudioCategory audioCategory,int index = 0) { - _audioModule = GameEntry.GetModule(); + _audioModule = GameModule.Audio; 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; @@ -151,13 +224,22 @@ namespace TEngine _source.playOnAwake = false; AudioMixerGroup[] audioMixerGroups = audioCategory.AudioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}/{1}", 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; _id = _source.GetInstanceID(); } + /// + /// 加载音频代理辅助器。 + /// + /// 资源路径。 + /// 是否异步。 + /// 是否池化。 public void Load(string path, bool bAsync, bool bInPool = false) { _inPool = bInPool; - if (_state == State.None || _state == State.End) + if (_runtimeState == RuntimeState.None || _runtimeState == RuntimeState.End) { _duration = 0; if (!string.IsNullOrEmpty(path)) @@ -170,7 +252,7 @@ namespace TEngine if (bAsync) { - _state = State.Loading; + _runtimeState = RuntimeState.Loading; AssetOperationHandle handle = _audioModule.ResourceManager.LoadAssetAsyncHandle(path); handle.Completed += OnAssetLoadComplete; } @@ -183,15 +265,19 @@ namespace TEngine } else { - _pendingLoad = new LoadRequest { path = path, bAsync = bAsync }; + _pendingLoad = new LoadRequest { Path = path, BAsync = bAsync }; - if (_state == State.Playing) + if (_runtimeState == RuntimeState.Playing) { Stop(true); } } } + /// + /// 暂停音频代理辅助器。 + /// + /// 是否渐出。 public void Stop(bool fadeout = false) { if (_source != null) @@ -199,16 +285,20 @@ namespace TEngine if (fadeout) { _fadeoutTimer = FadeoutDuration; - _state = State.FadingOut; + _runtimeState = RuntimeState.FadingOut; } else { _source.Stop(); - _state = State.End; + _runtimeState = RuntimeState.End; } } } + /// + /// 资源加载完成。 + /// + /// 资源操作句柄。 void OnAssetLoadComplete(AssetOperationHandle handle) { if (handle != null) @@ -220,7 +310,6 @@ namespace TEngine } } - if (_pendingLoad != null) { if (handle != null) @@ -228,46 +317,52 @@ namespace TEngine handle.Dispose(); } - _state = State.End; - string path = _pendingLoad.path; - bool bAsync = _pendingLoad.bAsync; + _runtimeState = RuntimeState.End; + string path = _pendingLoad.Path; + bool bAsync = _pendingLoad.BAsync; _pendingLoad = null; Load(path, bAsync); } else if (handle != null) { - if (assetOperationHandle != null) + if (_assetOperationHandle != null) { - assetOperationHandle.Dispose(); + _assetOperationHandle.Dispose(); } - assetOperationHandle = handle; + _assetOperationHandle = handle; - _source.clip = assetOperationHandle.AssetObject as AudioClip; + _source.clip = _assetOperationHandle.AssetObject as AudioClip; if (_source.clip != null) { _source.Play(); - _state = State.Playing; + _runtimeState = RuntimeState.Playing; } else { - _state = State.End; + _runtimeState = RuntimeState.End; } } else { - _state = State.End; + _runtimeState = RuntimeState.End; } } + /// + /// 轮询音频代理辅助器。 + /// + /// public void Update(float delta) { - if (_state == State.Playing) + if (_runtimeState == RuntimeState.Playing) { if (!_source.isPlaying) - _state = State.End; + { + _runtimeState = RuntimeState.End; + } } - else if (_state == State.FadingOut) + else if (_runtimeState == RuntimeState.FadingOut) { if (_fadeoutTimer > 0f) { @@ -279,8 +374,8 @@ namespace TEngine Stop(); if (_pendingLoad != null) { - string path = _pendingLoad.path; - bool bAsync = _pendingLoad.bAsync; + string path = _pendingLoad.Path; + bool bAsync = _pendingLoad.BAsync; _pendingLoad = null; Load(path, bAsync); } @@ -288,10 +383,12 @@ namespace TEngine _source.volume = _volume; } } - _duration += delta; } + /// + /// 销毁音频代理辅助器。 + /// public void Destroy() { if (_transform != null) @@ -299,9 +396,9 @@ namespace TEngine Object.Destroy(_transform.gameObject); } - if (assetOperationHandle != null) + if (_assetOperationHandle != null) { - assetOperationHandle.Dispose(); + _assetOperationHandle.Dispose(); } } } diff --git a/Assets/TEngine/Runtime/GameFramework/Audio/AudioCategory.cs b/Assets/TEngine/Runtime/GameFramework/Audio/AudioCategory.cs index 24785aeb..d8d1e1cf 100644 --- a/Assets/TEngine/Runtime/GameFramework/Audio/AudioCategory.cs +++ b/Assets/TEngine/Runtime/GameFramework/Audio/AudioCategory.cs @@ -15,13 +15,33 @@ namespace TEngine private AudioMixer _audioMixer = null; public List AudioAgents; private readonly AudioMixerGroup _audioMixerGroup; + private AudioGroupConfig _audioGroupConfig; private int _maxChannel; private bool _bEnable = true; + + /// + /// 音频混响器。 + /// public AudioMixer AudioMixer => _audioMixer; + + /// + /// 音频混响器组。 + /// public AudioMixerGroup AudioMixerGroup => _audioMixerGroup; + /// + /// 音频组配置。 + /// + public AudioGroupConfig AudioGroupConfig => _audioGroupConfig; + + /// + /// 实例化根节点。 + /// public Transform InstanceRoot { private set; get; } + /// + /// 音频轨道是否启用。 + /// public bool Enable { get => _bEnable; @@ -44,12 +64,18 @@ namespace TEngine } } - - public AudioCategory(int maxChannel, AudioMixer audioMixer,AudioType audioType) + /// + /// 音频轨道构造函数。 + /// + /// 最大Channel。 + /// 音频混响器。 + /// 音频轨道组配置。 + public AudioCategory(int maxChannel, AudioMixer audioMixer,AudioGroupConfig audioGroupConfig) { _audioMixer = audioMixer; _maxChannel = maxChannel; - AudioMixerGroup[] audioMixerGroups = audioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}", audioType.ToString())); + _audioGroupConfig = audioGroupConfig; + AudioMixerGroup[] audioMixerGroups = audioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}", audioGroupConfig.AudioType.ToString())); if (audioMixerGroups.Length > 0) { _audioMixerGroup = audioMixerGroups[0]; @@ -69,6 +95,10 @@ namespace TEngine } } + /// + /// 增加音频。 + /// + /// public void AddAudio(int num) { _maxChannel += num; @@ -78,7 +108,13 @@ namespace TEngine } } - + /// + /// 播放音频。 + /// + /// + /// + /// + /// public AudioAgent Play(string path, bool bAsync, bool bInPool = false) { if (!_bEnable) @@ -91,7 +127,7 @@ namespace TEngine for (int i = 0; i < AudioAgents.Count; i++) { - if (AudioAgents[i].assetOperationHandle == null || AudioAgents[i].IsFinish) + if (AudioAgents[i].assetOperationHandle == null || AudioAgents[i].IsFree) { freeChannel = i; break; @@ -123,6 +159,10 @@ namespace TEngine } } + /// + /// 暂停音频。 + /// + /// 是否渐出 public void Stop(bool fadeout) { for (int i = 0; i < AudioAgents.Count; ++i) @@ -134,6 +174,10 @@ namespace TEngine } } + /// + /// 音频轨道轮询。 + /// + /// public void Update(float delta) { for (int i = 0; i < AudioAgents.Count; ++i) diff --git a/Assets/TEngine/Runtime/GameFramework/Audio/AudioGroupConfig.cs b/Assets/TEngine/Runtime/GameFramework/Audio/AudioGroupConfig.cs index 190f219a..ed19e93a 100644 --- a/Assets/TEngine/Runtime/GameFramework/Audio/AudioGroupConfig.cs +++ b/Assets/TEngine/Runtime/GameFramework/Audio/AudioGroupConfig.cs @@ -3,6 +3,9 @@ using UnityEngine; namespace TEngine { + /// + /// 音频轨道组配置。 + /// [Serializable] public sealed class AudioGroupConfig { @@ -20,6 +23,12 @@ namespace TEngine public AudioType AudioType; + public AudioRolloffMode audioRolloffMode = AudioRolloffMode.Logarithmic; + + public float minDistance = 1f; + + public float maxDistance = 500f; + public string Name { get diff --git a/Assets/TEngine/Runtime/GameFramework/Audio/AudioModule.cs b/Assets/TEngine/Runtime/GameFramework/Audio/AudioModule.cs index 603e3275..510aac4c 100644 --- a/Assets/TEngine/Runtime/GameFramework/Audio/AudioModule.cs +++ b/Assets/TEngine/Runtime/GameFramework/Audio/AudioModule.cs @@ -23,15 +23,10 @@ namespace TEngine private float _volume = 1f; private bool _enable = true; - private int _audioChannelMaxNum = 0; private AudioCategory[] _audioCategories = new AudioCategory[(int)AudioType.Max]; private readonly float[] _categoriesVolume = new float[(int)AudioType.Max]; public readonly Dictionary AudioClipPool = new Dictionary(); public IResourceManager ResourceManager; - - /// - /// Unity是否禁用音频模块。 - /// private bool _bUnityAudioDisabled = false; #region Public Propreties @@ -374,7 +369,7 @@ namespace TEngine { AudioType audioType = (AudioType)index; AudioGroupConfig audioGroupConfig = m_AudioGroupConfigs.First(t => t.AudioType == audioType); - _audioCategories[index] = new AudioCategory(audioGroupConfig.AgentHelperCount, m_AudioMixer, audioType); + _audioCategories[index] = new AudioCategory(audioGroupConfig.AgentHelperCount, m_AudioMixer, audioGroupConfig); _categoriesVolume[index] = audioGroupConfig.Volume; } } @@ -473,35 +468,7 @@ namespace TEngine } } } - - - /// - /// 修改最大的音效播放上限, - /// - /// 最大播放数量 - public void ChangeAudioChannelMaxNum(int num) - { - if (_bUnityAudioDisabled) - { - return; - } - - if (num >= _audioChannelMaxNum) - { - _audioCategories[(int)AudioType.Sound].AddAudio(num - _audioChannelMaxNum); - _audioChannelMaxNum = num; - } - else - { - Stop(AudioType.Sound, true); - _audioChannelMaxNum = num; - _audioCategories[(int)AudioType.Sound].Enable = false; - _audioCategories[(int)AudioType.Sound] = new AudioCategory(_audioChannelMaxNum, m_AudioMixer, AudioType.Sound); - _categoriesVolume[(int)AudioType.Sound] = 1.0f; - } - } - - + /// /// 预先加载AudioClip,并放入对象池。 /// @@ -562,6 +529,9 @@ namespace TEngine AudioClipPool.Clear(); } + /// + /// 音频模块轮询。 + /// private void Update() { for (int i = 0; i < _audioCategories.Length; ++i)