备份,准备做双端

This commit is contained in:
FloatGaming
2026-07-30 23:15:58 +08:00
parent add675e45d
commit ec4ec53545
88 changed files with 4050 additions and 872 deletions
+27 -5
View File
@@ -14,9 +14,16 @@ public class NotePool : MonoBehaviour
[Header("Pool Size")]
public int poolSize = 24;
public int maxPoolSize = 300;
// Worst-case hold-segment count for one long note ≈ length(s) × sm(≤8) × bpm / 15.
// A 4s hold at 120bpm with max flow speed needs ~256 middle segments of one color at once.
// maxPoolSize is the retain cap on return (below it, returned segments are kept, not
// Destroyed), so it must exceed that worst case to avoid churn when a dense long note recycles.
public int maxPoolSize = 320;
// poolSize × this = per-color hold-segment prewarm target. Sized so prewarm covers the
// worst case (24 × 12 = 288 ≥ 256), preventing a mid-song runtime Instantiate spike the
// first time a dense long note needs more segments than were prewarmed.
[Tooltip("Multiplier for hold segment pool size (per color).")]
public int holdSegmentPoolMultiplier = 8;
public int holdSegmentPoolMultiplier = 12;
[Tooltip("Multiplier for hold end pool size (per color).")]
public int holdEndPoolMultiplier = 8;
@@ -257,12 +264,18 @@ public class NotePool : MonoBehaviour
// Defensive: unregister/unlock any TrackKeyManager state referencing this object to avoid stale queues/locks
try
{
// Try to determine track index from Note or HoldNote components
// Try to determine track index from Note or HoldNote components. Reuse each
// note's already-cached instance-id string (Note.GetCachedInstanceId /
// HoldNote.GetQueueNoteId) instead of allocating a fresh GetInstanceID().ToString()
// on every return — a 256-segment hold recycle would otherwise burst 256 string
// allocations. The cached ids are byte-identical to what was used at RegisterKey.
int trackIdx = -1;
string id = null;
var noteComp = obj.GetComponent<Note>();
if (noteComp != null)
{
trackIdx = noteComp.GetTrackIndex();
id = noteComp.GetCachedInstanceId();
}
else
{
@@ -270,11 +283,20 @@ public class NotePool : MonoBehaviour
if (holdComp != null)
{
trackIdx = holdComp.trackIndex;
id = holdComp.GetQueueNoteId();
}
}
string id = obj.GetInstanceID().ToString();
if (TrackKeyManager.Instance != null && trackIdx >= 0)
// If a note component supplied a cached id, use it. When it's null (e.g. a hold
// middle/end segment that never registered a queue key), there is nothing to
// unregister — skip without allocating a throwaway ToString. Only the fully
// unknown case (no note component at all) falls back to a fresh id.
if (string.IsNullOrEmpty(id) && noteComp == null && trackIdx < 0)
{
id = obj.GetInstanceID().ToString();
}
if (TrackKeyManager.Instance != null && trackIdx >= 0 && !string.IsNullOrEmpty(id))
{
try { TrackKeyManager.Instance.UnregisterKey(trackIdx, id); } catch { }
try { TrackKeyManager.Instance.UnlockTrackForJudge(trackIdx, id); } catch { }