using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class DraggableUI : MonoBehaviour, IDragHandler, IPointerDownHandler { public RectTransform target; public Button button; private bool isLocked = false; private Vector3 _dragOffset; private float _dragScreenZ; private void Awake() { LockDrag(); } public void OnPointerDown(PointerEventData eventData) { if (isLocked) return; Camera cam = ResolveCamera(eventData); if (cam == null) return; // 记录指针与物体的世界空间偏移,避免拖动开始时物体跳到指针中心。 _dragScreenZ = cam.WorldToScreenPoint(transform.position).z; Vector3 pointerWorld = ScreenToWorld(cam, eventData.position, _dragScreenZ); _dragOffset = transform.position - pointerWorld; } public void OnDrag(PointerEventData eventData) { if (isLocked) return; Camera cam = ResolveCamera(eventData); if (cam == null) return; Vector3 pointerWorld = ScreenToWorld(cam, eventData.position, _dragScreenZ); Vector3 move = pointerWorld + _dragOffset; move.z = transform.position.z; transform.position = move; } void Update() { if (target == null || button == null) return; float distance = Vector3.Distance(transform.position, target.position); if (distance <= 1 && !isLocked) { button.interactable=true; } else { button.interactable=false; } } public void LockDrag() { isLocked = true; } public void UnlockDrag() { isLocked = false; } private static Camera ResolveCamera(PointerEventData eventData) { if (eventData != null && eventData.pressEventCamera != null) return eventData.pressEventCamera; return Camera.main; } private static Vector3 ScreenToWorld(Camera cam, Vector2 screenPosition, float screenZ) { return cam.ScreenToWorldPoint(new Vector3(screenPosition.x, screenPosition.y, screenZ)); } }