Fix: each ping does its own closest-check instead of broken global delegate pattern
This commit is contained in:
@@ -50,32 +50,13 @@ public class PingClickHandler : MonoBehaviour
|
||||
while (true) { if (_outlineMesh != null) _outlineMesh.enabled = !_outlineMesh.enabled; yield return new WaitForSeconds(0.4f); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 全新的点击检测方式:由一个静态方法统一管理,不再依赖碰撞体。
|
||||
/// 在 Update 里,遍历所有活跃的 PingClickHandler,找到离鼠标最近的那个,只触发它。
|
||||
/// </summary>
|
||||
void Update()
|
||||
{
|
||||
// 只让 pingIndex 最小的那个实例来做全局检测,避免多个实例重复执行
|
||||
// 只有正在闪烁的 ping 才参与检测
|
||||
if (!_isBlinking) return;
|
||||
|
||||
// 只有一个实例负责全局判断
|
||||
var allHandlers = FindObjectsOfType<PingClickHandler>();
|
||||
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<PingClickHandler>();
|
||||
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<StepManager>();
|
||||
if (sm != null) sm.RecordPingStep(pingIndex, true);
|
||||
|
||||
var remainingPings = Object.FindObjectsOfType<PingClickHandler>();
|
||||
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<PingClickHandler>())
|
||||
{
|
||||
var c = p.GetComponent<Collider>();
|
||||
// 如果还有没被隐藏的 ping(依然可见),就说明没完
|
||||
if (p.gameObject.activeInHierarchy && p._modelShown && !p._isBlinking)
|
||||
{
|
||||
// 这个 ping 已经完成了第一阶段但还没进入第二阶段
|
||||
// 不算完成
|
||||
}
|
||||
}
|
||||
|
||||
// 简单判定:遍历所有的 ping,看看是否还有 collider enabled 的
|
||||
var pings = Object.FindObjectsOfType<PingClickHandler>();
|
||||
int remaining = 0;
|
||||
foreach (var p in pings)
|
||||
{
|
||||
var col = p.GetComponent<Collider>();
|
||||
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<AudioManager>();
|
||||
@@ -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<Renderer>(true)) { if (_outlineMesh != null && r == _outlineMesh) continue; r.enabled = false; }
|
||||
|
||||
Reference in New Issue
Block a user