From f307c83352728faa398b58773761e82eeb375409 Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 5 Nov 2026 16:58:12 +0100 Subject: [PATCH] =?UTF-8?q?3D:=20=D0=BD=D0=B0=D0=B6=D0=B0=D1=82=D0=B8?= =?UTF-8?q?=D0=B5=20=C2=AB=D0=BF=D0=BE=20HUD=C2=BB=20--=20=D1=82=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BF=D0=BE=20=D0=BA=D0=BD=D0=BE?= =?UTF-8?q?=D0=BF=D0=BA=D0=B0=D0=BC,=20=D0=BF=D1=80=D0=BE=D0=BA=D1=80?= =?UTF-8?q?=D1=83=D1=82=D0=BA=D0=B5=20=D0=B8=20=D0=BD=D0=B5=D0=B1=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D1=88=D0=B8=D0=BC=20=D0=BF=D0=B0=D0=BD=D0=B5=D0=BB?= =?UTF-8?q?=D1=8F=D0=BC;=20=D0=BD=D0=B5=D0=B2=D0=B8=D0=B4=D0=B8=D0=BC?= =?UTF-8?q?=D1=8B=D0=B9=20=D1=81=D0=BB=D0=BE=D0=B9=20=D0=B2=D0=BE=20=D0=B2?= =?UTF-8?q?=D0=B5=D1=81=D1=8C=20=D1=8D=D0=BA=D1=80=D0=B0=D0=BD=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=B8=D1=80=D1=83=D0=B5=D1=82?= =?UTF-8?q?=20=D0=BA=D0=B0=D1=80=D1=82=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Тап, перетаскивание, стройка и зум в 3D-поселении блокировались проверкой UIBlocker. Такой слой и открытая панель HUD пишутся в Console один раз -- чтобы найти виновника. Co-Authored-By: Claude Opus 5.5 --- Assets/Scripts/City3D/City3DCamera.cs | 2 +- Assets/Scripts/City3D/City3DController.cs | 2 +- Assets/Scripts/City3D/City3DInput.cs | 66 +++++++++++++++++++++++ Assets/Scripts/City3D/City3DInput.cs.meta | 11 ++++ 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 Assets/Scripts/City3D/City3DInput.cs create mode 100644 Assets/Scripts/City3D/City3DInput.cs.meta diff --git a/Assets/Scripts/City3D/City3DCamera.cs b/Assets/Scripts/City3D/City3DCamera.cs index b46a694..1211385 100644 --- a/Assets/Scripts/City3D/City3DCamera.cs +++ b/Assets/Scripts/City3D/City3DCamera.cs @@ -66,7 +66,7 @@ public class City3DCamera : MonoBehaviour { // Колесо мыши (редактор, ПК) float wheel = Input.mouseScrollDelta.y; - if (UIBlocker.IsPointerOverUI()) wheel = 0f; // колесо над окнами HUD -- не приближать камеру (05.11) + if (City3DInput.OverHud(Input.mousePosition)) wheel = 0f; // колесо над окнами HUD -- не приближать камеру (05.11) if (Mathf.Abs(wheel) > 0.01f) Zoom(wheel * 0.1f); // Два пальца -- приближение, как на карте мира: расстояние камеры меняется во столько раз, diff --git a/Assets/Scripts/City3D/City3DController.cs b/Assets/Scripts/City3D/City3DController.cs index 36ca5d2..c0da680 100644 --- a/Assets/Scripts/City3D/City3DController.cs +++ b/Assets/Scripts/City3D/City3DController.cs @@ -695,7 +695,7 @@ public class City3DController : MonoBehaviour, City3DSave.ILive if (down) { - pointerOverGui = OverGui(pos) || UIBlocker.IsPointerOverUI(); // и кнопки/окна общего HUD + pointerOverGui = OverGui(pos) || City3DInput.OverHud(pos); // и кнопки/окна общего HUD if (pointerOverGui) return; pointerDown = pos; pointerMoved = false; diff --git a/Assets/Scripts/City3D/City3DInput.cs b/Assets/Scripts/City3D/City3DInput.cs new file mode 100644 index 0000000..e4e7ac4 --- /dev/null +++ b/Assets/Scripts/City3D/City3DInput.cs @@ -0,0 +1,66 @@ +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; + } +} diff --git a/Assets/Scripts/City3D/City3DInput.cs.meta b/Assets/Scripts/City3D/City3DInput.cs.meta new file mode 100644 index 0000000..bb13970 --- /dev/null +++ b/Assets/Scripts/City3D/City3DInput.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c71f24a7cb164064b98f198eec9665d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: