using System.Collections; using UnityEngine; public class NoteController : MonoBehaviour { private float speed; private bool isMoving = true; private bool isInJudgeZone = false; // Documentation text normalized. private ParticleSystem hitEffect; private Note linkedNote; // For absolute position tracking instead of relative translate private Vector3 spawnPosition; private float activationTime = -1f; // When the note should start moving (hitTime - travelTime) private float baseSpawnYOffset = 0f; // Initial Y offset from compensation at spawn time private void Awake() { hitEffect = GetComponentInChildren(); linkedNote = GetComponent(); spawnPosition = transform.position; } private void Update() { if (isMoving && activationTime >= 0f) { // Use absolute positioning based on elapsed time since activation float elapsedSinceActivation = Time.time - activationTime; float travelDistance = speed * Mathf.Max(0f, elapsedSinceActivation); // Position = spawnPoint + initial offset + downward travel Vector3 newPos = spawnPosition; newPos.y -= (baseSpawnYOffset + travelDistance); transform.position = newPos; } } public void SetSpeed(float newSpeed) { speed = newSpeed; } public void StopMovement() { isMoving = false; } public void PlayHitEffect() { if (hitEffect != null) { hitEffect.Play(); } } /// /// Configure timing for absolute position tracking. /// Call this from NoteSpawner after the note is spawned. /// public void ConfigureAbsolutePositioning(Vector3 initialSpawnPos, float hitTime, float travelTime, float initialYOffset) { spawnPosition = initialSpawnPos; activationTime = hitTime - travelTime; baseSpawnYOffset = initialYOffset; if (JudgeManager.IsDebugEnabled) Debug.Log($"[NoteController] Configured: spawnPos={spawnPosition}, activationTime={activationTime:F3}, initialYOffset={initialYOffset:F4}"); } public void ResetState() { speed = 0f; isMoving = true; isInJudgeZone = false; activationTime = -1f; baseSpawnYOffset = 0f; spawnPosition = transform.position; if (hitEffect != null) { hitEffect.Stop(); hitEffect.Clear(); } } private void OnTriggerEnter2D(Collider2D collision) { if (collision.CompareTag("JudgmentLine")) { if (linkedNote != null) { isInJudgeZone = true; // register note by instance id so TrackKeyManager can prioritize // tap notes are short notes without hold TrackKeyManager.Instance.RegisterKey(linkedNote.GetTrackIndex(), linkedNote.gameObject.GetInstanceID().ToString(), "tap", linkedNote.HitTime); } } } private void OnTriggerExit2D(Collider2D collision) { if (collision.CompareTag("JudgmentLine")) { if (linkedNote != null) { isInJudgeZone = false; TrackKeyManager.Instance.UnregisterKey(linkedNote.GetTrackIndex(), linkedNote.gameObject.GetInstanceID().ToString()); linkedNote.SetJudgeZone(isInJudgeZone); } } } /// /// Query Note whether it's in judge zone /// public bool IsInJudgeZone() { return isInJudgeZone; } }