using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace BaseGames.World.Map { /// /// 全屏地图输入处理器(架构 15_MapShopModule §1.3.1)。 /// 挂在与 MapPanel 相同的 GameObject 上(MapPanel OnEnable/OnDisable 联动启停)。 /// /// 鼠标滚轮缩放(以鼠标位置为缩放中心) /// 键盘方向键 / WASD 平移 /// /// [RequireComponent(typeof(MapPanel))] public class MapInputHandler : MonoBehaviour, IScrollHandler { [SerializeField] private ScrollRect _scrollRect; [SerializeField] private RectTransform _zoomTarget; // 通常为 _roomContainer(格子根节点) [Header("缩放")] [SerializeField, Range(0.2f, 1f)] private float _zoomMin = 0.4f; [SerializeField, Range(1f, 5f)] private float _zoomMax = 3.0f; [SerializeField, Range(0.05f, 0.5f)] private float _zoomStep = 0.12f; [Header("键盘平移")] [SerializeField] private float _keyPanSpeed = 600f; // px / 秒 private float _zoom = 1f; private void OnEnable() { // 重新激活时还原缩放,避免上次关闭时的残留状态 if (_zoomTarget != null) _zoom = _zoomTarget.localScale.x; } private void Update() { if (_scrollRect == null) return; float h = Input.GetAxisRaw("Horizontal"); float v = Input.GetAxisRaw("Vertical"); if (h == 0 && v == 0) return; var delta = new Vector2(h, v) * (_keyPanSpeed * Time.unscaledDeltaTime); _scrollRect.content.anchoredPosition += delta; } // ── 鼠标滚轮缩放 ───────────────────────────────────────────────────── public void OnScroll(PointerEventData eventData) { if (_zoomTarget == null) return; float newZoom = Mathf.Clamp( _zoom + eventData.scrollDelta.y * _zoomStep, _zoomMin, _zoomMax); if (Mathf.Approximately(newZoom, _zoom)) return; // 将鼠标屏幕坐标转为 zoomTarget 本地坐标(缩放前) RectTransformUtility.ScreenPointToLocalPointInRectangle( _zoomTarget, eventData.position, eventData.pressEventCamera, out Vector2 pivotBefore); _zoom = newZoom; _zoomTarget.localScale = new Vector3(_zoom, _zoom, 1f); // 将同一屏幕点再次映射(缩放后),计算偏移量保持鼠标下方内容不动 RectTransformUtility.ScreenPointToLocalPointInRectangle( _zoomTarget, eventData.position, eventData.pressEventCamera, out Vector2 pivotAfter); // pivotAfter - pivotBefore 是 zoomTarget 本地空间的偏差,需转为父空间偏差 Vector2 offset = pivotAfter - pivotBefore; _zoomTarget.anchoredPosition += offset * _zoom; } } }