using UnityEngine; using System.Collections; using Unity.VisualScripting; using System.Runtime.InteropServices.WindowsRuntime; using TMPro; public class NoteSpawner : MonoBehaviour { public NotePool notePool; // 引用 NotePool public Transform[] spawnPoints; // 对应轨道的生成点 public GameObject[] notePrefabs; // 短音符预制体 public TextMeshProUGUI globalGameTime; // 长音符预制体数组(分别为 start, middle, end) public GameObject[] holdNoteStartPrefabs; public GameObject[] holdNoteMiddlePrefabs; public GameObject[] holdNoteEndPrefabs; public float spawnOffset = 0f; // 生成音符时的时间偏移量 public float bpm; private Beatmap beatmap; private float startTime; // 存储歌曲开始时间 private bool isSpawning = false; private static int holdNoteIdCounter = 0; // 全局唯一长音符 ID 计数器 public void LoadBeatmap(Beatmap loadedBeatmap) { if (isSpawning) return; isSpawning = true; beatmap = loadedBeatmap; if (beatmap == null) { Debug.LogError("加载的谱面为空!"); return; } bpm = beatmap.bpm; startTime = Time.time; Debug.Log($"歌曲开始时间: {startTime}"); StartCoroutine(SpawnNotes()); } private IEnumerator SpawnNotes() { if (beatmap == null || beatmap.notes == null) { Debug.LogError("谱面数据为空!"); isSpawning = false; yield break; } foreach (NoteData note in beatmap.notes) { float travelTime = (60f / bpm) * 4; float spawnTime = note.time - travelTime; float delay = spawnTime - (Time.time - startTime) + spawnOffset; Debug.Log($"delay: {delay}"); if (delay > 0) yield return new WaitForSeconds(delay); if (note.type == "hold") { SpawnHoldNote(note); } else { SpawnNote(note); } } isSpawning = false; } // 生成短音符 public void SpawnNote(NoteData noteData) { if (noteData.trackIndex < 0 || noteData.trackIndex >= spawnPoints.Length) { Debug.LogError("轨道索引超出范围!"); return; } KeyCode key = KeyBindingManager.GetKeyForColor(noteData.color); if (key == KeyCode.None) { Debug.LogError($"未找到颜色 {noteData.color} 对应的按键!请检查 KeyBindingManager 是否正确初始化。"); return; } Debug.Log($"生成短音符:颜色={noteData.color}, 按键={key}, 轨道={noteData.trackIndex}"); GameObject note = notePool.GetNote(noteData.color); if (note == null) { Debug.LogError("对象池返回了一个空音符!"); return; } note.transform.position = spawnPoints[noteData.trackIndex].position; note.transform.rotation = Quaternion.identity; Note noteScript = note.GetComponent(); if (noteScript != null) { float noteSpawnTime = Time.time; noteScript.Setup(key, noteData.trackIndex, CalculateSpeed(), noteData.time, noteData.color); Debug.Log($"到达时间:{noteSpawnTime + (60f / bpm) * 4}"); } else { Debug.LogError("音符预制体缺少 Note 组件!"); } } public void SpawnHoldNote(NoteData noteData) { if (noteData.trackIndex < 0 || noteData.trackIndex >= spawnPoints.Length) { Debug.LogError("轨道索引超出范围!"); return; } KeyCode key = KeyBindingManager.GetKeyForColor(noteData.color); if (key == KeyCode.None) { Debug.LogError($"未找到颜色 {noteData.color} 对应的按键!"); return; } if (string.IsNullOrEmpty(noteData.color)) { Debug.LogError("[NoteSpawner] noteData.color 为空,无法生成音符!"); return; } Debug.Log($"生成时间:{Time.time}"); Debug.Log($"生成长音符:颜色={noteData.color}, 按键={key}, 轨道={noteData.trackIndex}"); float segmentInterval = (60f / bpm) / 4f; int segmentCount = Mathf.CeilToInt(noteData.length / segmentInterval); Transform spawnPoint = spawnPoints[noteData.trackIndex]; float scheduledEndTime = noteData.time + noteData.length; // 生成唯一 id int holdNoteId = Random.Range(100000, 999999); // 生成 Start 段 GameObject startObj = notePool.GetStartNote(noteData.color); if (startObj == null) { Debug.LogError("对象池返回空 hold note start!"); return; } startObj.transform.position = spawnPoint.position; startObj.transform.rotation = Quaternion.identity; HoldNote holdNote = startObj.GetComponent(); if (holdNote != null) { holdNote.Setup(holdNoteId, noteData.trackIndex, CalculateSpeed(), noteData.time, 0f, false, scheduledEndTime, noteData.color, key, "start"); } else { Debug.LogError("长音符 start 部分缺少 HoldNote 组件!"); return; } // 生成 Middle 和 End 段 for (int i = 1; i < segmentCount; i++) { float segmentDelay = i * segmentInterval; bool isEndSegment = (i == segmentCount - 1); string partType = isEndSegment ? "end" : "middle"; GameObject segObj = notePool.GetHoldNoteSegment(noteData.color); if (segObj == null) { Debug.LogError("对象池返回空 hold note 片段!"); continue; } segObj.transform.position = spawnPoint.position; segObj.transform.rotation = Quaternion.identity; HoldNote holdSeg = segObj.GetComponent(); if (holdSeg != null) { holdSeg.Setup(holdNoteId, noteData.trackIndex, CalculateSpeed(), noteData.time, segmentDelay, isEndSegment, scheduledEndTime, noteData.color, key, partType); } else { Debug.LogError("长音符片段缺少 HoldNote 组件!"); } } } //TEST private float CalculateSpeed() { float noteTravelTime = (60f / bpm) * 4; return 10.75f / noteTravelTime; } private void Update() { //if (globalGameTime.text=="0.01") //{ // bgMusicAudioSource.Play(); //} //else return; } }