From 51fe94b3e1fe573d841b0907db82ae5761687c0f Mon Sep 17 00:00:00 2001 From: yangbear Date: Sun, 12 Jul 2026 04:07:20 +0800 Subject: [PATCH] Replace OnMouseDown with Physics.RaycastAll in Update for guaranteed click penetration --- .../Scripts/Interaction/PingClickHandler.cs | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/Assets/Scripts/Interaction/PingClickHandler.cs b/Assets/Scripts/Interaction/PingClickHandler.cs index 7a83bde..7dd1556 100644 --- a/Assets/Scripts/Interaction/PingClickHandler.cs +++ b/Assets/Scripts/Interaction/PingClickHandler.cs @@ -21,27 +21,11 @@ public class PingClickHandler : MonoBehaviour { col = gameObject.AddComponent(); } - - // 强行把碰撞体的世界大小固定在一个比较合适的尺寸(比如世界尺寸 0.15) - // 注意:父级如果在很远的层级里存在极端缩放,这里直接算可能还会出问题 - // 所以我们加一个更保守的安全保障:无论算出什么比例,绝对物理半径不能低于 0.05,不能高于 5.0 - float scale = Mathf.Max(Mathf.Abs(transform.lossyScale.x), Mathf.Abs(transform.lossyScale.y), Mathf.Abs(transform.lossyScale.z), 0.001f); - if (col is SphereCollider sphere) { - float targetRadius = 0.3f / scale; - // 如果缩放太小,导致计算出的局部半径极大,或者缩放太大导致半径极小,我们要Clamp住它 - // 以保证在 Scene/Game 视窗里它至少是个“可以点得到的球” - sphere.radius = Mathf.Clamp(targetRadius, 0.05f, 20f); - Debug.Log($"[PingClick] {name} 设置了碰撞体半径: {sphere.radius} (基于缩放 {scale})"); + float scale = Mathf.Max(Mathf.Abs(transform.lossyScale.x), Mathf.Abs(transform.lossyScale.y), Mathf.Abs(transform.lossyScale.z), 0.001f); + sphere.radius = Mathf.Clamp(0.3f / scale, 0.05f, 20f); } - else if (col is BoxCollider box) - { - float targetSize = 0.6f / scale; - targetSize = Mathf.Clamp(targetSize, 0.1f, 40f); - box.size = new Vector3(targetSize, targetSize, targetSize); - } - col.enabled = true; CreateOutlineMesh(); @@ -78,21 +62,35 @@ public class PingClickHandler : MonoBehaviour while (true) { if (_outlineMesh != null) _outlineMesh.enabled = !_outlineMesh.enabled; yield return new WaitForSeconds(0.4f); } } - void OnMouseDown() + // 弃用 Unity 自带的 OnMouseDown,因为它只能检测最外层第一个碰到的物体,会被前面的隐形物体挡住 + void Update() { - Debug.Log($"[PingClick] 接收到鼠标点击: {name}"); - PerformClick(); + if (Input.GetMouseButtonDown(0)) + { + if (!_isBlinking) return; + + foreach (var c in Camera.allCameras) + { + if (!c.enabled) continue; + Ray ray = c.ScreenPointToRay(Input.mousePosition); + // 穿透所有物体! + RaycastHit[] hits = Physics.RaycastAll(ray, 1000f); + foreach (var hit in hits) + { + if (hit.collider != null && hit.collider.gameObject == gameObject) + { + Debug.Log($"[PingClick] Update全穿透射线成功点中: {name}"); + PerformClick(); + return; // 已经处理点击,退出 + } + } + } + } } public void PerformClick() { - if (!_isBlinking) - { - Debug.Log($"[PingClick] {name} 忽略点击,因为 _isBlinking=false"); - return; - } - - // 不做任何射线遮挡判定!直接穿透触发点击,确保 100% 成功! + if (!_isBlinking) return; if (!_modelShown) {