162 lines
5.1 KiB
C#
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();
|
|
}
|
|
}
|
|
} |