好多新内容

This commit is contained in:
FloatGaming
2026-07-22 05:35:53 +08:00
parent b5d1cdcbc5
commit 15649d02f8
128 changed files with 5956 additions and 673 deletions
@@ -9,6 +9,11 @@ public class NoteController : MonoBehaviour
private ParticleSystem hitEffect;
private Note linkedNote;
private bool useAbsolutePositioning = false;
// 去物理判定:用几何阈值复现原 Trigger 的进入/离开时刻。
private Collider2D _col;
private float _enterY, _exitY;
private bool _thresholdsReady;
// For absolute position tracking instead of relative translate
private Vector3 spawnPosition;
@@ -20,6 +25,12 @@ public class NoteController : MonoBehaviour
hitEffect = GetComponentInChildren<ParticleSystem>();
linkedNote = GetComponent<Note>();
spawnPosition = transform.position;
_col = GetComponent<Collider2D>();
// 去物理判定:判定改为几何驱动,音符不再需要 Physics2D 模拟。
// 关闭 Rigidbody2D 模拟,消除每帧移动 kinematic 刚体触发的物理同步/重叠检测开销。
// 保留 Collider 组件本身(仅用于读取其 bounds 计算阈值,不参与物理)。
var rb = GetComponent<Rigidbody2D>();
if (rb != null) rb.simulated = false;
}
private void Update()
@@ -29,12 +40,41 @@ public class NoteController : MonoBehaviour
// Use absolute positioning based on elapsed time since activation
float elapsedSinceActivation = GameplayClock.NowSongTime - activationTime;
float travelDistance = speed * Mathf.Max(0f, elapsedSinceActivation);
// Position = spawnPoint + initial offset + downward travel
Vector3 newPos = spawnPosition;
newPos.y -= (baseSpawnYOffset + travelDistance);
transform.position = newPos;
}
// 去物理判定:用音符 Y 与阈值的比较复现 OnTriggerEnter2D/Exit2D 的进入/离开时刻。
UpdateJudgeZoneByGeometry();
}
private void UpdateJudgeZoneByGeometry()
{
if (linkedNote == null) return;
if (!_thresholdsReady)
{
// 判定线捕获后,用音符自身 collider 计算进入/离开阈值(只算一次)。
if (!JudgeZoneGeometry.LineReady) return;
if (!JudgeZoneGeometry.TryGetThresholds(_col, transform, out _enterY, out _exitY)) return;
_thresholdsReady = true;
}
float noteY = transform.position.y;
// 进入:noteY 下降到 ≤ enterY 且尚未进入。
if (!isInJudgeZone && noteY <= _enterY)
{
EnterJudgeZone();
// 单帧穿透(帧尖峰导致一帧内越过整个判定区):立即补一次离开,行为与物理一致。
if (noteY <= _exitY) ExitJudgeZone();
}
// 离开:noteY 继续下降到 ≤ exitY 且当前在区内。
else if (isInJudgeZone && noteY <= _exitY)
{
ExitJudgeZone();
}
}
public void SetSpeed(float newSpeed)
@@ -89,6 +129,7 @@ public class NoteController : MonoBehaviour
baseSpawnYOffset = 0f;
spawnPosition = transform.position;
useAbsolutePositioning = false;
_thresholdsReady = false; // 池化复用:下次重新计算阈值。
if (hitEffect != null)
{
@@ -97,31 +138,23 @@ public class NoteController : MonoBehaviour
}
}
private void OnTriggerEnter2D(Collider2D collision)
// 进入判定区(原 OnTriggerEnter2D 逻辑,保持完全一致)。
private void EnterJudgeZone()
{
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);
}
}
if (linkedNote == null) return;
isInJudgeZone = true;
// register note by instance id so TrackKeyManager can prioritize
// tap notes are short notes without hold
TrackKeyManager.Instance.RegisterKey(linkedNote.GetTrackIndex(), linkedNote.GetCachedInstanceId(), "tap", linkedNote.HitTime);
}
private void OnTriggerExit2D(Collider2D collision)
// 离开判定区(原 OnTriggerExit2D 逻辑,保持完全一致)。
private void ExitJudgeZone()
{
if (collision.CompareTag("JudgmentLine"))
{
if (linkedNote != null)
{
isInJudgeZone = false;
TrackKeyManager.Instance.UnregisterKey(linkedNote.GetTrackIndex(), linkedNote.gameObject.GetInstanceID().ToString());
linkedNote.SetJudgeZone(isInJudgeZone);
}
}
if (linkedNote == null) return;
isInJudgeZone = false;
TrackKeyManager.Instance.UnregisterKey(linkedNote.GetTrackIndex(), linkedNote.GetCachedInstanceId());
linkedNote.SetJudgeZone(isInJudgeZone);
}
/// <summary>