using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; // Палец над HUD в 3D-поселении (05.11): «над интерфейсом» -- только если под пальцем то, что нажимают или крутят // (кнопка, поле, ползунок, прокручиваемое окно) или небольшая панель. Невидимый слой во весь экран // (затемнение, контейнер безопасной зоны, фон) карту не блокирует -- иначе не работают ни тап, ни зум, ни стройка. // Такой слой пишется в Console один раз, чтобы его можно было найти и убрать. public static class City3DInput { static readonly List hits = new List(); static readonly HashSet reported = new HashSet(); public static bool OverHud(Vector2 screen) { var es = EventSystem.current; if (es == null) return false; // Открыто окно HUD (панель) -- весь ввод его, карта не трогается if (UIPanelManager.Instance != null && UIPanelManager.Instance.CurrentId != "") { if (reported.Add("panel:" + UIPanelManager.Instance.CurrentId)) Debug.Log($"[3D] Открыта панель HUD «{UIPanelManager.Instance.CurrentId}» -- 3D-карта не принимает нажатия, пока её не закрыть"); return true; } hits.Clear(); es.RaycastAll(new PointerEventData(es) { position = screen }, hits); foreach (var h in hits) { if (h.gameObject == null) continue; if (IsInteractive(h.gameObject) || !CoversScreen(h.gameObject)) return true; if (reported.Add(h.gameObject.name)) Debug.Log($"[3D] Слой интерфейса во весь экран ловит нажатия, 3D-карта его пропускает: «{Path(h.gameObject.transform)}». " + "Если он не нужен -- выключить у него Raycast Target"); } return false; } static bool IsInteractive(GameObject go) { // кнопки, прокрутка, поля, а также всё, что само ловит нажатие (затемнение модального окна закрывает его тапом) return go.GetComponentInParent() != null || go.GetComponentInParent() != null || go.GetComponentInParent() != null || go.GetComponentInParent() != null || go.name == "Modal" || go.GetComponentInParent() != null; } // Занимает почти весь экран (больше 80% по ширине и высоте) static bool CoversScreen(GameObject go) { if (!(go.transform is RectTransform rt)) return false; var corners = new Vector3[4]; rt.GetWorldCorners(corners); var canvas = go.GetComponentInParent(); Camera cam = canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay ? canvas.worldCamera : null; Vector2 a = RectTransformUtility.WorldToScreenPoint(cam, corners[0]); Vector2 b = RectTransformUtility.WorldToScreenPoint(cam, corners[2]); return Mathf.Abs(b.x - a.x) > Screen.width * 0.8f && Mathf.Abs(b.y - a.y) > Screen.height * 0.8f; } static string Path(Transform t) { string p = t.name; for (var x = t.parent; x != null; x = x.parent) p = x.name + "/" + p; return p; } }