超大量的更新 修复很多问题,gameplay特效初步

This commit is contained in:
2026-02-14 23:46:20 +08:00
parent ef8eb67259
commit 3a7a0b4669
360 changed files with 85670 additions and 4144 deletions
+147 -9
View File
@@ -12,7 +12,6 @@ public class HoldNote : BaseNote
private string noteID = string.Empty;
private NoteSegment segment = NoteSegment.None;
private new float hitTime = 0f;
private float releaseTime = 0f;
private bool hasReleased = true;
private bool hasEnteredLine = false;
@@ -68,6 +67,7 @@ public class HoldNote : BaseNote
// Cache allies per track to avoid GameObject.Find on first judgement.
private static AllyCombatant[] allyCache;
private static BeatmapManager beatmapManagerCache;
private struct RendererMaterialCache
{
@@ -92,6 +92,40 @@ public class HoldNote : BaseNote
return allyCache[trackIndex];
}
private static BeatmapManager GetBeatmapManagerCached()
{
if (beatmapManagerCache != null) return beatmapManagerCache;
beatmapManagerCache = Object.FindAnyObjectByType<BeatmapManager>();
return beatmapManagerCache;
}
private static float JudgeToPmMultiplier(string judgeResult)
{
switch (judgeResult)
{
case "Perfect": return 1f;
case "Great": return 0.75f;
case "Good": return 0.5f;
case "Miss": return 0f;
default: return 0f;
}
}
private static int ComputePmDeltaFromJudge(string judgeResult, AllyCombatant ally)
{
int baseScore = 0;
var bmm = ally != null ? ally.bmm : null;
if (bmm == null) bmm = GetBeatmapManagerCached();
if (bmm != null) baseScore = Mathf.Max(0, bmm.perNoteScore);
if (baseScore <= 0 && ally != null) baseScore = Mathf.Max(0, ally.baseTrackScore);
if (baseScore <= 0) return 0;
float mult = JudgeToPmMultiplier(judgeResult);
return Mathf.FloorToInt(baseScore * mult);
}
private JudgeManager cachedJudgeManager;
private TrackKeyManager cachedTrackKeyManager;
@@ -362,6 +396,12 @@ public class HoldNote : BaseNote
if (now < hitTime - 0.5f) return;
}
if (GameConfig.autoPlayEnabled)
{
UpdateAutoplay(now, jm, tkm, debugEnabled);
return;
}
bool keyHeld = Input.GetKey(keyToPress);
bool keyDown = Input.GetKeyDown(keyToPress);
bool keyUp = Input.GetKeyUp(keyToPress);
@@ -491,6 +531,104 @@ public class HoldNote : BaseNote
}
}
private void UpdateAutoplay(float now, JudgeManager jm, TrackKeyManager tkm, bool debugEnabled)
{
// Keep the "hold active" state alive for middle/end segments once the start has been judged.
if (!isHoldActive && jm != null && jm.IsStartJudged(noteID) && !jm.HasNoteReleased(noteID))
{
isHoldActive = true;
}
if (segment == NoteSegment.Start)
{
bool startResolved = jm != null && jm.IsStartJudged(noteID);
if (!startResolved && now >= hitTime)
{
// Ensure we are the front-most note in the judge queue (if any)
var headId = tkm?.GetCurrentNoteId(trackIndex);
if (headId != null && headId != queueNoteId)
{
return;
}
float pressTimeLocal = hitTime; // force Perfect regardless of frame timing
float maxWindow = (judgeConfig?.missRange ?? 0.5f) * holdWindowMultiplier;
if (tkm != null && !tkm.IsBestCandidate(trackIndex, queueNoteId, pressTimeLocal, maxWindow))
{
return;
}
HandleStartAutoplayPerfect(pressTimeLocal);
}
return;
}
if (segment == NoteSegment.Middle)
{
if (jm != null && jm.IsStartJudged(noteID) && isHoldActive && !jm.HasNoteReleased(noteID))
{
if (now >= hitTime && hasEnteredLine)
{
if (debugEnabled) Debug.Log($"[HoldNote.AutoPlay] Middle passed: {noteColor}");
PlayHitAnimation();
jm?.RegisterMiddlePassed(noteID);
ScheduleReturnToPool(0.2f);
isJudged = true;
}
}
return;
}
if (segment == NoteSegment.End)
{
if (jm != null && jm.IsStartJudged(noteID) && !jm.HasNoteReleased(noteID))
{
if (now >= scheduledEndTime)
{
// Defensive: ensure pool info exists so EvaluateHoldEnd resolves to Perfect deterministically.
if (!HoldNoteJudgePool.TryGet(noteID, out _))
{
if (noteData != null) noteData.judgeOffsetMs = 0f;
HoldNoteJudgePool.RegisterStart(noteID, hitTime, hitTime, scheduledEndTime, noteColor, trackIndex, (object)noteData);
}
EvaluateHoldEnd(scheduledEndTime, false);
}
}
return;
}
}
private void HandleStartAutoplayPerfect(float pressTime)
{
// release from queue so following notes can become head
UnregisterQueueIfNeeded();
if (!JudgeManager.Instance.TryResolveStart(noteID))
{
if (JudgeManager.IsDebugEnabled) Debug.Log($"[HoldNote.AutoPlay] START try-resolve failed: {noteColor}");
return;
}
const string result = "Perfect";
float rawOffsetMs = (hitTime - pressTime) * 1000f;
if (noteData != null) noteData.judgeOffsetMs = rawOffsetMs;
JudgeManager.Instance.RegisterStartJudged(noteID, true);
isHoldActive = true;
PlayHitAnimation();
AnimationController.Global?.StartHoldParticles(noteColor);
holdStartTime = pressTime;
HoldNoteJudgePool.RegisterStart(noteID, pressTime, hitTime, scheduledEndTime, noteColor, trackIndex, (object)noteData);
InputManager.Instance?.ShowJudgeResult(trackIndex, result);
teamUIController.Instance?.OnJudgeResult(result);
JudgeSoundManager.Instance?.PlayJudgeSound(result);
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (!collision.CompareTag("JudgmentLine")) return;
@@ -523,8 +661,9 @@ public class HoldNote : BaseNote
return;
}
// NEW: If the key is still being held down when end segment enters judge zone, immediately judge
if (Input.GetKey(keyToPress) && JudgeManager.Instance.IsStartJudged(noteID) && !isJudged)
// If the key is still being held down when end segment enters judge zone, immediately judge.
// Autoplay must ignore physical input to guarantee Perfect at scheduledEndTime.
if (!GameConfig.autoPlayEnabled && Input.GetKey(keyToPress) && JudgeManager.Instance.IsStartJudged(noteID) && !isJudged)
{
if (JudgeManager.IsDebugEnabled) Debug.Log($"[HoldNote] End entered while key still held: {noteColor}, calculating result immediately");
// Record release time as current time (player is still holding)
@@ -945,12 +1084,11 @@ public class HoldNote : BaseNote
try
{
var ally = GetAllyForTrackCached(TrackIndex);
if (ally != null)
{
int added = ally.AddScoreForJudge(result);
float efficiency = ally.scoreEfficiency;
ScoreManager.Instance?.AddPmScoreForTrack(TrackIndex, added, efficiency);
}
if (ally != null) ally.AddScoreForJudge(result);
int pmDelta = ComputePmDeltaFromJudge(result, ally);
float efficiency = (ally != null && !ally.IsDead) ? ally.scoreEfficiency : 0f;
ScoreManager.Instance?.AddPmScoreForTrack(TrackIndex, pmDelta, efficiency);
}
catch (System.Exception ex)
{