Files
ichni_Official/Assets/Scripts/Manager/NoteManager.cs
SoulliesOfficial 96619b1bb5 谱面替换
2026-07-30 09:28:43 -04:00

92 lines
3.0 KiB
C#

using System.Collections.Generic;
using Lean.Pool;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class NoteManager : MonoBehaviour
{
#region [] Fields
// 挂起队列:存放还未进入判定时间序列休眠的预设
private List<(float activationTime, NoteBase note)> _pendingNotes = new List<(float, NoteBase)>();
// 活跃队列:存活在场上的有效音符,统一进行中央更新
private List<NoteBase> _activeNotes = new List<NoteBase>(500);
private int _nextNoteIndex = 0;
#endregion
#region [] Registration
public void RegisterNote(NoteBase note, float activationTime)
{
_pendingNotes.Add((activationTime, note));
}
public void AllNotesRegistered()
{
_pendingNotes.Sort((a, b) => a.activationTime.CompareTo(b.activationTime));
_nextNoteIndex = 0;
}
#endregion
#region [] Manager-Driven Tick
public void ManualPrepareForJudge(float currentSongTime)
{
if (!GameManager.Instance.songPlayer.isUpdating) return;
// 1. 唤醒 pending 并推进入场
while (_nextNoteIndex < _pendingNotes.Count &&
currentSongTime >= _pendingNotes[_nextNoteIndex].activationTime)
{
NoteBase noteToActivate = _pendingNotes[_nextNoteIndex].note;
noteToActivate.gameObject.SetActive(true);
_activeNotes.Add(noteToActivate);
_nextNoteIndex++;
}
// 2. 判定前更新场内 Note 的最终空间状态与候选列表。
for (int i = _activeNotes.Count - 1; i >= 0; i--)
{
_activeNotes[i].ManualPrepareForJudge(currentSongTime);
}
}
public void ManualResolveAfterJudge(float currentSongTime)
{
if (!GameManager.Instance.songPlayer.isUpdating) return;
// 输入判定完成后再处理 Miss、Hold buffer、特效与销毁。
for (int i = _activeNotes.Count - 1; i >= 0; i--)
{
if (!_activeNotes[i].ManualResolveAfterJudge(currentSongTime))
{
_activeNotes.RemoveAt(i);
}
}
}
public void ManualLateUpdate(float currentSongTime)
{
if (!GameManager.Instance.songPlayer.isUpdating) return;
for (int i = _activeNotes.Count - 1; i >= 0; i--)
{
if (_activeNotes[i] is Hold hold)
{
hold.isHolding = false;
}
}
}
#endregion
#region [] Pool Management
public void DespawnNote(NoteBase note)
{
if (note.gameObject.activeSelf)
{
LeanPool.Despawn(note.gameObject);
}
}
#endregion
}
}