feat: 重构音频系统 - 重命名AudioScheduler为SfxSystem并添加Accented音效类型
- 将AudioScheduler重命名为SfxSystem,统一命名规范 - 新增MixingType.Accented音效类型,支持强调音效独立混音 - 重构音频混合器层级: Master下新增Regular中间层 - SfxSystem使用外部AudioSourcePool,与MusicSystem隔离 - 修复ambiencePoolRoot父节点错误(原错误挂载到musicPoolRoot) - Play方法支持onPlay回调 - 同步更新AudioObject.bytes二进制配置数据
This commit is contained in:
@@ -44,6 +44,7 @@ public partial class AudioObject : IBinarySerializable
|
||||
/// 0 = SFX
|
||||
/// 1 = Muisc
|
||||
/// 2 = Voice
|
||||
/// 3 = Accent
|
||||
/// </summary>
|
||||
public MixingType MixingType { get; set; }
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace OCES.Audio
|
||||
const string k_audioConfigPath = "AudioData";
|
||||
const string k_audioResourcePath = "Audios";
|
||||
|
||||
AudioScheduler m_scheduler;
|
||||
SfxSystem m_sfxSystem;
|
||||
MusicSystem m_musicSystem;
|
||||
|
||||
AudioObjectConfig m_audioObjects;
|
||||
@@ -26,16 +26,18 @@ namespace OCES.Audio
|
||||
// 公开接口
|
||||
// ─────────────────────────────────────────────
|
||||
|
||||
public void Play(uint audioId)
|
||||
public void Play(uint audioId, Action onPlay = null)
|
||||
{
|
||||
AudioObject obj = this.m_audioObjects.QueryById(audioId);
|
||||
if (obj != null)
|
||||
Play(obj);
|
||||
{
|
||||
Play(obj, onPlay);
|
||||
}
|
||||
}
|
||||
|
||||
public void Play(AudioObject audioObject)
|
||||
public void Play(AudioObject audioObject, Action onPlay = null)
|
||||
{
|
||||
this.m_scheduler.TryPlay(audioObject);
|
||||
this.m_sfxSystem.TryPlay(audioObject, onPlay);
|
||||
}
|
||||
|
||||
public void Play(int audioId)
|
||||
@@ -126,10 +128,15 @@ namespace OCES.Audio
|
||||
this.m_mixer = Resources.Load<AudioMixer>("Audios/Master");
|
||||
|
||||
// ── SFX 调度器 ──
|
||||
this.m_scheduler = gameObject.AddComponent<AudioScheduler>();
|
||||
// AudioSystem.cs 中
|
||||
GameObject sfxPoolRoot = new("SfxSourcePool");
|
||||
sfxPoolRoot.transform.SetParent(transform, false);
|
||||
AudioSourcePool sfxPool = new(sfxPoolRoot.transform); // 不传 mixer group,让 SfxSystem 自己设置
|
||||
this.m_sfxSystem = gameObject.AddComponent<SfxSystem>();
|
||||
this.m_audioObjects = AudioConfigLoader.Load<AudioObjectConfig>($"{k_audioConfigPath}/AudioObject");
|
||||
this.m_groups = AudioConfigLoader.Load<AudioGroupConfig>($"{k_audioConfigPath}/AudioGroup");
|
||||
this.m_scheduler.Initialize(this.m_groups, this.m_mixer);
|
||||
this.m_sfxSystem.Initialize(this.m_groups, this.m_mixer, sfxPool); // 传入 pool
|
||||
|
||||
|
||||
// ── 音乐与环境音系统 ──
|
||||
var segments = AudioConfigLoader.Load<MusicSegmentConfig>($"{k_audioConfigPath}/MusicSegment");
|
||||
@@ -145,12 +152,12 @@ namespace OCES.Audio
|
||||
// AudioSourcePool 由 MusicSystem 独占一个子节点,与 SFX pool 隔离
|
||||
GameObject musicPoolRoot = new("MusicSourcePool");
|
||||
musicPoolRoot.transform.SetParent(transform, false);
|
||||
AudioMixerGroup musicGroup = this.m_mixer.FindMatchingGroups("Master/Music")[0];
|
||||
AudioMixerGroup musicGroup = this.m_mixer.FindMatchingGroups("Master/Regular/Music")[0];
|
||||
AudioSourcePool musicPool = new(musicPoolRoot.transform, musicGroup);
|
||||
|
||||
GameObject ambiencePoolRoot = new("AmbienceSourcePool");
|
||||
musicPoolRoot.transform.SetParent(transform, false);
|
||||
AudioMixerGroup ambienceGroup = this.m_mixer.FindMatchingGroups("Master/SFX/Ambience")[0];
|
||||
ambiencePoolRoot.transform.SetParent(transform, false);
|
||||
AudioMixerGroup ambienceGroup = this.m_mixer.FindMatchingGroups("Master/Regular/SFX/Ambience")[0];
|
||||
AudioSourcePool ambiencePool = new(ambiencePoolRoot.transform, ambienceGroup);
|
||||
|
||||
this.m_musicSystem.Initialize(
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace OCES.Audio
|
||||
public enum MixingType
|
||||
{
|
||||
Sfx = 0,
|
||||
Music,
|
||||
Voice,
|
||||
Accented,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
+28
-10
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -7,9 +8,9 @@ using UnityEngine.Audio;
|
||||
namespace OCES.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// 音频调度器
|
||||
/// 音效系统
|
||||
/// </summary>
|
||||
public class AudioScheduler : MonoBehaviour
|
||||
public class SfxSystem : MonoBehaviour
|
||||
{
|
||||
public UnityEngine.UI.Text audioSystemTextBox;
|
||||
|
||||
@@ -27,8 +28,8 @@ namespace OCES.Audio
|
||||
|
||||
AudioGroupConfig m_groupConfig;
|
||||
AudioMixerGroup m_sfxGroup;
|
||||
AudioMixerGroup m_musicGroup;
|
||||
AudioMixerGroup m_voiceGroup;
|
||||
AudioMixerGroup m_accentSfxGroup;
|
||||
AudioSourcePool m_pool;
|
||||
AudioContainerSelector m_containerSelector;
|
||||
PitchStepResolver m_pitchStepResolver;
|
||||
@@ -50,7 +51,9 @@ namespace OCES.Audio
|
||||
void IncrementClipCount(uint id)
|
||||
{
|
||||
this.m_clipConcurrentCount[id] = GetClipCount(id) + 1;
|
||||
#if UNITY_EDITOR
|
||||
Debug.Log($"{id} count added to {GetClipCount(id)}");
|
||||
#endif
|
||||
}
|
||||
|
||||
void DecrementClipCount(uint id)
|
||||
@@ -64,18 +67,21 @@ namespace OCES.Audio
|
||||
// 初始化
|
||||
// ─────────────────────────────────────────────
|
||||
|
||||
public void Initialize(AudioGroupConfig groups, AudioMixer mixer)
|
||||
public void Initialize(AudioGroupConfig groups, AudioMixer mixer, AudioSourcePool pool)
|
||||
{
|
||||
this.m_groupConfig = groups;
|
||||
|
||||
this.m_pool = new AudioSourcePool(transform);
|
||||
this.m_pool = pool;
|
||||
this.m_containerSelector = new AudioContainerSelector();
|
||||
this.m_pitchStepResolver = new PitchStepResolver();
|
||||
|
||||
AudioMixerGroup[] sfx = Find("Master/SFX");
|
||||
AudioMixerGroup[] sfx = Find("Master/Regular/SFX");
|
||||
if (sfx.Length > 0) this.m_sfxGroup = sfx[0];
|
||||
AudioMixerGroup[] voice = Find("Master/Voice");
|
||||
AudioMixerGroup[] voice = Find("Master/Regular/Voice");
|
||||
if (voice.Length > 0) this.m_voiceGroup = voice[0];
|
||||
AudioMixerGroup[] accentSfx = Find("Master/SFX_Accent");
|
||||
if (accentSfx.Length > 0) this.m_accentSfxGroup = accentSfx[0];
|
||||
|
||||
return;
|
||||
|
||||
AudioMixerGroup[] Find(string path) => mixer.FindMatchingGroups(path);
|
||||
@@ -85,7 +91,7 @@ namespace OCES.Audio
|
||||
// 节流 & 调度入口
|
||||
// ─────────────────────────────────────────────
|
||||
|
||||
internal void TryPlay(AudioObject audioObject)
|
||||
internal void TryPlay(AudioObject audioObject, Action onPlay = null)
|
||||
{
|
||||
double now = Time.realtimeSinceStartupAsDouble * 1000.0;
|
||||
|
||||
@@ -169,6 +175,7 @@ namespace OCES.Audio
|
||||
float pitch = this.m_pitchStepResolver.ResolvePitch(audioObject, now); //算一下用不用变调
|
||||
PlayNewSound(audioObject, pitch);
|
||||
this.m_lastPlayTime[audioObject.Id] = now;
|
||||
onPlay?.Invoke();
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
@@ -263,6 +270,7 @@ namespace OCES.Audio
|
||||
yield return new WaitForSeconds(audioObject.InitialDelay);
|
||||
|
||||
if (!this.m_activeSounds.Contains(active)) yield break;
|
||||
active.Pitch = pitch;
|
||||
|
||||
ExecutePlay(active, isRegistered: true);
|
||||
}
|
||||
@@ -312,11 +320,21 @@ namespace OCES.Audio
|
||||
/// </summary>
|
||||
AudioMixerGroup GetMixerGroup(MixingType type) => type switch
|
||||
{
|
||||
MixingType.Music => this.m_musicGroup,
|
||||
MixingType.Voice => this.m_voiceGroup,
|
||||
_ => this.m_sfxGroup,
|
||||
MixingType.Accented => this.m_accentSfxGroup,
|
||||
_ => GetDefaultGroup(type),
|
||||
};
|
||||
|
||||
AudioMixerGroup GetDefaultGroup(MixingType type)
|
||||
{
|
||||
if (type != MixingType.Sfx)
|
||||
{
|
||||
Debug.LogWarning($"[SfxSystem] Unrecognized MixingType: {type}, defaulting to SFX.");
|
||||
}
|
||||
|
||||
return this.m_sfxGroup;
|
||||
}
|
||||
|
||||
bool SetupSource(AudioSource source, AudioObject audioObject, float pitch, int clipIndex = 0)
|
||||
{
|
||||
AudioClip clip = Resources.Load<AudioClip>($"Audios/{audioObject.Name[clipIndex]}"); // TODO 抽象同一资源加载接口
|
||||
Reference in New Issue
Block a user