com.alicizax.unity.framework/Runtime/Audio/AudioCategory.cs
2025-09-05 19:46:30 +08:00

240 lines
7.0 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
namespace AlicizaX.Audio.Runtime
{
/// <summary>
/// 音频轨道(类别)。
/// </summary>
[Serializable]
public class AudioCategory
{
[SerializeField] private AudioMixer audioMixer = null;
public List<AudioAgent> AudioAgents;
private readonly AudioMixerGroup _audioMixerGroup;
private AudioGroupConfig _audioGroupConfig;
private int _maxChannel;
private bool _bEnable = true;
/// <summary>
/// 音频混响器。
/// </summary>
public AudioMixer AudioMixer => audioMixer;
/// <summary>
/// 音频混响器组。
/// </summary>
public AudioMixerGroup AudioMixerGroup => _audioMixerGroup;
/// <summary>
/// 音频组配置。
/// </summary>
public AudioGroupConfig AudioGroupConfig => _audioGroupConfig;
/// <summary>
/// 实例化根节点。
/// </summary>
public Transform InstanceRoot { private set; get; }
/// <summary>
/// 音频轨道是否启用。
/// </summary>
public bool Enable
{
get => _bEnable;
set
{
if (_bEnable != value)
{
_bEnable = value;
if (!_bEnable)
{
foreach (var audioAgent in AudioAgents)
{
if (audioAgent != null)
{
audioAgent.Stop();
}
}
}
}
}
}
/// <summary>
/// 音频轨道构造函数。
/// </summary>
/// <param name="maxChannel">最大Channel。</param>
/// <param name="audioMixer">音频混响器。</param>
/// <param name="audioGroupConfig">音频轨道组配置。</param>
public AudioCategory(int maxChannel, AudioMixer audioMixer, AudioGroupConfig audioGroupConfig)
{
var audioModule = ModuleSystem.GetModule<IAudioModule>();
this.audioMixer = audioMixer;
_maxChannel = maxChannel;
_audioGroupConfig = audioGroupConfig;
AudioMixerGroup[] audioMixerGroups = audioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}", audioGroupConfig.AudioType.ToString()));
if (audioMixerGroups.Length > 0)
{
_audioMixerGroup = audioMixerGroups[0];
}
else
{
_audioMixerGroup = audioMixer.FindMatchingGroups("Master")[0];
}
AudioAgents = new List<AudioAgent>(32);
InstanceRoot = new GameObject(Utility.Text.Format("Audio Category - {0}", _audioMixerGroup.name)).transform;
InstanceRoot.SetParent(audioModule.InstanceRoot);
for (int index = 0; index < _maxChannel; index++)
{
AudioAgent audioAgent = new AudioAgent();
audioAgent.Init(this, index);
AudioAgents.Add(audioAgent);
}
}
/// <summary>
/// 增加音频。
/// </summary>
/// <param name="num"></param>
public void AddAudio(int num)
{
_maxChannel += num;
for (int i = 0; i < num; i++)
{
AudioAgents.Add(null);
}
}
public AudioAgent Play(AudioClip clip)
{
if (!_bEnable)
{
return null;
}
int freeChannel = -1;
float duration = -1;
for (int i = 0; i < AudioAgents.Count; i++)
{
if (AudioAgents[i].IsFree)
{
freeChannel = i;
break;
}
else if (AudioAgents[i].Duration > duration)
{
duration = AudioAgents[i].Duration;
freeChannel = i;
}
}
if (freeChannel >= 0)
{
if (AudioAgents[freeChannel] == null)
{
AudioAgents[freeChannel] = AudioAgent.Create(clip, this);
}
else
{
AudioAgents[freeChannel].SetAudioClip(clip);
}
return AudioAgents[freeChannel];
}
else
{
Log.Error($"Here is no channel to play audio clip");
return null;
}
}
/// <summary>
/// 播放音频。
/// </summary>
/// <param name="path"></param>
/// <param name="bAsync"></param>
/// <param name="bInPool"></param>
/// <returns></returns>
public AudioAgent Play(string path, bool bAsync, bool bInPool = false)
{
if (!_bEnable)
{
return null;
}
int freeChannel = -1;
float duration = -1;
for (int i = 0; i < AudioAgents.Count; i++)
{
if (AudioAgents[i].AudioData?.AssetHandle == null || AudioAgents[i].IsFree)
{
freeChannel = i;
break;
}
else if (AudioAgents[i].Duration > duration)
{
duration = AudioAgents[i].Duration;
freeChannel = i;
}
}
if (freeChannel >= 0)
{
if (AudioAgents[freeChannel] == null)
{
AudioAgents[freeChannel] = AudioAgent.Create(path, bAsync, this, bInPool);
}
else
{
AudioAgents[freeChannel].Load(path, bAsync, bInPool);
}
return AudioAgents[freeChannel];
}
else
{
Log.Error($"Here is no channel to play audio {path}");
return null;
}
}
/// <summary>
/// 暂停音频。
/// </summary>
/// <param name="fadeout">是否渐出</param>
public void Stop(bool fadeout)
{
for (int i = 0; i < AudioAgents.Count; ++i)
{
if (AudioAgents[i] != null)
{
AudioAgents[i].Stop(fadeout);
}
}
}
/// <summary>
/// 音频轨道轮询。
/// </summary>
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
public void Update(float elapseSeconds)
{
for (int i = 0; i < AudioAgents.Count; ++i)
{
if (AudioAgents[i] != null)
{
AudioAgents[i].Update(elapseSeconds);
}
}
}
}
}