hold音符补丁 备份
This commit is contained in:
@@ -60,6 +60,11 @@ public class HoldNote : BaseNote
|
||||
[Range(1f, 2f)]
|
||||
public float holdWindowMultiplier = 1.3f;
|
||||
|
||||
[Header("Custom Animation")]
|
||||
public GameObject holdAnimationPrefab;
|
||||
private GameObject activeHoldAnimationInstance;
|
||||
private Coroutine delayedHoldAnimationCoroutine;
|
||||
|
||||
public float visualSpeedMultiplier = 1f; // injected from NoteSpawner to adapt windows when visual speed changes
|
||||
|
||||
// track when the hold actually started (real-time) so we can compute held fraction
|
||||
@@ -317,6 +322,58 @@ public class HoldNote : BaseNote
|
||||
}
|
||||
}
|
||||
|
||||
private void StartHoldEffects()
|
||||
{
|
||||
StopHoldEffects(); // cleanup any existing
|
||||
if (gameObject.activeInHierarchy)
|
||||
{
|
||||
delayedHoldAnimationCoroutine = StartCoroutine(DelayedStartHoldEffects());
|
||||
}
|
||||
}
|
||||
|
||||
private void StopHoldEffects()
|
||||
{
|
||||
if (delayedHoldAnimationCoroutine != null)
|
||||
{
|
||||
StopCoroutine(delayedHoldAnimationCoroutine);
|
||||
delayedHoldAnimationCoroutine = null;
|
||||
}
|
||||
if (activeHoldAnimationInstance != null)
|
||||
{
|
||||
Destroy(activeHoldAnimationInstance);
|
||||
activeHoldAnimationInstance = null;
|
||||
}
|
||||
AnimationController.Global?.StopHoldParticles();
|
||||
}
|
||||
|
||||
private IEnumerator DelayedStartHoldEffects()
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
|
||||
// Start standard particles
|
||||
AnimationController.Global?.StartHoldParticles(noteColor);
|
||||
|
||||
// Instantiate custom prefab if assigned
|
||||
if (holdAnimationPrefab != null)
|
||||
{
|
||||
// find spawn position: prefer the track effect position if available from AnimationController
|
||||
Vector3 spawnPos = transform.position;
|
||||
var ac = AnimationController.Global;
|
||||
if (ac != null)
|
||||
{
|
||||
// Logic to find slot position (simplified: use ac's position or the note's)
|
||||
// In AnimationController.PlayDestroyAnimation, it uses redEffect.transform.position etc.
|
||||
// We don't have direct access to those private fields, but we can assume
|
||||
// the note is at the judge line when this starts.
|
||||
}
|
||||
|
||||
activeHoldAnimationInstance = Instantiate(holdAnimationPrefab, spawnPos, Quaternion.identity);
|
||||
|
||||
// Optionally parent to the note or track
|
||||
// activeHoldAnimationInstance.transform.SetParent(this.transform, false);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator DelayedDisableAnimation(GameObject animationObject, float delay)
|
||||
{
|
||||
// No-op: we used to disable the shared AnimationController here which stopped coroutines.
|
||||
@@ -440,7 +497,7 @@ public class HoldNote : BaseNote
|
||||
if (!isHoldActive && jm != null && jm.IsStartJudged(noteID) && !jm.HasNoteReleased(noteID) && keyHeld)
|
||||
{
|
||||
isHoldActive = true;
|
||||
AnimationController.Global?.StartHoldParticles(noteColor);
|
||||
StartHoldEffects();
|
||||
if (debugEnabled) Debug.Log($"[HoldNote] Start particles started for {noteID} color={noteColor} at time={now:F3}");
|
||||
}
|
||||
|
||||
@@ -474,7 +531,7 @@ public class HoldNote : BaseNote
|
||||
if (isHoldActive && keyUp)
|
||||
{
|
||||
isHoldActive = false;
|
||||
AnimationController.Global?.StopHoldParticles();
|
||||
StopHoldEffects();
|
||||
if (debugEnabled) Debug.Log($"[HoldNote] KeyUp {keyToPress} detected. NoteID: {noteID}, Segment: {segment}, Type: {type}");
|
||||
|
||||
if (!hasReleased)
|
||||
@@ -649,7 +706,7 @@ public class HoldNote : BaseNote
|
||||
JudgeManager.Instance.RegisterStartJudged(noteID, true);
|
||||
isHoldActive = true;
|
||||
PlayHitAnimation();
|
||||
AnimationController.Global?.StartHoldParticles(noteColor);
|
||||
StartHoldEffects();
|
||||
|
||||
holdStartTime = pressTime;
|
||||
HoldNoteJudgePool.RegisterStart(noteID, pressTime, hitTime, scheduledEndTime, noteColor, trackIndex, (object)noteData);
|
||||
@@ -695,17 +752,17 @@ public class HoldNote : BaseNote
|
||||
// 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");
|
||||
if (JudgeManager.IsDebugEnabled) Debug.Log($"[HoldNote] End entered while key still held: {noteColor}, forcing Perfect");
|
||||
// Record release time as current time (player is still holding)
|
||||
releaseTime = Time.time;
|
||||
hasReleased = true;
|
||||
JudgeManager.Instance?.RegisterNoteReleased(noteID, true);
|
||||
// Evaluate and judge the hold end
|
||||
EvaluateHoldEnd(releaseTime, false);
|
||||
// Evaluate and judge the hold end - force Perfect since we reached the end while holding
|
||||
EvaluateHoldEnd(releaseTime, false, true);
|
||||
isJudged = true;
|
||||
// Terminate input - mark key as released
|
||||
isHoldActive = false;
|
||||
AnimationController.Global?.StopHoldParticles();
|
||||
StopHoldEffects();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -875,7 +932,7 @@ public class HoldNote : BaseNote
|
||||
JudgeManager.Instance.RegisterStartJudged(noteID, true);
|
||||
isHoldActive = true;
|
||||
PlayHitAnimation();
|
||||
AnimationController.Global?.StartHoldParticles(noteColor);
|
||||
StartHoldEffects();
|
||||
|
||||
// record when the hold started so we can compute held fraction later
|
||||
holdStartTime = pressTime;
|
||||
@@ -891,7 +948,7 @@ public class HoldNote : BaseNote
|
||||
JudgeManager.Instance.RegisterStartJudged(noteID, true);
|
||||
isHoldActive = true;
|
||||
PlayHitAnimation();
|
||||
AnimationController.Global?.StartHoldParticles(noteColor);
|
||||
StartHoldEffects();
|
||||
|
||||
holdStartTime = pressTime;
|
||||
|
||||
@@ -905,7 +962,7 @@ public class HoldNote : BaseNote
|
||||
JudgeManager.Instance.RegisterStartJudged(noteID, true);
|
||||
isHoldActive = true;
|
||||
PlayHitAnimation();
|
||||
AnimationController.Global?.StartHoldParticles(noteColor);
|
||||
StartHoldEffects();
|
||||
|
||||
holdStartTime = pressTime;
|
||||
|
||||
@@ -986,7 +1043,7 @@ public class HoldNote : BaseNote
|
||||
}
|
||||
|
||||
// central evaluation for hold end, given an actual releaseTime (real-time) or forceMiss
|
||||
private void EvaluateHoldEnd(float actualReleaseTime, bool forceMiss)
|
||||
private void EvaluateHoldEnd(float actualReleaseTime, bool forceMiss, bool forcePerfect = false)
|
||||
{
|
||||
if (isJudged) return; // already evaluated
|
||||
|
||||
@@ -1001,7 +1058,7 @@ public class HoldNote : BaseNote
|
||||
hasReleased = true;
|
||||
JudgeManager.Instance.RegisterNoteReleased(noteID, true);
|
||||
|
||||
if (JudgeManager.IsDebugEnabled) Debug.Log($"[HoldNote] EvaluateHoldEnd: noteID={noteID} releaseTime={releaseTime:F3} scheduledEnd={scheduledEndTime:F3} forceMiss={forceMiss}");
|
||||
if (JudgeManager.IsDebugEnabled) Debug.Log($"[HoldNote] EvaluateHoldEnd: noteID={noteID} releaseTime={releaseTime:F3} scheduledEnd={scheduledEndTime:F3} forceMiss={forceMiss} forcePerfect={forcePerfect}");
|
||||
|
||||
string result;
|
||||
|
||||
@@ -1028,13 +1085,13 @@ public class HoldNote : BaseNote
|
||||
float playerHeld = Mathf.Clamp(releaseTime - info.pressTime, 0f, info.length);
|
||||
float frac = info.length <= 0f ? 0f : (playerHeld / info.length);
|
||||
|
||||
if (frac > 0.8f)
|
||||
if (forcePerfect || frac > 0.7f)
|
||||
{
|
||||
result = "Perfect";
|
||||
ScoreManager.Instance.countPerfect += 1;
|
||||
if (trackIndex >= 0 && trackIndex < 5) ScoreManager.Instance.trackPerfectCounts[trackIndex]++;
|
||||
}
|
||||
else if (frac > 0.5f)
|
||||
else if (frac > 0.4f)
|
||||
{
|
||||
result = "Great";
|
||||
ScoreManager.Instance.countGreat += 1;
|
||||
@@ -1069,13 +1126,13 @@ public class HoldNote : BaseNote
|
||||
float held = Mathf.Clamp(actualReleaseTime - hitTime, 0f, holdRequired);
|
||||
float frac = holdRequired <= 0f ? 0f : (held / holdRequired);
|
||||
|
||||
if (frac > 0.8f)
|
||||
if (forcePerfect || frac > 0.7f)
|
||||
{
|
||||
result = "Perfect";
|
||||
ScoreManager.Instance.countPerfect += 1;
|
||||
if (trackIndex >= 0 && trackIndex < 5) ScoreManager.Instance.trackPerfectCounts[trackIndex]++;
|
||||
}
|
||||
else if (frac > 0.5f)
|
||||
else if (frac > 0.4f)
|
||||
{
|
||||
result = "Great";
|
||||
ScoreManager.Instance.countGreat += 1;
|
||||
@@ -1193,7 +1250,7 @@ public class HoldNote : BaseNote
|
||||
if (JudgeManager.IsDebugEnabled) Debug.Log($"[HoldNote] Hold end NotifyNoteHit called: TrackIndex={TrackIndex} trackIndexField={trackIndex} result={result} triggeredHold={triggeredHold} triggeredTap={triggeredTap}");
|
||||
}
|
||||
|
||||
AnimationController.Global?.StopHoldParticles();
|
||||
StopHoldEffects();
|
||||
|
||||
// Release the track lock immediately after end evaluation so the next hold can start on time
|
||||
ReleaseTrackJudgeLockSafe();
|
||||
@@ -1315,6 +1372,9 @@ public class HoldNote : BaseNote
|
||||
// Restore materials before returning to pool/reusing
|
||||
RestoreOriginalMaterials();
|
||||
|
||||
// Stop any active hold animations or delayed starts
|
||||
StopHoldEffects();
|
||||
|
||||
hasReleased = false;
|
||||
segment = NoteSegment.None;
|
||||
keyToPress = KeyCode.None;
|
||||
|
||||
Reference in New Issue
Block a user