123 lines
3.6 KiB
C#
123 lines
3.6 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
|
|
public class NoteController : MonoBehaviour
|
|
{
|
|
private float speed;
|
|
private bool isMoving = true;
|
|
private bool isInJudgeZone = false; // 判定范围内
|
|
|
|
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<ParticleSystem>();
|
|
linkedNote = GetComponent<Note>();
|
|
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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configure timing for absolute position tracking.
|
|
/// Call this from NoteSpawner after the note is spawned.
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Query Note whether it's in judge zone
|
|
/// </summary>
|
|
public bool IsInJudgeZone()
|
|
{
|
|
return isInJudgeZone;
|
|
}
|
|
}
|