Files
bansonic_beta_main/Assets/scripts/gamePlay_gameplay/Note.cs
T

252 lines
8.2 KiB
C#

using UnityEngine;
public class Note : BaseNote
{
private KeyCode keyToPress;
private string noteColor;
private AnimationController anim;
private NoteController controller;
private bool isJudged = false;
private NoteData noteData;
[Header("ж")]
public NoteJudgeConfig judgeConfig; // жãԤʱֵ
// Cache allies per track to avoid GameObject.Find on every judge.
private static AllyCombatant[] allyCache;
private static AllyCombatant GetAllyForTrackCached(int trackIndex)
{
if (trackIndex < 0) return null;
if (allyCache == null || allyCache.Length < 10) allyCache = new AllyCombatant[10];
if (allyCache[trackIndex] != null) return allyCache[trackIndex];
var allyGo = GameObject.Find($"ally_0{trackIndex + 1}");
if (allyGo != null)
{
allyCache[trackIndex] = allyGo.GetComponent<AllyCombatant>();
}
return allyCache[trackIndex];
}
private void Awake()
{
anim = GetComponent<AnimationController>();
controller = GetComponent<NoteController>();
}
public void Setup(KeyCode key, int trackIndex, float speed, float hitTime, string color, NoteJudgeConfig judgeConfig, NoteData data)
{
keyToPress = key;
noteColor = color;
TrackIndex = trackIndex;
Speed = speed;
this.hitTime = hitTime;
isJudged = false;
this.judgeConfig = judgeConfig;
this.noteData = data;
if (controller != null)
{
controller.SetSpeed(speed);
}
InputManager.OnKeyPressed += HandlePress;
// жü
if (judgeConfig == null)
{
if (GameConfig.verboseLogs) Debug.LogError($"NoteJudgeConfig is null! жδ룡track={trackIndex}");
}
else
{
if (GameConfig.verboseLogs) Debug.Log($"NoteJudgeConfig: perfect={judgeConfig.perfectRange}, great={judgeConfig.greatRange}, good={judgeConfig.goodRange}, miss={judgeConfig.missRange}");
}
}
private void OnDestroy()
{
InputManager.OnKeyPressed -= HandlePress;
}
private void HandlePress(KeyCode key)
{
// ֻжȷж
if (isJudged || key != keyToPress || (controller != null && !controller.IsInJudgeZone()))
return;
float timeDifference = Mathf.Abs(Time.time - hitTime);
// ƫֵǰֵ
float rawOffsetMs = (hitTime - Time.time) * 1000f;
string judgeResult = null;
if (judgeConfig != null)
{
if (timeDifference <= judgeConfig.perfectRange)
{
if (GameConfig.verboseLogs) Debug.Log($"{keyToPress}: Perfect");
judgeResult = "Perfect";
ScoreManager.Instance.countPerfect += 1;
if (noteData != null) noteData.judgeOffsetMs = rawOffsetMs;
}
else if (timeDifference <= judgeConfig.greatRange)
{
if (GameConfig.verboseLogs) Debug.Log($"{keyToPress}: Great");
judgeResult = "Great";
ScoreManager.Instance.countGreat += 1;
if (noteData != null) noteData.judgeOffsetMs = rawOffsetMs;
}
else if (timeDifference <= judgeConfig.goodRange)
{
if (GameConfig.verboseLogs) Debug.Log($"{keyToPress}: Good");
judgeResult = "Good";
ScoreManager.Instance.countGood += 1;
if (noteData != null) noteData.judgeOffsetMs = rawOffsetMs;
}
else
{
if (GameConfig.verboseLogs) Debug.Log($"{keyToPress}: Miss");
judgeResult = "Miss";
}
}
else
{
// fallback timing
if (timeDifference <= 0.08f)
{
if (GameConfig.verboseLogs) Debug.Log($"{keyToPress}: Perfect");
judgeResult = "Perfect";
}
else if (timeDifference <= 0.15f)
{
if (GameConfig.verboseLogs) Debug.Log($"{keyToPress}: Great");
judgeResult = "Great";
}
else
{
if (GameConfig.verboseLogs) Debug.Log($"{keyToPress}: Miss");
judgeResult = "Miss";
}
}
if (!string.IsNullOrEmpty(judgeResult))
{
InputManager.Instance?.ShowJudgeResult(TrackIndex, judgeResult);
JudgeSoundManager.Instance?.PlayJudgeSound(judgeResult);
teamUIController.Instance?.OnJudgeResult(judgeResult);
Animation_GenerateJudgementSituationPrefab.Instance?.SpawnJudgePrefab(noteColor, judgeResult);
try
{
var ally = GetAllyForTrackCached(TrackIndex);
if (ally != null)
{
int added = ally.AddScoreForJudge(judgeResult);
float efficiency = ally.scoreEfficiency;
ScoreManager.Instance?.AddPmScoreForTrack(TrackIndex, added, efficiency);
}
}
catch (System.Exception ex)
{
Debug.LogWarning($"[Note] Failed to add per-track score: {ex}");
}
try { SkillBuilder.Instance?.NotifyNoteHit(TrackIndex, judgeResult, SkillDefinition.NoteTypeTrigger.Tap); } catch { }
}
Judge();
}
public bool IsJudged()
{
return isJudged;
}
public void Judge()
{
if (isJudged)
return;
isJudged = true;
if (controller != null)
{
controller.StopMovement();
controller.PlayHitEffect();
}
ReturnToPool();
if (anim != null)
{
anim.PlayDestroyAnimation(noteColor);
}
}
public void JudgeMiss()
{
// idempotent: this can be called from multiple paths
if (isJudged) return;
isJudged = true;
ScoreManager.Instance.countMiss += 1;
if (GameConfig.verboseLogs) Debug.Log($"{keyToPress} Miss");
InputManager.Instance?.ShowJudgeResult(TrackIndex, "Miss");
JudgeSoundManager.Instance?.PlayJudgeSound("Miss");
teamUIController.Instance?.OnJudgeResult("Miss");
Animation_GenerateJudgementSituationPrefab.Instance?.SpawnJudgePrefab(noteColor, "Miss");
try
{
var ally = GetAllyForTrackCached(TrackIndex);
if (ally != null)
{
int added = ally.AddScoreForJudge("Miss");
float efficiency = ally.scoreEfficiency;
ScoreManager.Instance?.AddPmScoreForTrack(TrackIndex, added, efficiency);
}
}
catch (System.Exception ex)
{
Debug.LogWarning($"[Note] Failed to add per-track score for Miss: {ex}");
}
try { SkillBuilder.Instance?.NotifyNoteHit(TrackIndex, "Miss", SkillDefinition.NoteTypeTrigger.Tap); } catch { }
ReturnToPool();
}
private void ReturnToPool()
{
InputManager.OnKeyPressed -= HandlePress;
if (controller != null)
{
controller.ResetState();
}
gameObject.SetActive(false);
NotePool.Instance.ReturnNote(gameObject, noteColor);
}
public int GetTrackIndex()
{
return TrackIndex;
}
public KeyCode GetKey()
{
return keyToPress;
}
/// <summary>
/// Controller ֪ͨ Note Ƿж
/// </summary>
public void SetJudgeZone(bool inZone)
{
// leaving judge zone without being judged -> Miss
if (!inZone)
{
// JudgeMiss already handles UI/sound and prevents double execution.
JudgeMiss();
}
}
}