using System; using System.Collections.Generic; using Dreamteck.Splines; using Ichni.RhythmGame.Beatmap; using Lean.Pool; using Unity.VisualScripting; namespace Ichni.RhythmGame { public class Tap : NoteBase { #region [生成与初始化] Generation & Initialization public static Tap GenerateElement(string elementName, Guid id, List tags, bool isFirstGenerated, GameElement parentElement, float exactJudgeTime) { Tap tap = LeanPool.Spawn(GameManager.Instance.basePrefabs.tapNote, parentElement.transform).GetComponent(); tap.Initialize(elementName, id, tags, isFirstGenerated, parentElement); tap.exactJudgeTime = exactJudgeTime; tap.judgeIntervals = NoteJudgeIntervals.TapDefault; // 接入了你改好的享元单例 if (parentElement.TryGetComponent(out Track track) && track.trackTimeSubmodule != null) { tap.track = track; tap.trackPositioner.enabled = true; tap.trackPositioner.spline = track.trackPathSubmodule.path; tap.isOnTrack = true; tap.UpdateNoteInTrack(CoreServices.TimeProvider.SongTime); } else { tap.track = null; tap.isOnTrack = false; } return tap; } public override void SetDefaultSubmodules() { base.SetDefaultSubmodules(); NoteAudioSubmodule = new NoteAudioSubmodule(this, "DefaultTap"); } #endregion #region [主循环阶段] Main Update public override bool ManualUpdate(float currentSongTime) { if (!isFirstJudged && !isDuringJudging && currentSongTime >= exactJudgeTime + judgeIntervals.beforeMiss.intervalStart && !GameManager.Instance.noteJudgeManager.checkingTapList.Contains(this)) { isDuringJudging = true; GameManager.Instance.noteJudgeManager.checkingTapList.Add(this); } return base.ManualUpdate(currentSongTime); } protected override void RemoveFromCheckingList() { if (GameManager.Instance.noteJudgeManager.checkingTapList.Contains(this)) GameManager.Instance.noteJudgeManager.checkingTapList.Remove(this); } #endregion #region [核心判定逻辑] Judgement Logic public bool CheckJudgeAvailability(InputUnitTap inputUnitTap) { foreach (var judgeUnit in NoteJudgeSubmodule.judgeUnitList) { if (!judgeUnit.CheckJudgeAvailability(inputUnitTap)) return false; } return true; } protected override NoteJudgeType GetStartJudgeType(float timeDifference) => judgeIntervals.GetNoteJudgeType(timeDifference); public override void ExecuteStartJudge(float triggerTime) { RemoveFromCheckingList(); float timeDifference = triggerTime - exactJudgeTime; NoteJudgeType startJudgeType = GetStartJudgeType(timeDifference); GameManager.Instance.playingRecorder.resultData.Add(timeDifference); switch (startJudgeType) { case NoteJudgeType.Perfect: Perfect(triggerTime); break; case NoteJudgeType.Good: Good(triggerTime); break; case NoteJudgeType.Bad: Bad(triggerTime); break; case NoteJudgeType.Miss: Miss(triggerTime); break; } if (startJudgeType != NoteJudgeType.Miss) NoteAudioSubmodule.PlayGeneralJudgeAudios(); isFirstJudged = true; isFinalJudged = true; } #endregion #region [谱面功能] Beatmap Method #endregion } }