using System.Collections; using UnityEngine; namespace OCES.Audio { /// /// 环境音通道播放器。 /// 与 MusicChannelPlayer 逻辑相同,但使用 AmbienceTransition 表,不涉及节拍对齐。 /// public class AmbienceChannelPlayer { readonly AmbienceTransitionConfig m_transitionConfig; readonly MonoBehaviour m_coroutineHost; readonly ChannelFader m_fader; ContainerPlayHandle m_currentHandle; Coroutine m_transitionCoroutine; uint m_currentContainerId; public AmbienceChannelPlayer( AmbienceTransitionConfig transitionConfig, MusicContainerPlayer player, MonoBehaviour coroutineHost) { this.m_transitionConfig = transitionConfig; this.m_coroutineHost = coroutineHost; this.m_fader = new ChannelFader(player, coroutineHost); } // ───────────────────────────────────────────── // 公开接口 // ───────────────────────────────────────────── public void SwitchTo(uint newContainerId, uint fromPathId, uint toPathId) { if (newContainerId == this.m_currentContainerId && this.m_currentHandle != null) return; AmbienceTransition transition = ResolveTransition(fromPathId, toPathId); if (this.m_transitionCoroutine != null) this.m_coroutineHost.StopCoroutine(this.m_transitionCoroutine); this.m_transitionCoroutine = this.m_coroutineHost.StartCoroutine( DoTransition(newContainerId, transition)); } public void Stop() { if (this.m_transitionCoroutine != null) this.m_coroutineHost.StopCoroutine(this.m_transitionCoroutine); this.m_fader.StopCurrent(); } // ───────────────────────────────────────────── // Transition 流程(无节拍对齐) // ───────────────────────────────────────────── IEnumerator DoTransition(uint newContainerId, AmbienceTransition transition) { ContainerPlayHandle outgoing = this.m_fader.CurrentHandle; float outgoingVolume = this.m_fader.CurrentVolume; float fadeOutOffSet = transition?.FadeOutOffset ?? 0f; float fadeOutTime = transition?.FadeOutTime ?? 0f; float fadeInOffSet = transition?.FadeInOffset ?? 0f; float fadeInTime = transition?.FadeInTime ?? 0f; // ContainerPlayHandle outgoingHandle = this.m_currentHandle; // float outgoingVolume = this.m_currentVolume; this.m_coroutineHost.StartCoroutine( this.m_fader.FadeOutBranch(outgoing, outgoingVolume,fadeOutOffSet, fadeOutTime)); yield return this.m_coroutineHost.StartCoroutine( this.m_fader.FadeInBranch(newContainerId, fadeInOffSet, fadeInTime)); } // ───────────────────────────────────────────── // 工具 // ───────────────────────────────────────────── AmbienceTransition ResolveTransition(uint fromPathId, uint toPathId) { // 优先精确匹配 uint exactId = fromPathId * 1000 + toPathId; AmbienceTransition exact = this.m_transitionConfig.QueryById(exactId); if (exact != null) return exact; // From 为任意 uint fromWildcard = 999u * 1000 + toPathId; AmbienceTransition fromWild = this.m_transitionConfig.QueryById(fromWildcard); if (fromWild != null) return fromWild; // To 为任意 uint toWildcard = fromPathId * 1000 + 999u; AmbienceTransition toWild = this.m_transitionConfig.QueryById(toWildcard); if (toWild != null) return toWild; // 全通配 const uint allWild = 999u * 1000 + 999u; return this.m_transitionConfig.QueryById(allWild); } } }