diff --git a/Assets/Scripts/Interaction/PingClickHandler.cs b/Assets/Scripts/Interaction/PingClickHandler.cs index a06159d..22e8c02 100644 --- a/Assets/Scripts/Interaction/PingClickHandler.cs +++ b/Assets/Scripts/Interaction/PingClickHandler.cs @@ -50,32 +50,13 @@ public class PingClickHandler : MonoBehaviour while (true) { if (_outlineMesh != null) _outlineMesh.enabled = !_outlineMesh.enabled; yield return new WaitForSeconds(0.4f); } } - /// - /// 全新的点击检测方式:由一个静态方法统一管理,不再依赖碰撞体。 - /// 在 Update 里,遍历所有活跃的 PingClickHandler,找到离鼠标最近的那个,只触发它。 - /// void Update() { - // 只让 pingIndex 最小的那个实例来做全局检测,避免多个实例重复执行 + // 只有正在闪烁的 ping 才参与检测 if (!_isBlinking) return; - - // 只有一个实例负责全局判断 - var allHandlers = FindObjectsOfType(); - bool iAmFirst = true; - foreach (var h in allHandlers) - { - if (!h._isBlinking) continue; - if (h.GetInstanceID() < this.GetInstanceID()) - { - iAmFirst = false; - break; - } - } - if (!iAmFirst) return; - if (!Input.GetMouseButtonDown(0)) return; - // 不在 UI 上才检测 + // 如果点在 UI 上,不处理 if (UnityEngine.EventSystems.EventSystem.current != null && UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject()) return; @@ -91,36 +72,34 @@ public class PingClickHandler : MonoBehaviour } if (activeCamera == null) return; - // 遍历所有正在闪烁的 ping,找到距离鼠标最近的那个 - float bestDist = float.MaxValue; - PingClickHandler bestPing = null; + // 计算自己到鼠标的屏幕距离 + Vector3 screenPos = activeCamera.WorldToScreenPoint(transform.position); + if (screenPos.z < 0) return; // 在相机背后 Vector2 mousePos = Input.mousePosition; + float myDist = Vector2.Distance(mousePos, new Vector2(screenPos.x, screenPos.y)); + // 检查是否有其他正在闪烁的 ping 比我更近 + var allHandlers = FindObjectsOfType(); foreach (var h in allHandlers) { + if (h == this) continue; if (!h._isBlinking) continue; if (!h.gameObject.activeInHierarchy) continue; - Vector3 screenPos = activeCamera.WorldToScreenPoint(h.transform.position); + Vector3 otherScreen = activeCamera.WorldToScreenPoint(h.transform.position); + if (otherScreen.z < 0) continue; - // 如果在相机背后,跳过 - if (screenPos.z < 0) continue; - - float dist = Vector2.Distance(mousePos, new Vector2(screenPos.x, screenPos.y)); - if (dist < bestDist) - { - bestDist = dist; - bestPing = h; - } + float otherDist = Vector2.Distance(mousePos, new Vector2(otherScreen.x, otherScreen.y)); + if (otherDist < myDist) return; // 别人比我更近,让别人处理 } - // 点击半径阈值:80像素以内算点中(可以根据需要调整) - if (bestPing != null && bestDist < 80f) + // 我是离鼠标最近的闪烁中的 ping! + if (myDist < 80f) { - Debug.Log($"[PingClick] 屏幕坐标命中: {bestPing.name} (距离={bestDist:F1}px)"); - bestPing._isBlinking = false; - bestPing.PerformClick(); + Debug.Log($"[PingClick] 屏幕坐标命中: {name} (距离={myDist:F1}px)"); + _isBlinking = false; + PerformClick(); } } @@ -166,38 +145,15 @@ public class PingClickHandler : MonoBehaviour var sm = FindObjectOfType(); if (sm != null) sm.RecordPingStep(pingIndex, true); - var remainingPings = Object.FindObjectsOfType(); - int activePingCount = 0; - foreach (var p in remainingPings) - { - if (p._isBlinking || p._modelShown) activePingCount++; - } - - // 自己刚刚隐藏了,所以要减 1 看看还剩几个 - // 其实更准确的是检查 collider enabled,但现在我们不用 collider 了 - // 直接看有没有剩余的活跃 ping - bool allDone = true; - foreach (var p in Object.FindObjectsOfType()) - { - var c = p.GetComponent(); - // 如果还有没被隐藏的 ping(依然可见),就说明没完 - if (p.gameObject.activeInHierarchy && p._modelShown && !p._isBlinking) - { - // 这个 ping 已经完成了第一阶段但还没进入第二阶段 - // 不算完成 - } - } - - // 简单判定:遍历所有的 ping,看看是否还有 collider enabled 的 var pings = Object.FindObjectsOfType(); int remaining = 0; foreach (var p in pings) { - var col = p.GetComponent(); - if (col != null && col.enabled) remaining++; + if (p.gameObject.activeInHierarchy && (p._isBlinking || p._modelShown)) + remaining++; } - - if (remaining == 0) + // 自己刚刚 HideSelf 了,如果没有其他活跃的 ping 了 + if (remaining <= 1) { Debug.Log("[PingClick] 所有的 ping 都已经绑成 chanrao 了!播放完成语音。"); var am = FindObjectOfType(); @@ -281,7 +237,6 @@ public class PingClickHandler : MonoBehaviour public void ResetState() { _modelShown = false; - _isBlinking = true; if (_modelRenderer != null) _modelRenderer.enabled = false; foreach (var r in GetComponentsInChildren(true)) { if (_outlineMesh != null && r == _outlineMesh) continue; r.enabled = false; }