好多新内容

This commit is contained in:
2026-07-22 05:35:53 +08:00
parent b5d1cdcbc5
commit 15649d02f8
128 changed files with 5956 additions and 673 deletions
@@ -68,6 +68,11 @@ public class TrackTouchInput : MonoBehaviour
private void Update()
{
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
// Windows 平台:禁用轨道点击/触摸轮询,只依赖按键输入。
// 编辑器(Win)也一并禁用,便于在 PC 上以键盘方式测试真实 Windows 行为。
return;
#else
var im = InputManager.Instance;
if (im == null) return;
@@ -80,6 +85,7 @@ public class TrackTouchInput : MonoBehaviour
{
ProcessMouse(im, cam);
}
#endif
}
/// <summary>处理所有并发触点,返回本帧触点数量。</summary>
@@ -198,6 +204,7 @@ public class TrackTouchInput : MonoBehaviour
/// </summary>
private int ResolveTrack(Camera cam, Vector2 screenPos)
{
EnsureOverlapFilter();
Vector2 point;
if (forceOrthographicMode || cam.orthographic)
@@ -222,12 +229,58 @@ public class TrackTouchInput : MonoBehaviour
point = new Vector2(world.x, world.y);
}
Collider2D hit = Physics2D.OverlapPoint(point, hitLayers);
if (hit == null) return -1;
// 用 OverlapPointAll 遍历所有命中的碰撞体,挑出带 TrackTouchZone 的那个。
// 关键修复:判定线附近同一屏幕点常密集着 note 的 Collider2D 与 judgeline 触发器,
// 单值版 OverlapPoint 只返回其中一个,若不是 tap zone 就丢判定(=点了轨道却没反应)。
// 遍历全部命中即可穿透这些遮挡,可靠找到轨道点击区。
int count = Physics2D.OverlapPoint(point, _overlapFilter, _overlapResults);
for (int i = 0; i < count; i++)
{
Collider2D hit = _overlapResults[i];
if (hit == null) continue;
TrackTouchZone zone = hit.GetComponent<TrackTouchZone>();
if (zone == null) zone = hit.GetComponentInParent<TrackTouchZone>();
if (zone != null) return zone.trackIndex;
}
TrackTouchZone zone = hit.GetComponent<TrackTouchZone>();
if (zone == null) zone = hit.GetComponentInParent<TrackTouchZone>();
return zone != null ? zone.trackIndex : -1;
// 兜底:没有精确命中任何 zone(点落在轨道间缝隙或紧邻边缘)。
// 取横向最近的 zone,只要触点在其 Collider 的纵向范围内即算命中——
// 等效于把相邻轨道点击区在横向补满、消除缝隙,且不误触远离轨道区的点击。
return ResolveNearestZone(point);
}
// 横向最近轨道兜底:在所有 zone 中找触点纵向落在其包围盒内、且横向距离最近的一个。
private int ResolveNearestZone(Vector2 point)
{
var zones = TrackTouchZone.All;
int best = -1;
float bestDist = float.MaxValue;
for (int i = 0; i < zones.Count; i++)
{
TrackTouchZone z = zones[i];
if (z == null || z.Collider == null) continue;
Bounds b = z.Collider.bounds;
// 纵向必须落在该点击区范围内(留一点容差),避免点屏幕别处也触发轨道。
if (point.y < b.min.y - 0.1f || point.y > b.max.y + 0.1f) continue;
float dx = Mathf.Abs(point.x - b.center.x);
if (dx < bestDist) { bestDist = dx; best = z.trackIndex; }
}
return best;
}
// OverlapPoint 的复用缓冲与过滤器(避免每次触摸分配 GC)。
private static readonly Collider2D[] _overlapResults = new Collider2D[16];
private ContactFilter2D _overlapFilter;
private bool _filterReady;
private void EnsureOverlapFilter()
{
if (_filterReady) return;
_overlapFilter = new ContactFilter2D();
_overlapFilter.useLayerMask = true;
_overlapFilter.SetLayerMask(hitLayers);
_overlapFilter.useTriggers = true; // tap zone 可能是触发器,需包含
_filterReady = true;
}
private void OnDisable()