修复一堆bug 加入粒子系统代替原击打特效 焕新长音符逻辑 修复多重计分 更新判定管理和音符生成器 搞了一个免费包
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System.Collections;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -32,21 +32,37 @@ public class HoldNote : BaseNote
|
||||
public KeyCode key;
|
||||
public string type; // "start", "middle", or "end"
|
||||
|
||||
private bool isJudged = false; // 分段判定标记,一旦判定(无论成功失败)就设为true,避免重复判定
|
||||
private bool isHoldActive = false; // 长按有效标记:Start段成功判定且按键未松开
|
||||
private bool isJudged = false; // 分段判定标记,一旦判定(无论成功失败)就设为true,避免重复判定
|
||||
private bool isHoldActive = false; // 长按有效标记:Start段成功判定且按键未松开
|
||||
|
||||
// 新增变量
|
||||
private bool hasBeenHeldFromStart = false; // 进入判定区时是否已按住 (用于辅助判断,但不再直接阻断判定)
|
||||
// 新增变量
|
||||
private bool hasBeenHeldFromStart = false; // 进入判定区时是否已按住 (用于辅助判断,但不再直接阻断判定)
|
||||
|
||||
[Header("判定区间配置")]
|
||||
public NoteJudgeConfig judgeConfig; // 判定区间配置,需在预制体或生成时赋值
|
||||
[Header("判定区间配置")]
|
||||
public NoteJudgeConfig judgeConfig; // 判定区间配置,需在预制体或生成时赋值
|
||||
private NoteData noteData;
|
||||
|
||||
private bool _hasTriggeredOnThisHold = false; // ensure single trigger per hold note
|
||||
// private bool _hasTriggeredOnThisHold = false; // ensure single trigger per hold note
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
controller = GetComponent<HoldNoteController>();
|
||||
anim = GetComponent<AnimationController>();
|
||||
// Prefer the global shared AnimationController if available, otherwise fallback to local or scene instance
|
||||
anim = AnimationController.Global;
|
||||
if (anim == null)
|
||||
{
|
||||
anim = GetComponent<AnimationController>();
|
||||
if (anim == null)
|
||||
{
|
||||
anim = FindObjectOfType<AnimationController>();
|
||||
}
|
||||
}
|
||||
|
||||
if (anim == null)
|
||||
{
|
||||
Debug.LogWarning("HoldNote: No AnimationController found (Global/local/scene). Particle effects will be unavailable.");
|
||||
}
|
||||
|
||||
if (controller != null)
|
||||
{
|
||||
controller.OnJudgeZoneChanged += OnJudgeZoneChanged;
|
||||
@@ -73,30 +89,26 @@ public class HoldNote : BaseNote
|
||||
|
||||
private void PlayHitAnimation()
|
||||
{
|
||||
if (anim != null)
|
||||
var controller = AnimationController.Global ?? anim;
|
||||
if (controller != null)
|
||||
{
|
||||
// 激活动画效果 GameObject
|
||||
anim.gameObject.SetActive(true);
|
||||
anim.PlayDestroyAnimation(noteColor);
|
||||
|
||||
// 延迟禁用动画效果 GameObject,确保动画播放完毕
|
||||
StartCoroutine(DelayedDisableAnimation(anim.gameObject, 0.5f)); // 0.5秒后禁用
|
||||
controller.PlayDestroyAnimation(noteColor);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator DelayedDisableAnimation(GameObject animationObject, float delay)
|
||||
{
|
||||
yield return new WaitForSeconds(delay);
|
||||
animationObject.SetActive(false);
|
||||
// No-op: we used to disable the shared AnimationController here which stopped coroutines.
|
||||
// Keep as no-op to avoid side effects.
|
||||
yield return null;
|
||||
}
|
||||
|
||||
public void Setup(int id, int trackIndex, float speed, float time, float delay,
|
||||
bool isEnd, float scheduledEnd, string color, KeyCode key, string type, NoteJudgeConfig judgeConfig)
|
||||
bool isEnd, float scheduledEnd, string color, KeyCode key, string type, NoteJudgeConfig judgeConfig, NoteData noteData)
|
||||
{
|
||||
this.id = id;
|
||||
this.trackIndex = trackIndex;
|
||||
// also set BaseNote.TrackIndex so other systems using TrackIndex property work consistently
|
||||
this.TrackIndex = trackIndex;
|
||||
this.speed = speed;
|
||||
this.startTime = time;
|
||||
this.delay = delay;
|
||||
@@ -117,19 +129,21 @@ public class HoldNote : BaseNote
|
||||
this.hasEnteredLine = false;
|
||||
this.hasReleased = false;
|
||||
|
||||
// 判定区间配置检查
|
||||
// 判定区间配置检查
|
||||
if (judgeConfig == null)
|
||||
Debug.LogError($"HoldNoteJudgeConfig is null! 判定区间配置未传入!track={trackIndex}");
|
||||
Debug.LogError($"HoldNoteJudgeConfig is null! 判定区间配置未传入!track={trackIndex}");
|
||||
else
|
||||
Debug.Log($"HoldNoteJudgeConfig: perfect={judgeConfig.perfectRange}, great={judgeConfig.greatRange}, good={judgeConfig.goodRange}, miss={judgeConfig.missRange}");
|
||||
|
||||
this.noteData = noteData;
|
||||
|
||||
// Debug info to help investigate end note visibility
|
||||
Debug.Log($"[HoldNote.Setup] id={noteID} segment={segment} type={type} hitTime={hitTime:F2} scheduledEnd={scheduledEndTime:F2} color={color} track={trackIndex}");
|
||||
|
||||
// 在 Setup 时注册初始状态
|
||||
// 在 Setup 时注册初始状态
|
||||
JudgeManager.Instance?.RegisterNoteReleased(noteID, false);
|
||||
if (segment == NoteSegment.Start)
|
||||
JudgeManager.Instance?.RegisterStartJudged(noteID, false); // 初始为未判定
|
||||
JudgeManager.Instance?.RegisterStartJudged(noteID, false); // 初始为未判定
|
||||
|
||||
if (segment == NoteSegment.End)
|
||||
JudgeManager.Instance?.RegisterScheduledEndTime(noteID, scheduledEndTime);
|
||||
@@ -140,33 +154,50 @@ public class HoldNote : BaseNote
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 如果当前片段已经判定过,直接返回
|
||||
// 如果当前片段已经判定过,直接返回
|
||||
if (isJudged) return;
|
||||
|
||||
// 自动 Miss 判定:当音符经过判定线且未被判定时
|
||||
// 重新启动长按粒子协程,如果长按状态恢复且协程未运行
|
||||
if (!isHoldActive && JudgeManager.Instance.IsStartJudged(noteID) && !JudgeManager.Instance.HasNoteReleased(noteID) && Input.GetKey(keyToPress))
|
||||
{
|
||||
isHoldActive = true;
|
||||
AnimationController.Global?.StartHoldParticles(noteColor);
|
||||
}
|
||||
|
||||
// 自动 Miss 判定:当音符经过判定线且未被判定时
|
||||
if (hasEnteredLine && !isJudged)
|
||||
{
|
||||
if (segment == NoteSegment.Start && Time.time > hitTime + judgeConfig?.missRange)
|
||||
if(segment == NoteSegment.Start && Time.time > hitTime + judgeConfig?.missRange)
|
||||
{
|
||||
Debug.Log($"[HoldNote] START段超时自动Miss: {noteColor}");
|
||||
HandleStart();
|
||||
Debug.Log($"[HoldNote] START段超时自动Miss(自动): {noteColor}");
|
||||
|
||||
// 只做 Miss 结果展示与登记
|
||||
JudgeManager.Instance.RegisterStartJudged(noteID, false);
|
||||
|
||||
InputManager.Instance?.ShowJudgeResult(trackIndex, "Miss");
|
||||
JudgeSoundManager.Instance?.PlayJudgeSound("Miss");
|
||||
teamUIController.Instance?.OnJudgeResult("Miss");
|
||||
|
||||
isJudged = true;
|
||||
ReturnToPool();
|
||||
}
|
||||
|
||||
else if (segment == NoteSegment.End && Time.time > scheduledEndTime + (judgeConfig?.missRange ?? 0.3f))
|
||||
{
|
||||
Debug.Log($"[HoldNote] END段超时自动Miss: {noteColor}");
|
||||
Debug.Log($"[HoldNote] END段超时自动Miss: {noteColor}");
|
||||
HandleEnd(true);
|
||||
isJudged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// **通用长按状态更新:**
|
||||
// **通用长按状态更新:**
|
||||
if (isHoldActive && Input.GetKeyUp(keyToPress))
|
||||
{
|
||||
isHoldActive = false;
|
||||
Debug.Log($"[HoldNote] 按键 {keyToPress} 松开,长按状态失效。NoteID: {noteID}, Segment: {segment}, Type: {type}");
|
||||
AnimationController.Global?.StopHoldParticles();
|
||||
Debug.Log($"[HoldNote] 按键 {keyToPress} 松开,长按状态失效。NoteID: {noteID}, Segment: {segment}, Type: {type}");
|
||||
|
||||
// 当玩家松开按键时,向 JudgeManager 注册该长音符已被释放,确保尾部能正确检查释放状态
|
||||
// 当玩家松开按键时,向 JudgeManager 注册该长音符已被释放,确保尾部能正确检查释放状态
|
||||
if (!hasReleased)
|
||||
{
|
||||
hasReleased = true;
|
||||
@@ -176,21 +207,21 @@ public class HoldNote : BaseNote
|
||||
}
|
||||
}
|
||||
|
||||
if (JudgeManager.Instance.IsStartJudged(noteID) && Input.GetKey(keyToPress))
|
||||
/*if (JudgeManager.Instance.IsStartJudged(noteID) && Input.GetKey(keyToPress))
|
||||
{
|
||||
isHoldActive = true;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Start段判定
|
||||
// Start段判定
|
||||
if (segment == NoteSegment.Start && hasEnteredLine)
|
||||
{
|
||||
if (Input.GetKeyDown(keyToPress))
|
||||
{
|
||||
HandleStart();
|
||||
isJudged = true; // 无论成功失败都标记为已判定,避免重复尝试
|
||||
isJudged = true; // 无论成功失败都标记为已判定,避免重复尝试
|
||||
}
|
||||
}
|
||||
// Middle段判定:中段只负责视觉/回收,不做 End 判定统计
|
||||
// Middle段判定:中段只负责视觉/回收,不做 End 判定统计
|
||||
else if (segment == NoteSegment.Middle
|
||||
&& JudgeManager.Instance.IsStartJudged(noteID)
|
||||
&& isHoldActive
|
||||
@@ -200,16 +231,16 @@ public class HoldNote : BaseNote
|
||||
{
|
||||
if (hasEnteredLine)
|
||||
{
|
||||
Debug.Log($"[HoldNote] Middle段通过 (持续长按): {noteColor}");
|
||||
Debug.Log($"[HoldNote] Middle段通过 (持续长按): {noteColor}");
|
||||
PlayHitAnimation();
|
||||
// 把通过事件上报给 JudgeManager(记录中段通过)
|
||||
// 把通过事件上报给 JudgeManager(记录中段通过)
|
||||
JudgeManager.Instance?.RegisterMiddlePassed(noteID);
|
||||
ReturnToPool();
|
||||
isJudged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// End段判定:现在 End 段判定由独立的尾部音符负责(即本对象仍可判定,但更重要的是尾部note会决定最终判定)
|
||||
// End段判定:现在 End 段判定由独立的尾部音符负责(即本对象仍可判定,但更重要的是尾部note会决定最终判定)
|
||||
else if (segment == NoteSegment.End
|
||||
&& JudgeManager.Instance.IsStartJudged(noteID)
|
||||
&& !JudgeManager.Instance.HasNoteReleased(noteID))
|
||||
@@ -231,7 +262,7 @@ public class HoldNote : BaseNote
|
||||
if (segment == NoteSegment.Middle)
|
||||
{
|
||||
hasBeenHeldFromStart = Input.GetKey(keyToPress);
|
||||
Debug.Log($"[HoldNote] Middle段进入判定线: color={noteColor}, isStartJudged={JudgeManager.Instance.IsStartJudged(noteID)}, hasReleased={JudgeManager.Instance.HasNoteReleased(noteID)}, isKeyHeld={Input.GetKey(keyToPress)}, hasBeenHeldFromStart={hasBeenHeldFromStart}");
|
||||
Debug.Log($"[HoldNote] Middle段进入判定线: color={noteColor}, isStartJudged={JudgeManager.Instance.IsStartJudged(noteID)}, hasReleased={JudgeManager.Instance.HasNoteReleased(noteID)}, isKeyHeld={Input.GetKey(keyToPress)}, hasBeenHeldFromStart={hasBeenHeldFromStart}");
|
||||
|
||||
if (autoReturnCoroutine != null)
|
||||
StopCoroutine(autoReturnCoroutine);
|
||||
@@ -241,10 +272,10 @@ public class HoldNote : BaseNote
|
||||
if (autoReturnCoroutine != null)
|
||||
StopCoroutine(autoReturnCoroutine);
|
||||
|
||||
// 如果在尾部进入判定区时玩家已经释放按键,则此时应立即做 End 判定
|
||||
// 如果在尾部进入判定区时玩家已经释放按键,则此时应立即做 End 判定
|
||||
if (JudgeManager.Instance.HasNoteReleased(noteID) && !isJudged)
|
||||
{
|
||||
Debug.Log($"[HoldNote] End段进入判定线但已经释放,立即执行 End 判定: {noteColor}");
|
||||
Debug.Log($"[HoldNote] End段进入判定线但已经释放,立即执行 End 判定: {noteColor}");
|
||||
HandleEnd();
|
||||
isJudged = true;
|
||||
// ReturnToPool handled inside HandleEnd
|
||||
@@ -263,8 +294,8 @@ public class HoldNote : BaseNote
|
||||
{
|
||||
if (!JudgeManager.Instance.IsStartJudged(noteID))
|
||||
{
|
||||
Debug.Log($"[HoldNote] Start段离开判定线未判定,补偿 Miss 并回收: {noteColor}");
|
||||
// 确保未判定的 Start 段在离开判定线时登记为 Miss
|
||||
Debug.Log($"[HoldNote] Start段离开判定线未判定,补偿 Miss 并回收: {noteColor}");
|
||||
// 确保未判定的 Start 段在离开判定线时登记为 Miss
|
||||
HandleStart();
|
||||
isJudged = true;
|
||||
ReturnToPool();
|
||||
@@ -272,7 +303,7 @@ public class HoldNote : BaseNote
|
||||
}
|
||||
else if (segment == NoteSegment.Middle)
|
||||
{
|
||||
Debug.Log($"[HoldNote] Middle段离开判定线强制回收: {noteColor}");
|
||||
Debug.Log($"[HoldNote] Middle段离开判定线强制回收: {noteColor}");
|
||||
ReturnToPool();
|
||||
}
|
||||
else if (segment == NoteSegment.End)
|
||||
@@ -283,15 +314,15 @@ public class HoldNote : BaseNote
|
||||
autoReturnCoroutine = null;
|
||||
}
|
||||
|
||||
// 在尾部离开判定线时,按如下规则处理:
|
||||
// - 如果头部未判定:补偿 Miss 并回收
|
||||
// - 如果头部已判定且玩家已经释放:执行 End 判定并回收
|
||||
// - 如果头部已判定且玩家仍在按住:不要强制 Miss,也不要立即回收,等待玩家松手或超时处理
|
||||
// 在尾部离开判定线时,按如下规则处理:
|
||||
// - 如果头部未判定:补偿 Miss 并回收
|
||||
// - 如果头部已判定且玩家已经释放:执行 End 判定并回收
|
||||
// - 如果头部已判定且玩家仍在按住:不要强制 Miss,也不要立即回收,等待玩家松手或超时处理
|
||||
if (!isJudged)
|
||||
{
|
||||
if (!JudgeManager.Instance.IsStartJudged(noteID))
|
||||
{
|
||||
Debug.Log($"[HoldNote] End段离开判定线且头部未判定,补偿 Miss: {noteColor}");
|
||||
Debug.Log($"[HoldNote] End段离开判定线且头部未判定,补偿 Miss: {noteColor}");
|
||||
if (!JudgeManager.Instance.HasNoteReleased(noteID))
|
||||
HandleEnd(true);
|
||||
ReturnToPool();
|
||||
@@ -300,15 +331,15 @@ public class HoldNote : BaseNote
|
||||
{
|
||||
if (JudgeManager.Instance.HasNoteReleased(noteID))
|
||||
{
|
||||
Debug.Log($"[HoldNote] End段离开判定线且已释放,执行 End 判定: {noteColor}");
|
||||
Debug.Log($"[HoldNote] End段离开判定线且已释放,执行 End 判定: {noteColor}");
|
||||
HandleEnd();
|
||||
isJudged = true;
|
||||
ReturnToPool();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 头部已判定且玩家仍在按住:保持显示,不作回收或判定
|
||||
Debug.Log($"[HoldNote] End段离开判定线,头部已判定且仍在按住,保持显示等待松手或超时: {noteColor}");
|
||||
// 头部已判定且玩家仍在按住:保持显示,不作回收或判定
|
||||
Debug.Log($"[HoldNote] End段离开判定线,头部已判定且仍在按住,保持显示等待松手或超时: {noteColor}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -341,19 +372,28 @@ public class HoldNote : BaseNote
|
||||
|
||||
private void HandleStart()
|
||||
{
|
||||
if (!JudgeManager.Instance.TryResolveStart(noteID))
|
||||
{
|
||||
Debug.Log($"[HoldNote] START 已被判定,跳过: {noteColor}");
|
||||
return;
|
||||
}
|
||||
float pressTime = Time.time;
|
||||
float rawOffsetMs = (hitTime - pressTime) * 1000f;
|
||||
float offset = Mathf.Abs(pressTime - hitTime);
|
||||
string result;
|
||||
if (offset < 0.1f) // 判定成功
|
||||
if (offset < (judgeConfig?.perfectRange ?? 0.1f)) // 判定成功
|
||||
{
|
||||
result = "Perfect";
|
||||
Debug.Log($"[HoldNote] START判定成功(偏差={offset:F2}秒): {noteColor}");
|
||||
ScoreManager.Instance.countPerfect += 1;
|
||||
if (noteData != null) noteData.judgeOffsetMs = rawOffsetMs;
|
||||
Debug.Log($"[HoldNote] START判定成功(偏差={offset:F2}秒): {noteColor}");
|
||||
JudgeManager.Instance.RegisterStartJudged(noteID, true);
|
||||
isHoldActive = true; // 成功判定Start,长按状态激活
|
||||
isHoldActive = true; // 成功判定Start,长按状态激活
|
||||
PlayHitAnimation();
|
||||
AnimationController.Global?.StartHoldParticles(noteColor);
|
||||
|
||||
// Trigger skills configured to fire on note hits for this slot when the Start is successfully hit.
|
||||
if (!_hasTriggeredOnThisHold)
|
||||
if (/*!_hasTriggeredOnThisHold*/JudgeManager.Instance.TryTriggerSkill(noteID))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -371,15 +411,21 @@ public class HoldNote : BaseNote
|
||||
{
|
||||
Debug.LogError($"[HoldNote] NotifyNoteHit(Start) threw: {ex}");
|
||||
}
|
||||
_hasTriggeredOnThisHold = true; // avoid triggering again at End
|
||||
// _hasTriggeredOnThisHold = true; // avoid triggering again at End
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = "Miss";
|
||||
Debug.Log($"[HoldNote] START Miss(偏差={offset:F2}秒): {noteColor}");
|
||||
JudgeManager.Instance.RegisterStartJudged(noteID, false); // 明确标记未判定
|
||||
isHoldActive = false; // Start Miss,长按状态不激活
|
||||
if (JudgeManager.Instance.TryResolveStart(noteID)) // 或 TryResolveEnd
|
||||
{
|
||||
ScoreManager.Instance.countMiss += 1;
|
||||
}
|
||||
// if (noteData != null) noteData.judgeOffsetMs = rawOffsetMs;
|
||||
|
||||
Debug.Log($"[HoldNote] START Miss(偏差={offset:F2}秒): {noteColor}");
|
||||
JudgeManager.Instance.RegisterStartJudged(noteID, false); // 明确标记未判定
|
||||
isHoldActive = false; // Start Miss,长按状态不激活
|
||||
|
||||
// For Miss we should still notify shared logic once so it behaves like short notes
|
||||
try
|
||||
@@ -392,15 +438,39 @@ public class HoldNote : BaseNote
|
||||
{
|
||||
Debug.LogError($"[HoldNote] NotifyNoteHit(Start Miss) threw: {ex}");
|
||||
}
|
||||
_hasTriggeredOnThisHold = true; // ensure we don't trigger again at End
|
||||
// _hasTriggeredOnThisHold = true; // ensure we don't trigger again at End
|
||||
}
|
||||
|
||||
// show judge result and play sound / update combo like short notes
|
||||
InputManager.Instance?.ShowJudgeResult(trackIndex, result);
|
||||
JudgeSoundManager.Instance?.PlayJudgeSound(result);
|
||||
teamUIController.Instance?.OnJudgeResult(result);
|
||||
Animation_GenerateJudgementSituationPrefab.Instance?.SpawnJudgePrefab(noteColor, result);
|
||||
|
||||
StartCoroutine(DelayedReturn());
|
||||
// --- Add scoring for Start like short notes ---
|
||||
try
|
||||
{
|
||||
var allyGo = GameObject.Find($"ally_0{TrackIndex + 1}");
|
||||
if (allyGo != null)
|
||||
{
|
||||
var ally = allyGo.GetComponent<AllyCombatant>();
|
||||
if (ally != null)
|
||||
{
|
||||
int added = ally.AddScoreForJudge(result);
|
||||
float efficiency = ally.scoreEfficiency;
|
||||
ScoreManager.Instance?.AddPmScoreForTrack(TrackIndex, added, efficiency);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogWarning($"[HoldNote] Failed to add per-track score for START: {ex}");
|
||||
}
|
||||
|
||||
if (segment != NoteSegment.Start)
|
||||
{
|
||||
StartCoroutine(DelayedReturn());
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator DelayedReturn()
|
||||
@@ -414,7 +484,12 @@ public class HoldNote : BaseNote
|
||||
|
||||
private void HandleEnd(bool forceMiss = false)
|
||||
{
|
||||
// 记录释放时间并在 JudgeManager 中登记已释放状态
|
||||
if (!JudgeManager.Instance.TryResolveEnd(noteID))
|
||||
{
|
||||
Debug.Log($"[HoldNote] END 已被判定,跳过: {noteColor}");
|
||||
return;
|
||||
}
|
||||
// 记录释放时间并在 JudgeManager 中登记已释放状态
|
||||
if (!hasReleased)
|
||||
{
|
||||
releaseTime = Time.time;
|
||||
@@ -423,15 +498,17 @@ public class HoldNote : BaseNote
|
||||
}
|
||||
|
||||
string result;
|
||||
float rawOffsetMsEnd = 0f;
|
||||
|
||||
// 如果玩家在尾部进入判定区前就松手,则仅登记释放,不在此处进行最终判定和回收,除非是强制 Miss
|
||||
|
||||
// 如果玩家在尾部进入判定区前就松手,则仅登记释放,不在此处进行最终判定和回收,除非是强制 Miss
|
||||
if (!hasEnteredLine && !forceMiss)
|
||||
{
|
||||
Debug.Log($"[HoldNote] HandleEnd: 提前松手,记录释放但等待尾部进入判定区再判定. NoteID={noteID}, color={noteColor}");
|
||||
Debug.Log($"[HoldNote] HandleEnd: 提前松手,记录释放但等待尾部进入判定区再判定. NoteID={noteID}, color={noteColor}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 现在进行正常判定逻辑
|
||||
// 现在进行正常判定逻辑
|
||||
releaseTime = Time.time;
|
||||
hasReleased = true;
|
||||
JudgeManager.Instance.RegisterNoteReleased(noteID, true);
|
||||
@@ -439,56 +516,101 @@ public class HoldNote : BaseNote
|
||||
if (forceMiss || !JudgeManager.Instance.IsStartJudged(noteID))
|
||||
{
|
||||
result = "Miss";
|
||||
Debug.LogWarning($"[HoldNote] END判定失败({noteColor}):{(forceMiss ? "强制Miss" : "头部未判定")}");
|
||||
}
|
||||
else if (judgeConfig != null)
|
||||
{
|
||||
float diff = Mathf.Abs(releaseTime - scheduledEndTime);
|
||||
if (diff <= judgeConfig.perfectRange)
|
||||
// if (JudgeManager.Instance.TryResolveEnd(noteID))
|
||||
{
|
||||
result = "Perfect";
|
||||
}
|
||||
else if (diff <= judgeConfig.greatRange)
|
||||
{
|
||||
result = "Great";
|
||||
}
|
||||
else if (diff <= judgeConfig.goodRange)
|
||||
{
|
||||
result = "Good";
|
||||
}
|
||||
else if (diff <= judgeConfig.missRange)
|
||||
{
|
||||
result = "Miss";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = "Miss";
|
||||
if (result == "Perfect") ScoreManager.Instance.countPerfect += 1;
|
||||
else if (result == "Great") ScoreManager.Instance.countGreat += 1;
|
||||
else if (result == "Good") ScoreManager.Instance.countGood += 1;
|
||||
else ScoreManager.Instance.countMiss += 1;
|
||||
}
|
||||
|
||||
Debug.LogWarning($"[HoldNote] END判定失败({noteColor}):{(forceMiss ? "强制Miss" : "头部未判定")}");
|
||||
}
|
||||
else
|
||||
{
|
||||
float diff = Mathf.Abs(releaseTime - scheduledEndTime);
|
||||
if (diff <= 0.1f)
|
||||
rawOffsetMsEnd = (scheduledEndTime - releaseTime) * 1000f;
|
||||
if (judgeConfig != null)
|
||||
{
|
||||
result = "Perfect";
|
||||
}
|
||||
else if (diff < 0.2f)
|
||||
{
|
||||
result = "Great";
|
||||
}
|
||||
else if (diff < 0.3f)
|
||||
{
|
||||
result = "Good";
|
||||
if (diff <= judgeConfig.perfectRange)
|
||||
{
|
||||
result = "Perfect";
|
||||
}
|
||||
else if (diff <= judgeConfig.greatRange)
|
||||
{
|
||||
result = "Great";
|
||||
}
|
||||
else if (diff <= judgeConfig.goodRange)
|
||||
{
|
||||
result = "Good";
|
||||
}
|
||||
else if (diff <= judgeConfig.missRange)
|
||||
{
|
||||
result = "Miss";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = "Miss";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = "Bad";
|
||||
if (diff <= 0.1f)
|
||||
{
|
||||
result = "Perfect";
|
||||
}
|
||||
else if (diff < 0.2f)
|
||||
{
|
||||
result = "Great";
|
||||
}
|
||||
else if (diff < 0.3f)
|
||||
{
|
||||
result = "Good";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = "Bad";
|
||||
}
|
||||
}
|
||||
// --- 新增:根据最终确定的 result 统计 ---
|
||||
if (result == "Perfect") ScoreManager.Instance.countPerfect += 1;
|
||||
else if (result == "Great") ScoreManager.Instance.countGreat += 1;
|
||||
else if (result == "Good") ScoreManager.Instance.countGood += 1;
|
||||
else ScoreManager.Instance.countMiss += 1;
|
||||
|
||||
// --- 新增:记录偏差数据到 NoteData ---
|
||||
if (noteData != null && result != "Miss")
|
||||
{
|
||||
noteData.judgeOffsetMsEnd = rawOffsetMsEnd;
|
||||
}
|
||||
}
|
||||
|
||||
InputManager.Instance?.ShowJudgeResult(trackIndex, result);
|
||||
teamUIController.Instance?.OnJudgeResult(result); // 新增:更新combo计数
|
||||
teamUIController.Instance?.OnJudgeResult(result); // 新增:更新combo计数
|
||||
Animation_GenerateJudgementSituationPrefab.Instance?.SpawnJudgePrefab(noteColor, result);
|
||||
|
||||
// --- Add scoring for End like short notes ---
|
||||
try
|
||||
{
|
||||
var allyGo = GameObject.Find($"ally_0{TrackIndex + 1}");
|
||||
if (allyGo != null)
|
||||
{
|
||||
var ally = allyGo.GetComponent<AllyCombatant>();
|
||||
if (ally != null)
|
||||
{
|
||||
int added = ally.AddScoreForJudge(result);
|
||||
float efficiency = ally.scoreEfficiency;
|
||||
ScoreManager.Instance?.AddPmScoreForTrack(TrackIndex, added, efficiency);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogWarning($"[HoldNote] Failed to add per-track score for END: {ex}");
|
||||
}
|
||||
|
||||
// Notify SkillBuilder so Hold notes can trigger skills configured for Hold
|
||||
if (!_hasTriggeredOnThisHold)
|
||||
if (JudgeManager.Instance.TryTriggerSkill(noteID))
|
||||
{
|
||||
var sb = SkillBuilder.Instance;
|
||||
if (sb == null)
|
||||
@@ -499,7 +621,7 @@ public class HoldNote : BaseNote
|
||||
{
|
||||
var so = sb.GetAllyHeroSOBySlot(TrackIndex);
|
||||
var def = so?.GetPrimarySkill();
|
||||
Debug.Log($"[HoldNote] About to NotifyNoteHit: TrackIndex={TrackIndex} trackIndexField={trackIndex} so={(so!=null?so.name:"null")} skill={(def!=null?def.skillId:"null")} trigger={(def!=null?def.triggerCondition.ToString():"-")}");
|
||||
Debug.Log($"[HoldNote] About to NotifyNoteHit: TrackIndex={TrackIndex} trackIndexField={trackIndex} so={(so != null ? so.name : "null")} skill={(def != null ? def.skillId : "null")} trigger={(def != null ? def.triggerCondition.ToString() : "-")}");
|
||||
}
|
||||
|
||||
bool triggeredHold = false;
|
||||
@@ -566,15 +688,20 @@ public class HoldNote : BaseNote
|
||||
}
|
||||
}
|
||||
|
||||
_hasTriggeredOnThisHold = true;
|
||||
// _hasTriggeredOnThisHold = true;
|
||||
Debug.Log($"[HoldNote] Hold end NotifyNoteHit called: TrackIndex={TrackIndex} trackIndexField={trackIndex} result={result} triggeredHold={triggeredHold} triggeredTap={triggeredTap}");
|
||||
}
|
||||
Debug.Log($"[HoldNote] END判定结果: {noteColor} {result} (release={releaseTime:F2}, target={scheduledEndTime:F2})");
|
||||
Debug.Log($"[HoldNote] END判定结果: {noteColor} {result} (release={releaseTime:F2}, target={scheduledEndTime:F2})");
|
||||
AnimationController.Global?.StopHoldParticles();
|
||||
ReturnToPool();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (segment == NoteSegment.End)
|
||||
{
|
||||
AnimationController.Global?.StopHoldParticles();
|
||||
}
|
||||
if (autoReturnCoroutine != null)
|
||||
{
|
||||
StopCoroutine(autoReturnCoroutine);
|
||||
@@ -582,19 +709,23 @@ public class HoldNote : BaseNote
|
||||
}
|
||||
|
||||
if (segment == NoteSegment.End &&
|
||||
!isJudged && // 尚未判定
|
||||
JudgeManager.Instance.IsStartJudged(noteID)) // 头部已判定
|
||||
!isJudged && // 尚未判定
|
||||
JudgeManager.Instance.IsStartJudged(noteID)) // 头部已判定
|
||||
{
|
||||
// 只在头部已判定且玩家已松手时补偿 End 判定为 Miss;否则不要强制 Miss
|
||||
// 只在头部已判定且玩家已松手时补偿 End 判定为 Miss;否则不要强制 Miss
|
||||
if (JudgeManager.Instance.HasNoteReleased(noteID) && !isHoldActive)
|
||||
{
|
||||
Debug.Log($"[HoldNote] OnDisable补偿End段判定(已释放): {noteColor}");
|
||||
HandleEnd(); // 正常判定(基于 releaseTime)
|
||||
Debug.Log($"[HoldNote] OnDisable补偿End段判定(已释放): {noteColor}");
|
||||
if (JudgeManager.Instance.TryResolveEnd(noteID))
|
||||
{
|
||||
HandleEnd();
|
||||
}
|
||||
|
||||
isJudged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"[HoldNote] OnDisable:End段未判定且尚有按键状态,跳过强制 Miss: {noteColor}");
|
||||
Debug.Log($"[HoldNote] OnDisable:End段未判定且尚有按键状态,跳过强制 Miss: {noteColor}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,11 +734,11 @@ public class HoldNote : BaseNote
|
||||
|
||||
private void ReturnToPool()
|
||||
{
|
||||
if (!gameObject.activeSelf) return; // 再次检查以防止对象已被禁用
|
||||
if (!gameObject.activeSelf) return; // 再次检查以防止对象已被禁用
|
||||
|
||||
if (segment == NoteSegment.Start && !hasEnteredLine)
|
||||
{
|
||||
Debug.LogWarning($"[HoldNote] 阻止回收尚未进入判定线的 Start段: {noteColor}");
|
||||
Debug.LogWarning($"[HoldNote] 阻止回收尚未进入判定线的 Start段: {noteColor}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -632,9 +763,9 @@ public class HoldNote : BaseNote
|
||||
scheduledEndTime = 0f;
|
||||
hasEnteredLine = false;
|
||||
isJudged = false;
|
||||
isHoldActive = false; // 重置长按标记
|
||||
hasBeenHeldFromStart = false; // 重置
|
||||
_hasTriggeredOnThisHold = false; // 重置
|
||||
isHoldActive = false; // 重置长按标记
|
||||
hasBeenHeldFromStart = false; // 重置
|
||||
// _hasTriggeredOnThisHold = false; // 重置
|
||||
|
||||
if (autoReturnCoroutine != null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user