解决重复切换State的时候会导致重复播放对应Segment的问题。
修复FadeIn读取了FadeOut参数的问题。 增加Initial Delay功能。 重构AudioScheduler.ConfigureSource() -> SetupSource(), RegisterActiveSound(), StartPlayBack()。 移动长音频相关功能至LongAudio文件夹。
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace OCES.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// 与Transition无关的音量/生命周期管理逻辑
|
||||
/// </summary>
|
||||
public class ChannelFader
|
||||
{
|
||||
readonly MusicContainerPlayer m_player;
|
||||
readonly MonoBehaviour m_coroutineHost;
|
||||
|
||||
public ContainerPlayHandle CurrentHandle { get; private set; }
|
||||
public uint CurrentContainerId { get; private set; }
|
||||
public float CurrentVolume { get; private set; }
|
||||
|
||||
public ChannelFader(MusicContainerPlayer player, MonoBehaviour coroutineHost)
|
||||
{
|
||||
this.m_player = player;
|
||||
this.m_coroutineHost = coroutineHost;
|
||||
}
|
||||
|
||||
void StartNew(uint containerId, float startVolume)
|
||||
{
|
||||
CurrentContainerId = containerId;
|
||||
CurrentVolume = startVolume;
|
||||
CurrentHandle = this.m_player.Play(containerId);
|
||||
}
|
||||
|
||||
public void StopCurrent()
|
||||
{
|
||||
StopHandle(CurrentHandle);
|
||||
CurrentHandle = null;
|
||||
CurrentContainerId = 0;
|
||||
}
|
||||
|
||||
void StopHandle(ContainerPlayHandle handle)
|
||||
{
|
||||
if (handle == null) return;
|
||||
this.m_player.Stop(handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 淡出分支:fire-and-forget,由调用方 StartCoroutine
|
||||
/// </summary>
|
||||
internal IEnumerator FadeOutBranch(ContainerPlayHandle outgoingHandle, float outgoingVolume, ITransitionConfig transition)
|
||||
{
|
||||
if (outgoingHandle == null) yield break;
|
||||
|
||||
if (transition?.FadeOutOffset > 0f)
|
||||
{
|
||||
//Debug.Log($"Waiting for {transition.FadeOutOffset} to fade out.");
|
||||
yield return new WaitForSeconds(transition.FadeOutOffset);
|
||||
}
|
||||
|
||||
if (transition?.FadeOutTime > 0f )
|
||||
yield return this.m_coroutineHost.StartCoroutine(
|
||||
FadeOut(outgoingHandle, outgoingVolume, transition.FadeOutTime));
|
||||
else
|
||||
StopHandle(outgoingHandle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 淡入分支:等待 FadeInOffset 后启动新音乐并淡入。
|
||||
/// 主协程 yield return 此分支,以便 DoTransition 在新音乐就绪后才结束。
|
||||
/// </summary>
|
||||
internal IEnumerator FadeInBranch(uint newContainerId, ITransitionConfig transition, Action onContainerStarted = null)
|
||||
{
|
||||
if (transition?.FadeInOffset > 0f)
|
||||
{
|
||||
//Debug.Log($"Waiting {transition.FadeInOffset} to fade in.");
|
||||
yield return new WaitForSeconds(transition.FadeInOffset);
|
||||
}
|
||||
|
||||
if (newContainerId == 0)
|
||||
{
|
||||
CurrentHandle = null;
|
||||
CurrentContainerId = 0;
|
||||
yield break;
|
||||
}
|
||||
|
||||
float startVolume = transition?.FadeInTime > 0f ? 0f : 1f;
|
||||
StartNew(newContainerId, startVolume);
|
||||
onContainerStarted?.Invoke();
|
||||
|
||||
if (transition?.FadeInTime > 0f)
|
||||
{
|
||||
yield return this.m_coroutineHost.StartCoroutine(
|
||||
FadeIn(CurrentHandle, transition.FadeInTime));
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator FadeOut(ContainerPlayHandle handle, float fromVolume, float duration)
|
||||
{
|
||||
//Debug.Log($"Fading out in {duration} seconds.");
|
||||
if (handle == null || handle.Cancelled) yield break;
|
||||
|
||||
float elapsed = 0f;
|
||||
List<AudioSource> sources = new();
|
||||
handle.CollectActiveSources(sources);
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
if (handle.Cancelled) break;
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
float vol = Mathf.Lerp(fromVolume, 0f, t);
|
||||
foreach (AudioSource src in sources)
|
||||
if (src) src.volume = vol;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
StopHandle(handle);
|
||||
}
|
||||
|
||||
IEnumerator FadeIn(ContainerPlayHandle handle, float duration)
|
||||
{
|
||||
//Debug.Log($"Fading In {duration} seconds.");
|
||||
if (handle == null || handle.Cancelled) yield break;
|
||||
|
||||
float elapsed = 0f;
|
||||
List<AudioSource> sources = new();
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
if (handle.Cancelled) yield break;
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
|
||||
// 每帧重新收集(Blend 模式下新 source 可能中途加入)
|
||||
sources.Clear();
|
||||
handle.CollectActiveSources(sources);
|
||||
foreach (AudioSource src in sources)
|
||||
if (src) src.volume = Mathf.Lerp(0f, 1f, t);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// 确保最终音量准确
|
||||
sources.Clear();
|
||||
handle.CollectActiveSources(sources);
|
||||
foreach (AudioSource src in sources)
|
||||
if (src) src.volume = 1f;
|
||||
|
||||
CurrentVolume = 1f;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user