first commit

This commit is contained in:
2026-03-20 17:55:53 +08:00
commit c5778c498b
328 changed files with 11867 additions and 0 deletions
@@ -0,0 +1,151 @@
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, float fadeOutOffset, float fadeOutTime)
{
if (outgoingHandle == null) yield break;
if (fadeOutOffset > 0f)
{
Debug.Log($"Waiting for {fadeOutOffset} to fade out.");
yield return new WaitForSeconds(fadeOutOffset);
}
if (fadeOutTime > 0f )
yield return this.m_coroutineHost.StartCoroutine(
FadeOut(outgoingHandle, outgoingVolume, fadeOutTime));
else
StopHandle(outgoingHandle);
}
/// <summary>
/// 淡入分支:等待 FadeInOffset 后启动新音乐并淡入。
/// 主协程 yield return 此分支,以便 DoTransition 在新音乐就绪后才结束。
/// </summary>
internal IEnumerator FadeInBranch(uint newContainerId, float fadeInOffset, float fadeInTime, Action onContainerStarted = null)
{
if (fadeInOffset > 0f)
{
Debug.Log($"Waiting {fadeInOffset} to fade in.");
yield return new WaitForSeconds(fadeInOffset);
}
if (newContainerId == 0)
{
CurrentHandle = null;
CurrentContainerId = 0;
yield break;
}
float startVolume = fadeInTime > 0f ? 0f : 1f;
StartNew(newContainerId, startVolume);
if (fadeInTime > 0f )
{
yield return this.m_coroutineHost.StartCoroutine(
FadeIn(CurrentHandle, 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;
}
}
}