备份,准备做双端
This commit is contained in:
@@ -8,11 +8,25 @@ public static class GameplayClock
|
||||
private static double pauseStartDspTime;
|
||||
private static double accumulatedPauseSeconds;
|
||||
private static float chartStartSongTime;
|
||||
private static double scheduledMusicStartDsp; // anchor: when music actually starts playing
|
||||
// Seconds the chart clock leads the music clip position by (== globalDelaySeconds + userAudioOffset).
|
||||
// Captured when music is scheduled; used to preserve the songTime = musicTime + offset relationship
|
||||
// when re-anchoring to actual music progress after a pause.
|
||||
private static double musicToChartOffsetSeconds;
|
||||
|
||||
// Per-frame cache of NowSongTime. AudioSettings.dspTime only advances on the audio
|
||||
// thread (~once per audio buffer), so it is effectively constant within a rendered
|
||||
// frame. Many notes/segments read NowSongTime every frame; caching by frame turns
|
||||
// hundreds of native dspTime reads per frame into one. Invalidated when the frame
|
||||
// changes or clock state mutates (Reset/StartChart/Pause/Resume).
|
||||
private static int nowSongTimeFrame = -1;
|
||||
private static float nowSongTimeCached;
|
||||
|
||||
public static bool IsInitialized => initialized;
|
||||
public static bool IsPaused => paused;
|
||||
public static float ChartStartSongTime => chartStartSongTime;
|
||||
public static double ChartStartDspTime => chartStartDspTime;
|
||||
public static double ScheduledMusicStartDsp => scheduledMusicStartDsp;
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
@@ -22,6 +36,9 @@ public static class GameplayClock
|
||||
pauseStartDspTime = 0d;
|
||||
accumulatedPauseSeconds = 0d;
|
||||
chartStartSongTime = 0f;
|
||||
scheduledMusicStartDsp = 0d;
|
||||
musicToChartOffsetSeconds = 0d;
|
||||
nowSongTimeFrame = -1;
|
||||
}
|
||||
|
||||
public static void StartChart(float initialSongTimeSeconds = 0f)
|
||||
@@ -32,6 +49,27 @@ public static class GameplayClock
|
||||
pauseStartDspTime = 0d;
|
||||
accumulatedPauseSeconds = 0d;
|
||||
chartStartSongTime = Mathf.Max(0f, initialSongTimeSeconds);
|
||||
scheduledMusicStartDsp = 0d; // will be set by SetMusicAnchor when music plays
|
||||
musicToChartOffsetSeconds = 0d;
|
||||
nowSongTimeFrame = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record the scheduled music start time for reference.
|
||||
/// Call this immediately after PlayScheduled or Play.
|
||||
/// NOTE: Does NOT re-anchor chartStartDspTime — the chart clock stays pinned to gameplay start (StartChart),
|
||||
/// and music simply plays offset into the future. Re-anchoring would shift all note timing by globalDelaySeconds.
|
||||
/// </summary>
|
||||
public static void SetMusicAnchor(double musicStartDspTime)
|
||||
{
|
||||
if (!initialized) return;
|
||||
scheduledMusicStartDsp = musicStartDspTime;
|
||||
// Do NOT re-anchor chartStartDspTime here — note spawn/hit times were computed from the original anchor.
|
||||
// Re-anchoring would create a systematic offset equal to globalDelaySeconds.
|
||||
// Capture the constant lead of chart song-time over music-clip time: songTime(D) - musicTime(D),
|
||||
// where musicTime(D) = D - musicStartDspTime. This lets ReanchorToMusicTime preserve the relationship.
|
||||
musicToChartOffsetSeconds = chartStartSongTime - chartStartDspTime - accumulatedPauseSeconds + musicStartDspTime;
|
||||
nowSongTimeFrame = -1;
|
||||
}
|
||||
|
||||
public static void Pause()
|
||||
@@ -43,6 +81,7 @@ public static class GameplayClock
|
||||
|
||||
paused = true;
|
||||
pauseStartDspTime = AudioSettings.dspTime;
|
||||
nowSongTimeFrame = -1;
|
||||
}
|
||||
|
||||
public static void Resume()
|
||||
@@ -55,6 +94,24 @@ public static class GameplayClock
|
||||
accumulatedPauseSeconds += AudioSettings.dspTime - pauseStartDspTime;
|
||||
pauseStartDspTime = 0d;
|
||||
paused = false;
|
||||
nowSongTimeFrame = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Re-anchor the clock to the actual music progress on resume.
|
||||
/// Call this after Resume() if musicSource.time is available, to correct any drift.
|
||||
/// </summary>
|
||||
public static void ReanchorToMusicTime(float actualMusicTime)
|
||||
{
|
||||
if (!initialized || paused) return;
|
||||
// Reverse-calculate chartStartDspTime so that song-time now equals the music clip position
|
||||
// PLUS the constant lead (globalDelaySeconds/audio offset) captured at SetMusicAnchor.
|
||||
// Without adding musicToChartOffsetSeconds, resuming would force songTime == musicTime and
|
||||
// reintroduce the exact backward offset the SetMusicAnchor fix removed.
|
||||
double now = AudioSettings.dspTime;
|
||||
double targetSongTime = actualMusicTime + musicToChartOffsetSeconds;
|
||||
chartStartDspTime = now - accumulatedPauseSeconds - (targetSongTime - chartStartSongTime);
|
||||
nowSongTimeFrame = -1;
|
||||
}
|
||||
|
||||
public static float NowSongTime
|
||||
@@ -66,9 +123,21 @@ public static class GameplayClock
|
||||
return 0f;
|
||||
}
|
||||
|
||||
// While paused the value is frozen (pauseStartDspTime), so it's trivially stable;
|
||||
// while playing, reuse the value already computed this frame.
|
||||
int frame = Time.frameCount;
|
||||
if (frame == nowSongTimeFrame)
|
||||
{
|
||||
return nowSongTimeCached;
|
||||
}
|
||||
|
||||
double currentDsp = paused ? pauseStartDspTime : AudioSettings.dspTime;
|
||||
double elapsed = currentDsp - chartStartDspTime - accumulatedPauseSeconds;
|
||||
return chartStartSongTime + Mathf.Max(0f, (float)elapsed);
|
||||
float result = chartStartSongTime + Mathf.Max(0f, (float)elapsed);
|
||||
|
||||
nowSongTimeFrame = frame;
|
||||
nowSongTimeCached = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user