feat: polish VR gameplay and sync tools

This commit is contained in:
jongjae0305
2026-05-28 19:01:20 +09:00
parent ee34d79a66
commit 03105a4f85
50 changed files with 4986 additions and 328 deletions
+23 -7
View File
@@ -19,16 +19,25 @@ public class SongController : MonoBehaviour
private const float VerticalCenter = 1f;
private AudioManager _audio;
private ScoreManager _scoreManager;
private float _clipLength;
private static string CacheRoot =>
Path.Combine(Application.temporaryCachePath, "beatsaber");
Path.Combine(Application.persistentDataPath, "beatsaber");
private void Start()
{
_audio = FindFirstObjectByType<AudioManager>();
_scoreManager = FindFirstObjectByType<ScoreManager>();
StartCoroutine(LoadAndPlay());
}
private void Update()
{
if (_audio != null && _scoreManager != null && _clipLength > 0.0f)
_scoreManager.SetSongProgress(_audio.CurrentTime, _clipLength);
}
private IEnumerator LoadAndPlay()
{
SongInfo song = GameSession.SelectedSong;
@@ -53,6 +62,7 @@ public class SongController : MonoBehaviour
}
clip = DownloadHandlerAudioClip.GetContent(req);
}
_clipLength = clip.length;
// Load and parse map
DifficultyInfo diffInfo = song.difficulties.Get(diff);
@@ -74,13 +84,14 @@ public class SongController : MonoBehaviour
yield break;
}
map.target.Sort(CompareNotes);
_scoreManager?.SetTotalNotes(map.target.Count);
yield return StartCoroutine(Countdown());
_audio.PlayClip(clip);
StartCoroutine(SpawnRoutine(map.target));
yield return StartCoroutine(WaitForCompletion(clip.length));
yield return StartCoroutine(WaitForCompletion(clip.length, map.target));
}
private IEnumerator Countdown()
@@ -106,7 +117,8 @@ public class SongController : MonoBehaviour
foreach (NoteData note in notes)
{
float spawnAt = Mathf.Max(0f, note.time - travelTime);
float adjustedNoteTime = note.time + GlobalSyncSettings.AudioOffsetSeconds;
float spawnAt = Mathf.Max(0f, adjustedNoteTime - travelTime);
yield return new WaitUntil(() => _audio.CurrentTime >= spawnAt);
SpawnNote(note);
}
@@ -118,7 +130,7 @@ public class SongController : MonoBehaviour
float y = MapLayerY(note.lineLayer);
// 스폰 시점의 실제 남은 시간으로 역산 → 동시 노트가 프레임 차이 나도 같은 타이밍에 도착
float remaining = note.time - _audio.CurrentTime;
float remaining = note.time + GlobalSyncSettings.AudioOffsetSeconds - _audio.CurrentTime;
float travelTime = Mathf.Max(0.05f, remaining);
var info = new SpawnEventInfo
@@ -126,7 +138,7 @@ public class SongController : MonoBehaviour
position = new Vector3(x, y, 0f),
colorSide = note.colorType == 0 ? ColorSide.Left : ColorSide.Right,
hitDirection = MapCutDirection(note.cutDirection),
useSpark = true,
useSpark = false,
speed = 2f,
travelTimeOverride = travelTime,
};
@@ -177,9 +189,13 @@ public class SongController : MonoBehaviour
private static Direction MapCutDirection(int cut)
=> (cut >= 0 && cut < CutDirMap.Length) ? CutDirMap[cut] : Direction.Center;
private IEnumerator WaitForCompletion(float clipLength)
private IEnumerator WaitForCompletion(float clipLength, List<NoteData> notes)
{
yield return new WaitUntil(() => _audio.CurrentTime >= clipLength - 0.5f);
float lastNoteTime = notes.Count > 0 ? notes[notes.Count - 1].time : 0.0f;
float resultTime = Mathf.Min(clipLength, lastNoteTime + GlobalSyncSettings.AudioOffsetSeconds + 0.35f);
yield return new WaitUntil(() => _audio.CurrentTime >= resultTime);
yield return new WaitForSeconds(0.35f);
_scoreManager?.CompleteSong();
onLevelComplete?.Invoke();
}
}