Files
ichni_Creator_Studio/Assets/Scripts/Manager/NoteManager.cs
2025-10-03 18:21:40 +08:00

162 lines
5.1 KiB
C#

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<NoteBase> allNotes = new List<NoteBase>();
public List<NoteBase> activeNotes = new List<NoteBase>();
private List<NoteBase> notesToRemove = new List<NoteBase>();
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<NoteBase> GetAllNotes()
{
return allNotes.AsReadOnly();
}
}
}