WIP: StartOffset

This commit is contained in:
2026-05-07 12:09:16 +08:00
parent 0f30f98846
commit af4cd4da3f
51 changed files with 843 additions and 64 deletions
@@ -112,8 +112,9 @@ namespace OCES.Audio
while (true)
{
bool isLoop = loopsCompleted > 0;
yield return this.m_coroutineHost.StartCoroutine(
PlayContainerOnce(container, handle.TargetVolume, handle, effectiveBpm));
PlayContainerOnce(container, handle.TargetVolume, handle, effectiveBpm, isLoop));
if (handle.Cancelled) yield break;
@@ -139,7 +140,12 @@ namespace OCES.Audio
/// <summary>
/// 播放一个 Container 一轮(不含循环逻辑)
/// </summary>
IEnumerator PlayContainerOnce(MusicContainer container, float volumeScale, ContainerPlayHandle handle, float inheritedBpm)
IEnumerator PlayContainerOnce(
MusicContainer container,
float volumeScale,
ContainerPlayHandle handle,
float inheritedBpm,
bool isLoop = false)
{
if (container.Segments == null || container.Segments.Count == 0)
yield break;
@@ -151,11 +157,11 @@ namespace OCES.Audio
break;
case ContainerType.Sequence:
yield return PlaySequence(container, volumeScale, handle, inheritedBpm);
yield return PlaySequence(container, volumeScale, handle, inheritedBpm, isLoop);
break;
case ContainerType.Random:
yield return PlayRandom(container, volumeScale, handle, inheritedBpm);
yield return PlayRandom(container, volumeScale, handle, inheritedBpm, isLoop);
break;
}
}
@@ -211,7 +217,12 @@ namespace OCES.Audio
// Sequence
// ─────────────────────────────────────────────
IEnumerator PlaySequence(MusicContainer container, float volumeScale, ContainerPlayHandle handle, float inheritedBpm)
IEnumerator PlaySequence(
MusicContainer container,
float volumeScale,
ContainerPlayHandle handle,
float inheritedBpm,
bool isLoop = false)
{
bool isStep = container.ContainerPlayMode;
@@ -219,7 +230,7 @@ namespace OCES.Audio
{
// Step: 每次只播一个,游标全局推进
int index = GetNextSequenceIndex(container);
yield return PlayChildAndWait(container.Segments[index], volumeScale, handle, inheritedBpm);
yield return PlayChildAndWait(container.Segments[index], volumeScale, handle, inheritedBpm, isLoop);
}
else
@@ -233,7 +244,7 @@ namespace OCES.Audio
if (i > 0 && container.StrategyParam > 0)
yield return new WaitForSeconds(container.StrategyParam);
yield return PlayChildAndWait(container.Segments[i], volumeScale, handle, inheritedBpm);
yield return PlayChildAndWait(container.Segments[i], volumeScale, handle, inheritedBpm, isLoop);
}
}
}
@@ -242,7 +253,12 @@ namespace OCES.Audio
// Random
// ─────────────────────────────────────────────
IEnumerator PlayRandom(MusicContainer container, float volumeScale, ContainerPlayHandle handle, float inheritedBpm)
IEnumerator PlayRandom(
MusicContainer container,
float volumeScale,
ContainerPlayHandle handle,
float inheritedBpm,
bool isLoop = false)
{
bool isStep = container.ContainerPlayMode; // 同上,音乐系统默认 Continuous
@@ -250,7 +266,7 @@ namespace OCES.Audio
{
// Step Random: 随机选一个播放,算一次 loopCount
uint chosen = PickRandomChild(container);
yield return PlayChildAndWait(chosen, volumeScale, handle, inheritedBpm);
yield return PlayChildAndWait(chosen, volumeScale, handle, inheritedBpm, isLoop);
}
else
{
@@ -268,7 +284,7 @@ namespace OCES.Audio
if (container.StrategyParam > 0 && remaining.Count < container.Segments.Count - 1)
yield return new WaitForSeconds(container.StrategyParam);
yield return PlayChildAndWait(chosen, volumeScale, handle, inheritedBpm);
yield return PlayChildAndWait(chosen, volumeScale, handle, inheritedBpm, isLoop);
}
}
}
@@ -280,10 +296,14 @@ namespace OCES.Audio
/// <summary>
/// 播放一个子元素(segment 或 container),等待其完成后返回。
/// </summary>
IEnumerator PlayChildAndWait(uint id, float volumeScale, ContainerPlayHandle parentHandle, float inheritedBpm)
IEnumerator PlayChildAndWait(uint id,
float volumeScale,
ContainerPlayHandle parentHandle,
float inheritedBpm,
bool isLoop = false)
{
bool done = false;
ContainerPlayHandle child = PlayChild(id, volumeScale, () => done = true, inheritedBpm);
ContainerPlayHandle child = PlayChild(id, volumeScale, () => done = true, inheritedBpm, isLoop);
if (child != null)
parentHandle.ChildHandles.Add(child);
@@ -299,17 +319,17 @@ namespace OCES.Audio
/// <summary>
/// 启动一个子元素的播放,不等待,返回句柄。
/// </summary>
ContainerPlayHandle PlayChild(uint id, float volumeScale, Action onDone, float inheritedBpm)
ContainerPlayHandle PlayChild(uint id, float volumeScale, Action onDone, float inheritedBpm, bool isLoop = false)
{
// ID < 1000000 是 MusicSegment,否则是嵌套 Container
return id < 1000000u ? PlaySegment(id, volumeScale, onDone) : Play(id, onDone, inheritedBpm: inheritedBpm);
return id < 1000000u ? PlaySegment(id, volumeScale, onDone, isLoop) : Play(id, onDone, inheritedBpm);
}
// ─────────────────────────────────────────────
// Segment 播放
// ─────────────────────────────────────────────
ContainerPlayHandle PlaySegment(uint segmentId, float volumeScale, Action onFinished)
ContainerPlayHandle PlaySegment(uint segmentId, float volumeScale, Action onFinished, bool isLoop = false)
{
MusicSegment segment = this.m_segmentConfig.QueryById(segmentId);
if (segment == null)
@@ -333,7 +353,12 @@ namespace OCES.Audio
source.volume = volumeScale;
source.Play();
var handle = new ContainerPlayHandle();
if (isLoop && segment.StartOffset > 0)
{
source.time = (float)segment.StartOffset;
}
ContainerPlayHandle handle = new();
handle.ActiveSources.Add(source);
handle.Coroutine = this.m_coroutineHost.StartCoroutine(
WaitSegmentFinish(source, handle, onFinished, segment.EndOffset));
@@ -342,7 +367,7 @@ namespace OCES.Audio
IEnumerator WaitSegmentFinish(AudioSource source, ContainerPlayHandle handle, Action onFinished, double endOffset)
{
double effectiveTime = endOffset > 0f ? source.clip.length - endOffset : 0f;
double effectiveTime = endOffset > 0f ? source.clip.length - endOffset : source.clip.length;
// 1. 等待"逻辑结束"EndOffset 或自然结束)
yield return new WaitWhile(() =>