Files
bansonic_beta_main/Assets/scripts/gamePlay_gameplay/NoteSpawner.cs
T
2025-06-02 00:48:08 +08:00

218 lines
6.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<Note>();
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<HoldNote>();
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<HoldNote>();
if (holdSeg != null)
{
holdSeg.Setup(holdNoteId, noteData.trackIndex, CalculateSpeed(), noteData.time, segmentDelay, isEndSegment, scheduledEndTime, noteData.color, key, partType);
}
else
{
Debug.LogError("长音符片段缺少 HoldNote 组件!");
}
}
}
private float CalculateSpeed()
{
float noteTravelTime = (60f / bpm) * 4;
return 10.75f / noteTravelTime;
}
private void Update()
{
//if (globalGameTime.text=="0.01")
//{
// bgMusicAudioSource.Play();
//}
//else return;
}
}