using System.Collections; using System.Collections.Generic; using Ichni.RhythmGame; using UniRx; using UnityEngine; namespace Ichni { public class NoteManager { public static NoteManager instance; public NoteManager() { instance = this; } private List allNotes = new List(); public List activeNotes = new List(); private List notesToRemove = new List(); public int currentActiveNoteCount => activeNotes.Count; private float lastKnownTime = -1f; public void AddNote(NoteBase note) { allNotes.Add(note); // 只在添加时排序一次 allNotes.Sort((a, b) => a.NoteAppearTime.CompareTo(b.NoteAppearTime)); note.UpdateNote(); // 初始化状态 Observable.NextFrame().Subscribe(_ => { note.noteVisual?.generateEffect?.PreExecute(); note.noteVisual?.noteMain.SetActive(true); note.UpdateNote(); // 确保在下一帧也更新一次,防止遗漏 }); } public void RemoveNote(NoteBase note) { activeNotes.Remove(note); allNotes.Remove(note); } public void UpdateNote() { if (allNotes.Count == 0) return; float currentTime = EditorManager.instance.songInformation.songTime; // 检测时间方向 bool isTimeMovingForward = currentTime >= lastKnownTime; lastKnownTime = currentTime; // 清空待移除列表 notesToRemove.Clear(); // 处理时间前进的情况 - 添加新音符 if (isTimeMovingForward) { // 查找所有应该激活但尚未激活的音符 for (int i = 0; i < allNotes.Count; i++) { var note = allNotes[i]; // 如果音符应该出现但还没激活 if (note.NoteAppearTime <= currentTime ) { if (!activeNotes.Contains(note)) activeNotes.Add(note); } else if (note.exactJudgeTime < currentTime) break; } } // 处理时间倒退的情况 - 调整活跃列表 else { // 移除在当前时间之后出现的音符 for (int i = activeNotes.Count - 1; i >= 0; i--) { var note = activeNotes[i]; if (note.NoteAppearTime > currentTime) { notesToRemove.Add(note); } } for (int i = 0; i < allNotes.Count; i++) { var note = allNotes[i]; // 如果音符应该出现但还没激活 if (note.isFirstJudged && note.exactJudgeTime > currentTime ) { if (!activeNotes.Contains(note)) activeNotes.Add(note); } // else if (note.NoteAppearTime < currentTime) // { // break; // 提前退出循环,优化性能 // } } } // 更新所有活跃音符 for (int i = 0; i < activeNotes.Count; i++) { var note = activeNotes[i]; note.UpdateNote(); // Debug.Log($"Updating Note {note.elementName} at time {currentTime}"); // 标记已判定的音符等待移除 if (note.isFirstJudged) { notesToRemove.Add(note); } } // 移除标记的音符 for (int i = 0; i < notesToRemove.Count; i++) { activeNotes.Remove(notesToRemove[i]); } } // 重置所有状态(用于歌曲重新开始等) public void ResetAll() { activeNotes.Clear(); notesToRemove.Clear(); lastKnownTime = -1f; // 不重置音符状态,让音符自己的逻辑处理 } // 跳转到指定时间 public void SeekToTime(float targetTime) { // 清空当前活跃列表 activeNotes.Clear(); notesToRemove.Clear(); // 添加在目标时间之前应该出现的音符 for (int i = 0; i < allNotes.Count; i++) { var note = allNotes[i]; // 添加在目标时间之前应该出现的音符 if (note.NoteAppearTime <= targetTime) { activeNotes.Add(note); } } lastKnownTime = targetTime; } // 获取所有音符(只读) public IReadOnlyList GetAllNotes() { return allNotes.AsReadOnly(); } } }