비트 찍기 완료 및 클로드를 통한 api작업

This commit is contained in:
jongjae0305
2026-05-20 16:44:28 +09:00
commit 2cd1be88d4
1596 changed files with 444234 additions and 0 deletions
+137
View File
@@ -0,0 +1,137 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
public class Spawner : MonoBehaviour
{
[Header("오디오 및 파일 설정")]
public AudioSource audioSource;
[Header("노트 프리팹 & 위치")]
public GameObject[] cubePrefabs;
public Transform[] spawnPoints;
[Header("타이밍 설정")]
public float noteSpeed = 2.0f;
public float distanceToHit = 10.0f;
[Header("씬 설정")]
public string songSelectSceneName = "SongSelect";
private List<NoteData> mapNotes = new List<NoteData>();
private int nextNoteIndex = 0;
private float travelTime;
private bool isReady = false;
// ── Unity ────────────────────────────────────────────────
void Start()
{
travelTime = distanceToHit / noteSpeed;
if (GameSession.SelectedSong == null)
{
Debug.LogWarning("[Spawner] 선택된 곡 없음 → 곡 선택 화면으로 이동");
SceneManager.LoadScene(songSelectSceneName);
return;
}
StartCoroutine(InitGame());
}
void Update()
{
if (!isReady || audioSource == null || !audioSource.isPlaying) return;
float currentTime = audioSource.time;
while (nextNoteIndex < mapNotes.Count &&
currentTime + travelTime >= mapNotes[nextNoteIndex].time)
{
SpawnNote(mapNotes[nextNoteIndex]);
nextNoteIndex++;
}
}
// ── 초기화 ───────────────────────────────────────────────
private IEnumerator InitGame()
{
SongInfo song = GameSession.SelectedSong;
string difficulty = GameSession.SelectedDifficulty;
// 맵 JSON 로드
string mapPath = GetMapPath(song, difficulty);
if (!File.Exists(mapPath))
{
Debug.LogError($"[Spawner] 맵 파일 없음: {mapPath}");
yield break;
}
LoadMapJson(mapPath);
// 오디오 로드 (로컬 파일 → AudioClip)
string audioPath = GetAudioPath(song.id);
yield return LoadAudioClip(audioPath);
// LRU 갱신
SongLibrary.Instance?.TouchSong(song.id);
isReady = true;
audioSource.Play();
Debug.Log($"[Spawner] 시작: {song.title} ({difficulty})");
}
private void LoadMapJson(string path)
{
string json = File.ReadAllText(path);
MapData data = JsonUtility.FromJson<MapData>(json);
mapNotes = data?.target ?? new List<NoteData>();
mapNotes.Sort((a, b) => a.time.CompareTo(b.time));
Debug.Log($"[Spawner] 노트 로드: {mapNotes.Count}개");
}
private IEnumerator LoadAudioClip(string path)
{
string uri = "file://" + path;
using var req = UnityWebRequestMultimedia.GetAudioClip(uri, AudioType.MPEG);
yield return req.SendWebRequest();
if (req.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"[Spawner] 오디오 로드 실패: {req.error}");
yield break;
}
audioSource.clip = DownloadHandlerAudioClip.GetContent(req);
}
// ── 노트 스폰 ────────────────────────────────────────────
private void SpawnNote(NoteData data)
{
if (data.colorType >= cubePrefabs.Length || data.position >= spawnPoints.Length) return;
GameObject obj = Instantiate(
cubePrefabs[data.colorType],
spawnPoints[data.position].position,
spawnPoints[data.position].rotation);
obj.transform.Rotate(transform.forward, 90 * Random.Range(0, 4));
}
// ── 경로 헬퍼 ────────────────────────────────────────────
private static string CacheRoot =>
Path.Combine(Application.temporaryCachePath, "beatsaber");
private static string GetAudioPath(string songId) =>
Path.Combine(CacheRoot, songId, $"{songId}.mp3");
private static string GetMapPath(SongInfo song, string difficulty)
{
DifficultyInfo info = song.difficulties.Get(difficulty);
if (info == null) return string.Empty;
return Path.Combine(CacheRoot, song.id, Path.GetFileName(info.mapFile));
}
}